all repos — stealth-developers @ 4ba5deca0873ed7cfa5763ae4c64f6fa4db2b996

src/interactions/commands/bug.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
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
import {
	ActionRowBuilder,
	type ChatInputCommandInteraction,
	type Client,
	ModalBuilder,
	type ModalSubmitInteraction,
	SlashCommandBuilder,
	TextInputBuilder,
	TextInputStyle,
} from "discord.js";
import { BugModel, UserModel } from "../../database/schemas.ts";
import { createUserIfNotExists } from "../../utils/exists.ts";
import { Logger } from "../../utils/logging.ts";

const logger = new Logger("bug-command");

const commandData = new SlashCommandBuilder()
	.setName("bug")
	.setDescription("report a bug")
	.addStringOption((option) =>
		option
			.setName("game")
			.setDescription("which game this bug affects")
			.setRequired(true)
			.addChoices(
				{ name: "warfare tycoon", value: "wft" },
				{ name: "ground war", value: "gw" },
				{ name: "airsoft battles", value: "ab" },
			),
	);

async function execute(
	_client: Client,
	interaction: ChatInputCommandInteraction,
) {
	const game = interaction.options.getString("game", true);

	const modal = new ModalBuilder()
		.setCustomId(`bug:${game}`)
		.setTitle(`report bug - ${getGameName(game)}`);

	const titleInput = new TextInputBuilder()
		.setCustomId("title")
		.setLabel("bug title")
		.setStyle(TextInputStyle.Short)
		.setPlaceholder("short description of the bug")
		.setRequired(true)
		.setMaxLength(100);

	const descriptionInput = new TextInputBuilder()
		.setCustomId("description")
		.setLabel("bug description")
		.setStyle(TextInputStyle.Paragraph)
		.setPlaceholder("detailed description of the bug and steps to reproduce")
		.setRequired(true)
		.setMaxLength(1000);

	const firstRow = new ActionRowBuilder<TextInputBuilder>().addComponents(
		titleInput,
	);
	const secondRow = new ActionRowBuilder<TextInputBuilder>().addComponents(
		descriptionInput,
	);

	modal.addComponents(firstRow, secondRow);

	await interaction.showModal(modal);
}

async function modalExecute(
	_client: Client,
	interaction: ModalSubmitInteraction,
) {
	if (!interaction.guild) {
		await interaction.reply({
			content: "❌ this command can only be used in a server.",
			flags: ["Ephemeral"],
		});
		return;
	}

	const [, game] = interaction.customId.split(":");
	const title = interaction.fields.getTextInputValue("title");
	const description = interaction.fields.getTextInputValue("description");

	try {
		await createUserIfNotExists(interaction.user.id, interaction.guild.id);

		const bug = new BugModel({
			user_id: interaction.user.id,
			game,
			title,
			description,
			status: "open",
			sent: false,
		});

		await bug.save();
		logger.info(`bug report created: ${bug._id}`);

		await interaction.reply({
			content: `✅ bug report submitted!\n\n**game:** ${getGameName(game)}\n**title:** ${title}\n**id:** \`${bug._id}\``,
			flags: ["Ephemeral"],
		});
	} catch (error) {
		logger.error("failed to create bug report:", error);
		await interaction.reply({
			content: "❌ failed to submit bug report. please try again later.",
			flags: ["Ephemeral"],
		});
	}
}

function getGameName(value: string): string {
	switch (value) {
		case "wft":
			return "warfare tycoon";
		case "gw":
			return "ground war";
		case "ab":
			return "airsoft battles";
		default:
			return value;
	}
}

export default {
	data: commandData,
	execute,
	modalExecute,
};