all repos — stealth-developers @ 06404f4204962483adf1a2e8d42c80fbe1d50390

src/interactions/commands/bug/modals.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
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
import { bugs, db } from "@/database";
import { getGuild } from "@/utils/queries";
import type { Client, ModalSubmitInteraction } from "discord.js";
import { eq, sql } from "drizzle-orm";
import {
	INPUT_IDS,
	MODAL_IDS,
	VALIDATION,
	constructContainer,
} from "./_shared";

export async function handleNewBugModal(
	client: Client,
	interaction: ModalSubmitInteraction,
) {
	if (!interaction.guildId) return;

	const title = interaction.fields.getTextInputValue(INPUT_IDS.TITLE);
	const description = interaction.fields.getTextInputValue(
		INPUT_IDS.DESCRIPTION,
	);
	const affected = interaction.fields.getStringSelectValues(INPUT_IDS.AFFECTED);
	const media = interaction.fields.getUploadedFiles(INPUT_IDS.MEDIA);
	await interaction.deferReply({ flags: ["Ephemeral"] });

	const [{ count }] = await db
		.select({ count: sql<number>`COUNT(*)`.mapWith(Number) })
		.from(bugs)
		.where(eq(bugs.guildId, interaction.guildId));

	const bugNumber = count + 1;
	const paddedNumber = bugNumber.toString().padStart(4, "0");

	const bug = await db
		.insert(bugs)
		.values({
			guildId: interaction.guildId,
			bugNumber: bugNumber,

			authorId: interaction.user.id,
			status: "open",

			title: title,
			description: description,
			projects: [...affected],

			sent: false,
			messageId: null,
			threadId: null,

			createdAt: new Date(),
			updatedAt: new Date(),
			closedAt: null,
		})
		.returning();

	// TODO)) media uploads to s3
	const container = await constructContainer(bug[0], interaction.user.id);
	if (!container) return;

	const { data, exists } = await getGuild(interaction.guildId);
	if (!exists) return;

	const channelId = data.bug_channel_id;
	if (!channelId) return;

	const channel = await interaction.guild?.channels.fetch(channelId);
	if (!channel || !channel.isSendable()) return;

	// send message
	// TODO)) buttons
	const message = await channel.send({
		components: [container],
		flags: ["IsComponentsV2"],
	});

	// thread
	function truncateTitle(title: string, maxLength: number): string {
		return title.length > maxLength
			? `${title.substring(0, maxLength)}...`
			: title;
	}
	const threadName = `#${paddedNumber} ${truncateTitle(title, VALIDATION.THREAD_NAME_MAX_LENGTH)}`;
	const thread = await message.startThread({
		name: threadName,
		autoArchiveDuration: 1440,
	});

	// save & update user
	await db
		.update(bugs)
		.set({ messageId: message.id, threadId: thread.id, sent: true })
		.where(eq(bugs.id, bug[0].id));

	thread.send(
		"Use this space to discuss the bug, provide additional details, or ask questions.",
	);
	interaction.editReply(
		`Bug #${paddedNumber} created successfully! Find it here: ${message.url}`,
	);
}