import { type Attachment, type Ticket, attachments, db, ticketMessages } from "@/database"; import { getPublicUrl } from "@/utils/s3"; import { and, asc, eq, or, inArray } from "drizzle-orm"; export async function generateTranscript(ticket: Ticket): Promise<[string, Attachment[]]> { const messages = await db .select() .from(ticketMessages) .where(eq(ticketMessages.ticketId, ticket.id)) .orderBy(asc(ticketMessages.createdAt)); const messageIds = messages.map((m) => m.id); const ticketAttachments = await db .select() .from(attachments) .where( or( and(eq(attachments.ownerType, "ticket"), eq(attachments.ownerId, ticket.id)), messageIds.length > 0 ? and( eq(attachments.ownerType, "ticket_message"), inArray(attachments.ownerId, messageIds), ) : undefined, ), ); const ticketLevelAttachments = ticketAttachments.filter( (a) => a.ownerType === "ticket" && a.ownerId === ticket.id, ); const attachmentMap = new Map(); for (const att of ticketLevelAttachments) { const existing = attachmentMap.get(att.ownerId) ?? []; attachmentMap.set(att.ownerId, [...existing, att]); } const lines = messages.map((msg) => { const msgAttachments = attachmentMap.get(msg.id) ?? []; const time = new Date(msg.createdAt).toISOString(); let author = "Reporter"; if (msg.authorType === "system") { author = "System"; } else if (msg.authorType === "staff") { author = `<@${msg.authorId}>`; } else if (ticket.addedUsers?.includes(msg.authorId)) { author = `Guest ${ticket.addedUsers.indexOf(msg.authorId) + 1}`; } let text = `[${time}] ${author}: ${msg.content}`; if (msgAttachments.length > 0) { const attLines = msgAttachments .map((att) => { return `\n (Attachment) ${att.fileName}: ${getPublicUrl(att.key)}`; }) .join(""); text += attLines; } return text; }); const separator = "=================================================="; const header = [ separator, ` TRANSCRIPT FOR TICKET #${ticket.anonymousId}`, ` CREATED : ${new Date(ticket.createdAt).toISOString()}`, ` CLOSED : ${ticket.closedAt ? new Date(ticket.closedAt).toISOString() : new Date().toISOString()}`, "", " Times are displayed in UTC.", " All attachments are listed with their public URLs.", separator, "\n", ].join("\n"); return [header + lines.join("\n"), ticketLevelAttachments]; }