EverydayTech Platform - Developer Reference
Complete Source Code Documentation - All Applications
Loading...
Searching...
No Matches
emailToTicketWorker.js
Go to the documentation of this file.
1// Email-to-Ticket AI Worker: Smart ticket creation, update, or reopen
2const Redis = require("ioredis");
3const { v4: uuidv4 } = require("uuid");
4const fetch = require("node-fetch");
5
6const redisConfig = require('./config/redis');
7const sub = new Redis(redisConfig);
8const pub = new Redis(redisConfig);
9
10sub.subscribe("emails:ai:analysis");
11
12/**
13 *
14 * @param email
15 */
16async function findRelatedTicket(email) {
17 // Call backend API to find open/recent tickets for this customer/email
18 const res = await fetch(`http://localhost:3000/api/tickets/find-related?email=${encodeURIComponent(email.from)}&subject=${encodeURIComponent(email.subject)}`);
19 if (!res.ok) return null;
20 return await res.json();
21}
22
23/**
24 *
25 * @param ticketId
26 * @param note
27 * @param isReopen
28 * @param referenceId
29 */
30async function addNoteToTicket(ticketId, note, isReopen = false, referenceId = null) {
31 // Add note to ticket, optionally reopen and reference old ticket
32 await fetch(`http://localhost:3000/api/tickets/${ticketId}/notes`, {
33 method: "POST",
34 headers: { "Content-Type": "application/json" },
35 body: JSON.stringify({
36 content: note,
37 is_ai: true,
38 reference_ticket_id: referenceId || undefined,
39 reopen: isReopen || undefined
40 })
41 });
42}
43
44/**
45 *
46 * @param email
47 * @param note
48 * @param referenceId
49 */
50async function createNewTicket(email, note, referenceId = null) {
51 // Create a new ticket and add the note
52 const res = await fetch(`http://localhost:3000/api/tickets`, {
53 method: "POST",
54 headers: { "Content-Type": "application/json" },
55 body: JSON.stringify({
56 title: email.subject,
57 description: note,
58 customer_email: email.from,
59 status: "open",
60 reference_ticket_id: referenceId || undefined
61 })
62 });
63 if (!res.ok) return null;
64 return await res.json();
65}
66
67/**
68 *
69 * @param tenantId
70 * @param to
71 * @param subject
72 * @param body
73 */
74async function sendTicketEmail(tenantId, to, subject, body) {
75 // Call backend email send endpoint
76 await fetch(`http://localhost:3000/api/email/send/${tenantId}`, {
77 method: "POST",
78 headers: { "Content-Type": "application/json" },
79 body: JSON.stringify({ to, subject, body })
80 });
81}
82
83sub.on("message", async (_, message) => {
84 const { email, ai } = JSON.parse(message); // { email, ai: { status, reason, confidence } }
85 // Find related ticket
86 const related = await findRelatedTicket(email);
87 let ticket, ticketId;
88 if (related && related.status === "open") {
89 // Add note to open ticket
90 await addNoteToTicket(related.id, ai.reason);
91 ticketId = related.id;
92 } else if (related && related.status === "closed" && !related.billed) {
93 // Reopen closed ticket and add note
94 await addNoteToTicket(related.id, ai.reason, true);
95 ticketId = related.id;
96 } else if (related && related.status === "closed" && related.billed) {
97 // Create new ticket, reference old
98 const newTicket = await createNewTicket(email, ai.reason, related.id);
99 if (newTicket) {
100 await addNoteToTicket(newTicket.id, `Related to previous ticket #${related.id}`);
101 ticketId = newTicket.id;
102 }
103 } else {
104 // No related ticket, create new
105 const newTicket = await createNewTicket(email, ai.reason);
106 if (newTicket) ticketId = newTicket.id;
107 }
108 // Send notification email to customer (if ticketId and email.from)
109 if (ticketId && email.from) {
110 // Compose notification body
111 const subject = `Ticket Update: ${email.subject}`;
112 const body = `Your ticket has been updated.\n\n${ai.reason}`;
113 // Assume tenant_id is available on email or related
114 const tenantId = email.tenant_id || (related && related.tenant_id);
115 if (tenantId) {
116 await sendTicketEmail(tenantId, email.from, subject, body);
117 }
118 }
119 // Optionally publish dashboard event
120 pub.publish("dashboard:events", JSON.stringify({ type: "ticket_update", email, ai }));
121});
122
123console.log("Email-to-Ticket AI Worker running: smart ticket creation/update/reopen.");