diff --git a/src/modals/open-mod-ticket.ts b/src/modals/open-mod-ticket.ts index 4c34913..014093b 100644 --- a/src/modals/open-mod-ticket.ts +++ b/src/modals/open-mod-ticket.ts @@ -1,31 +1,39 @@ import { Client, MessageFlags, ModalSubmitInteraction } from 'discord.js'; import { Database } from '../shared/Database'; import { createPrivateHelpTicketThread } from '../utils'; +import { Modal } from '../types'; const warning = '\n\n\nLeaving this thread without acknowledgement may result in punishment. Staff will close the thread when they deem your response acceptable.'; -export default { - name: 'open-mod-ticket', - handler: async function (client: Client, interaction: ModalSubmitInteraction, userId: string) { - const guild = await client.guilds.fetch(interaction.guildId!); - const member = await guild.members.fetch(userId); +class OpenModTicketModal implements Modal { + id = 'open-mod-ticket'; - const guildSettings = await Database.getOrCreateSettings(guild.id); + async execute(context: Client, interaction: ModalSubmitInteraction, userId: string): Promise { + if (!interaction.inGuild()) return; + await interaction.deferReply({ flags: MessageFlags.Ephemeral }); - if (!guildSettings || !guildSettings.private_help_channel_id) - return interaction.reply({ flags: [MessageFlags.Ephemeral], content: 'Failed to create ticket. Please report this to a developer.' }); + try { + const settings = await Database.getOrCreateSettings(interaction.guildId); + if (settings.private_help_channel_id) throw new Error("`private_help_channel_id` hasn't been configured. Please report this error to staff."); - const title = interaction.fields.getTextInputValue('title') ? interaction.fields.getTextInputValue('title') : `Mod Ticket For ${member.displayName}`; - const reason = interaction.fields.getTextInputValue('initial-message') + warning; - const autoJoin = interaction.fields.getStringSelectValues('auto-join-thread')[0] == 'yes'; + const guild = await context.guilds.fetch(interaction.guildId); + const member = await guild.members.fetch(userId); - const membersToAdd = [userId]; + const title = interaction.fields.getTextInputValue('title') ? interaction.fields.getTextInputValue('title') : `Mod Ticket For ${member.displayName}`; + const reason = interaction.fields.getTextInputValue('initial-message') + warning; + const autoJoin = interaction.fields.getCheckbox('auto-join-thread'); - if (autoJoin) membersToAdd.push(interaction.user.id); + const membersToAdd = [userId]; + if (autoJoin) membersToAdd.push(interaction.user.id); - const thread = await createPrivateHelpTicketThread(client, guild, null, reason, title, membersToAdd); + const thread = await createPrivateHelpTicketThread(context, guild, null, reason, title, membersToAdd); + if (!thread) throw new Error('Failed to create a ticket thread. Please report this to a developer.'); - if (thread) interaction.reply({ flags: [MessageFlags.Ephemeral], content: `Mod ticket created: ${thread}.${!autoJoin ? "You've selected not to auto join the thread. You will not be notified of messages sent there. You will have to check the thread periodically for user response." : ''}` }); - else interaction.reply({ flags: [MessageFlags.Ephemeral], content: 'Failed to create ticket. Please report this to a developer.' }); + await interaction.editReply({ content: `Mod ticket created: ${thread}. ${!autoJoin ? "You've selected not to auto join the thread. You will not be notified of messages sent there. You will have to check the thread periodically for user response." : ''}` }); + } catch (error: Error | any) { + await interaction.editReply({ content: error.message }).catch(() => {}); + } } -}; \ No newline at end of file +} + +export default new OpenModTicketModal(); \ No newline at end of file diff --git a/src/utils/modal-utils.ts b/src/utils/modal-utils.ts index f0a4113..0fb7356 100644 --- a/src/utils/modal-utils.ts +++ b/src/utils/modal-utils.ts @@ -1,4 +1,4 @@ -import { LabelBuilder, StringSelectMenuBuilder, StringSelectMenuOptionBuilder, TextInputBuilder, TextInputStyle } from 'discord.js'; +import { CheckboxBuilder, LabelBuilder, TextInputBuilder, TextInputStyle } from 'discord.js'; export function createTextInput(customId: string, labelTitle: string, description: string | null, required: boolean, style: TextInputStyle, maxLength: number | null, minLength: number | null): LabelBuilder { const input = new TextInputBuilder() @@ -19,23 +19,13 @@ export function createTextInput(customId: string, labelTitle: string, descriptio return label; } -export function createYesNoMenu(customId: string, labelTitle: string, description: string | null, defaultYes: boolean): LabelBuilder { - const yesNoMenu = new StringSelectMenuBuilder() - .setCustomId(customId) - .addOptions( - new StringSelectMenuOptionBuilder() - .setLabel('Yes') - .setDefault(defaultYes) - .setValue('yes'), - new StringSelectMenuOptionBuilder() - .setLabel('No') - .setDefault(!defaultYes) - .setValue('no') - ); +export function createCheckbox(customId: string, labelTitle: string, description: string | null, defaultYes: boolean): LabelBuilder { + const component = new CheckboxBuilder() + .setCustomId(customId); const yesNoLabel = new LabelBuilder() .setLabel(labelTitle) - .setStringSelectMenuComponent(yesNoMenu); + .setCheckboxComponent(component); if (description !== null) yesNoLabel.setDescription(description); diff --git a/src/utils/private-help-utils.ts b/src/utils/private-help-utils.ts index e1b2903..11077b3 100644 --- a/src/utils/private-help-utils.ts +++ b/src/utils/private-help-utils.ts @@ -1,6 +1,6 @@ import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelType, ChatInputCommandInteraction, Client, Guild, GuildMember, ModalBuilder, PrivateThreadChannel, TextChannel, TextInputStyle, ThreadAutoArchiveDuration, ThreadChannel, UserContextMenuCommandInteraction } from 'discord.js'; import { Database } from '../shared/Database'; -import { createTextInput, createYesNoMenu } from './modal-utils'; +import { createTextInput, createCheckbox } from './modal-utils'; export async function closeOldTickets(client: Client) { for (const ticket of await Database.getAllOpenPrivateHelpTickets()) { @@ -92,9 +92,8 @@ export async function openModTicketModal(interaction: UserContextMenuCommandInte const titleLabel = createTextInput('title', 'Title', `The name of the thread. Defaults to "Mod Ticket For ${member.displayName}" if left empty`, false, TextInputStyle.Short, 100, null); const initialMessageLabel = createTextInput('initial-message', 'Inital Message', 'The inital message sent in the thread', false, TextInputStyle.Paragraph, 1800, null); - const autoJoinLabel = createYesNoMenu('auto-join-thread', 'Auto Join Thread', 'Whether or not to join you to the thread. Selecting no will not notify you of messages sent!', true); + const autoJoinLabel = createCheckbox('auto-join-thread', 'Auto Join Thread', 'Whether or not to automatically add you to the thread.', true); modal.addLabelComponents(titleLabel, initialMessageLabel, autoJoinLabel); - interaction.showModal(modal); } \ No newline at end of file