all repos — stealth-developers @ f93551c2f70938fc10d0a5c77b6e42b4e92c0073

pkgs/bot/src/utils/tickets/transcripts.ts (view raw)

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
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<number, Attachment[]>();
	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];
}