Add Zulip webhook handler workflow for n8n
This commit is contained in:
281
workflows/zulip-webhook-handler.json
Normal file
281
workflows/zulip-webhook-handler.json
Normal file
@@ -0,0 +1,281 @@
|
||||
{
|
||||
"name": "Zulip Command Handler",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {
|
||||
"httpMethod": "POST",
|
||||
"path": "zulip-commands",
|
||||
"responseMode": "responseNode",
|
||||
"options": {}
|
||||
},
|
||||
"id": "webhook-zulip",
|
||||
"name": "Zulip Webhook",
|
||||
"type": "n8n-nodes-base.webhook",
|
||||
"typeVersion": 2,
|
||||
"position": [240, 300]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "// Parse Zulip webhook payload
|
||||
const body = $input.first().json.body || $input.first().json;
|
||||
|
||||
// Extract message content
|
||||
const message = body.message || {};
|
||||
const content = message.content || body.data || \"\";
|
||||
const senderEmail = message.sender_email || body.user_email || \"unknown\";
|
||||
const stream = message.display_recipient || body.stream || \"general\";
|
||||
const topic = message.subject || body.topic || \"general\";
|
||||
|
||||
// Parse command: /category action args
|
||||
const match = content.match(/^\/(\w+)(?:\s+(\w+))?(?:\s+(.+))?$/);
|
||||
|
||||
if (\!match) {
|
||||
return [{
|
||||
json: {
|
||||
isCommand: false,
|
||||
rawContent: content,
|
||||
sender: senderEmail,
|
||||
stream: stream,
|
||||
topic: topic,
|
||||
error: \"Not a valid command format. Use /category action [args]\"
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
return [{
|
||||
json: {
|
||||
isCommand: true,
|
||||
category: match[1],
|
||||
action: match[2] || \"default\",
|
||||
args: match[3] || \"\",
|
||||
sender: senderEmail,
|
||||
stream: stream,
|
||||
topic: topic,
|
||||
rawContent: content
|
||||
}
|
||||
}];"
|
||||
},
|
||||
"id": "parse-command",
|
||||
"name": "Parse Zulip Command",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [460, 300]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"conditions": {
|
||||
"boolean": [
|
||||
{
|
||||
"value1": "={{ $json.isCommand }}",
|
||||
"value2": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"id": "is-command",
|
||||
"name": "Is Valid Command?",
|
||||
"type": "n8n-nodes-base.if",
|
||||
"typeVersion": 2,
|
||||
"position": [680, 300]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"rules": {
|
||||
"values": [
|
||||
{"value": "project", "output": 0},
|
||||
{"value": "code", "output": 1},
|
||||
{"value": "deploy", "output": 2},
|
||||
{"value": "sprint", "output": 3},
|
||||
{"value": "dt", "output": 4},
|
||||
{"value": "design", "output": 5}
|
||||
]
|
||||
},
|
||||
"fallbackOutput": 6,
|
||||
"options": {},
|
||||
"dataPropertyName": "={{ $json.category }}"
|
||||
},
|
||||
"id": "route-command",
|
||||
"name": "Route by Category",
|
||||
"type": "n8n-nodes-base.switch",
|
||||
"typeVersion": 3,
|
||||
"position": [900, 200]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "https://gitea.mylder.io/admin/skills-library/raw/branch/main/skills/project/create.md",
|
||||
"options": {}
|
||||
},
|
||||
"id": "load-project-skill",
|
||||
"name": "Load Project Skill",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4,
|
||||
"position": [1120, 0]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "https://gitea.mylder.io/admin/skills-library/raw/branch/main/skills/code/review.md",
|
||||
"options": {}
|
||||
},
|
||||
"id": "load-code-skill",
|
||||
"name": "Load Code Skill",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4,
|
||||
"position": [1120, 100]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "https://gitea.mylder.io/admin/skills-library/raw/branch/main/skills/deploy/preview.md",
|
||||
"options": {}
|
||||
},
|
||||
"id": "load-deploy-skill",
|
||||
"name": "Load Deploy Skill",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4,
|
||||
"position": [1120, 200]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "https://gitea.mylder.io/admin/skills-library/raw/branch/main/skills/sprint/plan.md",
|
||||
"options": {}
|
||||
},
|
||||
"id": "load-sprint-skill",
|
||||
"name": "Load Sprint Skill",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4,
|
||||
"position": [1120, 300]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "https://gitea.mylder.io/admin/skills-library/raw/branch/main/skills/design-thinking/ideate.md",
|
||||
"options": {}
|
||||
},
|
||||
"id": "load-dt-skill",
|
||||
"name": "Load Design Thinking Skill",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4,
|
||||
"position": [1120, 400]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "// Handle unknown command
|
||||
return [{
|
||||
json: {
|
||||
response: \"Unknown command category. Available: /project, /code, /deploy, /sprint, /dt, /design\",
|
||||
isError: true
|
||||
}
|
||||
}];"
|
||||
},
|
||||
"id": "unknown-command",
|
||||
"name": "Unknown Command",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [1120, 600]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "// Format response for Zulip
|
||||
const data = $input.first().json;
|
||||
|
||||
let response = data.response || data.error || \"Command processed\";
|
||||
|
||||
// Zulip expects { content: \"message\" } format
|
||||
return [{
|
||||
json: {
|
||||
content: response
|
||||
}
|
||||
}];"
|
||||
},
|
||||
"id": "format-response",
|
||||
"name": "Format Zulip Response",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [1540, 300]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"respondWith": "json",
|
||||
"responseBody": "={{ $json }}",
|
||||
"options": {}
|
||||
},
|
||||
"id": "respond-webhook",
|
||||
"name": "Respond to Zulip",
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"typeVersion": 1,
|
||||
"position": [1760, 300]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "// Error response for invalid command
|
||||
const data = $input.first().json;
|
||||
|
||||
return [{
|
||||
json: {
|
||||
content: data.error || \"Invalid command format. Use: /category action [args]\"
|
||||
}
|
||||
}];"
|
||||
},
|
||||
"id": "error-response",
|
||||
"name": "Error Response",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [900, 460]
|
||||
}
|
||||
],
|
||||
"connections": {
|
||||
"Zulip Webhook": {
|
||||
"main": [[{"node": "Parse Zulip Command", "type": "main", "index": 0}]]
|
||||
},
|
||||
"Parse Zulip Command": {
|
||||
"main": [[{"node": "Is Valid Command?", "type": "main", "index": 0}]]
|
||||
},
|
||||
"Is Valid Command?": {
|
||||
"main": [
|
||||
[{"node": "Route by Category", "type": "main", "index": 0}],
|
||||
[{"node": "Error Response", "type": "main", "index": 0}]
|
||||
]
|
||||
},
|
||||
"Route by Category": {
|
||||
"main": [
|
||||
[{"node": "Load Project Skill", "type": "main", "index": 0}],
|
||||
[{"node": "Load Code Skill", "type": "main", "index": 0}],
|
||||
[{"node": "Load Deploy Skill", "type": "main", "index": 0}],
|
||||
[{"node": "Load Sprint Skill", "type": "main", "index": 0}],
|
||||
[{"node": "Load Design Thinking Skill", "type": "main", "index": 0}],
|
||||
[{"node": "Load Design Thinking Skill", "type": "main", "index": 0}],
|
||||
[{"node": "Unknown Command", "type": "main", "index": 0}]
|
||||
]
|
||||
},
|
||||
"Load Project Skill": {
|
||||
"main": [[{"node": "Format Zulip Response", "type": "main", "index": 0}]]
|
||||
},
|
||||
"Load Code Skill": {
|
||||
"main": [[{"node": "Format Zulip Response", "type": "main", "index": 0}]]
|
||||
},
|
||||
"Load Deploy Skill": {
|
||||
"main": [[{"node": "Format Zulip Response", "type": "main", "index": 0}]]
|
||||
},
|
||||
"Load Sprint Skill": {
|
||||
"main": [[{"node": "Format Zulip Response", "type": "main", "index": 0}]]
|
||||
},
|
||||
"Load Design Thinking Skill": {
|
||||
"main": [[{"node": "Format Zulip Response", "type": "main", "index": 0}]]
|
||||
},
|
||||
"Unknown Command": {
|
||||
"main": [[{"node": "Format Zulip Response", "type": "main", "index": 0}]]
|
||||
},
|
||||
"Error Response": {
|
||||
"main": [[{"node": "Respond to Zulip", "type": "main", "index": 0}]]
|
||||
},
|
||||
"Format Zulip Response": {
|
||||
"main": [[{"node": "Respond to Zulip", "type": "main", "index": 0}]]
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"staticData": null,
|
||||
"tags": [],
|
||||
"triggerCount": 1,
|
||||
"updatedAt": "2025-12-11T20:30:00.000Z",
|
||||
"versionId": "1"
|
||||
}
|
||||
Reference in New Issue
Block a user