module.exports = function (RED) { "use strict"; function ZammadTicketNode(config) { RED.nodes.createNode(this, config); const node = this; node.configNode = RED.nodes.getNode(config.config); if (!node.configNode) { node.error("No zammad-config node configured"); return; } node.operation = config.operation || "list"; node.status({ fill: "blue", shape: "ring", text: "ready" }); function doRequest(method, path, body, msg, done) { node.status({ fill: "yellow", shape: "dot", text: method + " " + path }); node.configNode.sendRequest(method, path, body, {}, function (err, result) { if (err) { node.status({ fill: "red", shape: "ring", text: "error" }); done ? done(err) : node.error(err, msg); return; } msg.payload = result.body; msg.statusCode = result.statusCode; msg.zammad = result; node.status({ fill: "green", shape: "dot", text: result.statusCode }); done(); }); } function buildTicketPayload(msg) { if (msg.payload && typeof msg.payload === "object" && msg.payload.title) return msg.payload; const p = {}; if (msg.title !== undefined) p.title = msg.title; if (msg.customer !== undefined) p.customer = msg.customer; if (msg.group !== undefined) p.group = msg.group; if (msg.state !== undefined) p.state = msg.state; if (msg.priority !== undefined) p.priority = msg.priority; if (msg.body !== undefined || msg.articleBody !== undefined) { p.article = { body: msg.body || msg.articleBody, from: msg.from || "System", to: msg.to || "", sender: msg.sender || "Agent", type: msg.articleType || "note" }; } return p; } node.on("input", function (msg, send, done) { const op = msg.operation || node.operation; switch (op) { case "list": { const p = new URLSearchParams(); if (msg.query) p.append("query", msg.query); if (msg.limit) p.append("per_page", msg.limit); if (msg.page) p.append("page", msg.page); const qs = p.toString(); doRequest("GET", "/tickets" + (qs ? "?" + qs : ""), undefined, msg, done); break; } case "search": { const p = new URLSearchParams(); if (msg.query) p.append("query", msg.query); if (msg.limit) p.append("per_page", msg.limit); const qs = p.toString(); doRequest("GET", "/tickets/search" + (qs ? "?" + qs : ""), undefined, msg, done); break; } case "get": { const id = msg.ticketId || msg.payload; if (!id) { node.error("Missing ticketId"); done && done(new Error("Missing ticketId")); return; } doRequest("GET", "/tickets/" + encodeURIComponent(id), undefined, msg, done); break; } case "create": { doRequest("POST", "/tickets", buildTicketPayload(msg), msg, done); break; } case "update": { const id = msg.ticketId || (msg.payload && msg.payload.id); if (!id) { node.error("Missing ticketId"); done && done(new Error("Missing ticketId")); return; } doRequest("PUT", "/tickets/" + encodeURIComponent(id), msg.payload && typeof msg.payload === "object" && msg.payload.title ? msg.payload : buildTicketPayload(msg), msg, done); break; } case "articles": { const id = msg.ticketId || (msg.payload && msg.payload.id); if (!id) { node.error("Missing ticketId"); done && done(new Error("Missing ticketId")); return; } doRequest("GET", "/ticket_articles/by_ticket/" + encodeURIComponent(id), undefined, msg, done); break; } case "addArticle": { const id = msg.ticketId || (msg.payload && msg.payload.id); if (!id) { node.error("Missing ticketId"); done && done(new Error("Missing ticketId")); return; } const sender = msg.sender || "Agent"; doRequest("POST", "/ticket_articles", { body: msg.articleBody || msg.body || (msg.payload && msg.payload.body) || "", from: msg.from || sender, sender, type: msg.articleType || "note", internal: msg.internal !== undefined ? msg.internal : false, contentType: "text/plain" }, msg, done); break; } case "tags": { const id = msg.ticketId || (msg.payload && msg.payload.id); if (!id) { node.error("Missing ticketId"); done && done(new Error("Missing ticketId")); return; } doRequest("GET", "/tickets/" + encodeURIComponent(id) + "/tags", undefined, msg, done); break; } case "addTag": { const id = msg.ticketId || (msg.payload && msg.payload.id); const tag = msg.tag || msg.tagName; if (!id || !tag) { node.error("Missing ticketId or tag"); done && done(new Error("Missing ticketId or tag")); return; } doRequest("POST", "/tags/add", { tag, object: "Ticket", o_id: id }, msg, done); break; } default: { const err = new Error("Unknown operation: " + op); node.error(err); if (done) done(err); } } }); } RED.nodes.registerType("zammad-ticket", ZammadTicketNode); };