{ "name": "Zammad Ticket Summary to Zulip", "nodes": [ { "name": "On clicking 'execute'", "type": "n8n-nodes-base.manualTrigger", "position": [ -40, 340 ], "parameters": {}, "typeVersion": 1, "id": "zammad-ticket-summary-to-zulip-0" }, { "name": "Ticket Filtering", "type": "n8n-nodes-base.code", "position": [ 400, 460 ], "parameters": { "mode": "runOnceForAllItems", "jsCode": "function collect({previousState,tickets,newId,openId,reminderId,closeId}) {\n const ids=[newId,openId,reminderId,closeId];if(ids.some(x=>!Number.isSafeInteger(x)||x<1)||new Set(ids).size!==4)throw Error('Configure four distinct positive Zammad state IDs');\n if(previousState===null){if(tickets!==null)throw Error('Unexpected initial ticket page');return{state:{page:1,seen:[],counts:[0,0,0,0]},page:1,more:true,hasTickets:false,counts:[0,0,0,0]};}\n if(!previousState||!Number.isSafeInteger(previousState.page)||!Array.isArray(previousState.seen)||!Array.isArray(previousState.counts)||!Array.isArray(tickets))throw Error('Invalid Zammad page state');\n const seen=new Set(previousState.seen),counts=[...previousState.counts];for(const t of tickets){if(!t||!Number.isSafeInteger(t.id)||t.id<1||!Number.isSafeInteger(t.state_id)||seen.has(t.id))throw Error('Invalid or duplicate Zammad ticket');seen.add(t.id);const index=ids.indexOf(t.state_id);if(index!==-1)counts[index]++;}\n const state={page:previousState.page+1,seen:[...seen],counts};return{state,page:state.page,more:tickets.length>0,hasTickets:state.seen.length>0,counts};\n}\n\nconst options={newId:1,openId:2,reminderId:3,closeId:7};let state=collect({previousState:null,tickets:null,...options}).state;state=collect({previousState:state,tickets:$input.all().map(x=>x.json),...options}).state;const result=collect({previousState:state,tickets:[],...options});return result.hasTickets?[{json:{counts:result.counts}}]:[];" }, "typeVersion": 2, "id": "zammad-ticket-summary-to-zulip-1" }, { "name": "List Tickets", "type": "n8n-nodes-base.zammad", "position": [ 200, 460 ], "parameters": { "resource": "ticket", "operation": "getAll", "returnAll": true }, "typeVersion": 1, "id": "zammad-ticket-summary-to-zulip-2" }, { "name": "Notify for Standup", "type": "n8n-nodes-base.zulip", "position": [ 580, 460 ], "parameters": { "topic": "tickets", "stream": "customer support", "content": "={{ \":ticket: Support Tickets Summary:\\n* Open: \" + $json.counts[1] + \"\\n* New: \" + $json.counts[0] + \"\\n* Pending Close \" + $json.counts[3] + \"\\n* Pending Reminder \" + $json.counts[2] }}", "operation": "sendStream" }, "typeVersion": 1, "id": "zammad-ticket-summary-to-zulip-3" }, { "name": "Standup Cron", "type": "n8n-nodes-base.cron", "position": [ -40, 560 ], "parameters": { "triggerTimes": { "item": [ { "mode": "custom", "cronExpression": "0 30 8 * * 1-5" } ] } }, "executeOnce": true, "typeVersion": 1, "id": "zammad-ticket-summary-to-zulip-4" }, { "id": "zammad-ticket-summary-to-zulip-confirm", "name": "Confirm the Zulip message", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 760, 460 ], "parameters": { "mode": "runOnceForEachItem", "jsCode": "function confirm({body}) {if(!body||body.result!=='success'||!Number.isSafeInteger(body.id)||body.id<1)throw Error('Zulip did not confirm the message');return {messageId:body.id};}\n\nreturn {json:confirm({body:$json})};" } } ], "active": false, "settings": { "timezone": "UTC", "executionOrder": "v1" }, "connections": { "List Tickets": { "main": [ [ { "node": "Ticket Filtering", "type": "main", "index": 0 } ] ] }, "Standup Cron": { "main": [ [ { "node": "List Tickets", "type": "main", "index": 0 } ] ] }, "Ticket Filtering": { "main": [ [ { "node": "Notify for Standup", "type": "main", "index": 0 } ] ] }, "On clicking 'execute'": { "main": [ [ { "node": "List Tickets", "type": "main", "index": 0 } ] ] }, "Notify for Standup": { "main": [ [ { "node": "Confirm the Zulip message", "type": "main", "index": 0 } ] ] } }, "pinData": {} }