Add Zulip webhook handler workflow for n8n

This commit is contained in:
2025-12-11 20:27:44 +01:00
parent 402efc3fea
commit b67286c712

View 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"
}