import { type Attachment, type Ticket, attachments, db, ticketMessages, } from "@/database"; import { getPublicUrl } from "@/utils/s3"; import { and, asc, eq } 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(and(eq(attachments.ownerType, "ticket_message"))); const relevantAttachments = ticketAttachments.filter((att) => messageIds.includes(att.ownerId), ); const attachmentMap = new Map(); for (const att of relevantAttachments) { 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"; if (msg.authorType === "staff") author = `<@${msg.authorId}>`; 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"), relevantAttachments]; }