feat: finish /force-close command (closes #311)

This commit is contained in:
Isaac 2023-05-29 23:15:50 +01:00
parent 6b066c177a
commit 540ee547ea
No known key found for this signature in database
GPG Key ID: 0DE40AE37BBA5C33
3 changed files with 121 additions and 57 deletions

View File

@ -18,8 +18,12 @@ module.exports = class CategoryCompleter extends Autocompleter {
const client = this.client; const client = this.client;
let categories = await client.prisma.category.findMany({ where: { guildId: interaction.guild.id } }); let categories = await client.prisma.category.findMany({ where: { guildId: interaction.guild.id } });
const ticket = await client.prisma.ticket.findUnique({ where: { id: interaction.channel.id } });
if (ticket) categories = categories.filter(category => ticket.categoryId !== category.id); if (command.name === 'move') {
const ticket = await client.prisma.ticket.findUnique({ where: { id: interaction.channel.id } });
if (ticket) categories = categories.filter(category => ticket.categoryId !== category.id);
}
const options = value ? categories.filter(category => category.name.match(new RegExp(value, 'i'))) : categories; const options = value ? categories.filter(category => category.name.match(new RegExp(value, 'i'))) : categories;
await interaction.respond( await interaction.respond(
options options

View File

@ -59,7 +59,7 @@ module.exports = class ForceCloseSlashCommand extends SlashCommand {
/** @type {import("client")} */ /** @type {import("client")} */
const client = this.client; const client = this.client;
await interaction.deferReply(); await interaction.deferReply({ ephemeral: true });
const settings = await client.prisma.guild.findUnique({ where: { id: interaction.guild.id } }); const settings = await client.prisma.guild.findUnique({ where: { id: interaction.guild.id } });
const getMessage = client.i18n.getLocale(settings.locale); const getMessage = client.i18n.getLocale(settings.locale);
@ -79,7 +79,46 @@ module.exports = class ForceCloseSlashCommand extends SlashCommand {
}); });
} }
if (interaction.options.getString('time', false)) { // if time option is passed if (interaction.options.getString('ticket', false)) { // if ticket option is passed
ticket = await client.prisma.ticket.findUnique({
include: { category: true },
where: { id: interaction.options.getString('ticket') },
});
if (!ticket) {
return await interaction.editReply({
embeds: [
new ExtendedEmbedBuilder({
iconURL: interaction.guild.iconURL(),
text: settings.footer,
})
.setColor(settings.errorColour)
.setTitle(getMessage('misc.invalid_ticket.title'))
.setDescription(getMessage('misc.invalid_ticket.description')),
],
});
}
await interaction.editReply({
embeds: [
new ExtendedEmbedBuilder({
iconURL: interaction.guild.iconURL(),
text: settings.footer,
})
.setColor(settings.successColour)
.setTitle(getMessage('commands.slash.force-close.closed_one.title'))
.setDescription(getMessage('commands.slash.force-close.closed_one.description', { ticket: ticket.id })),
],
});
setTimeout(async () => {
await client.tickets.finallyClose(ticket.id, {
closedBy: interaction.user.id,
reason: interaction.options.getString('reason', false),
});
}, ms('3s'));
} else if (interaction.options.getString('time', false)) { // if time option is passed
const time = ms(interaction.options.getString('time', false)); const time = ms(interaction.options.getString('time', false));
if (!time) { if (!time) {
@ -96,9 +135,10 @@ module.exports = class ForceCloseSlashCommand extends SlashCommand {
}); });
} }
// TODO: category const categoryId = interaction.options.getInteger('category', false);
const tickets = await client.prisma.ticket.findMany({ const tickets = await client.prisma.ticket.findMany({
where: { where: {
categoryId: categoryId ?? undefined, // must be undefined not null
lastMessageAt: { lte: new Date(Date.now() - time) }, lastMessageAt: { lte: new Date(Date.now() - time) },
open: true, open: true,
}, },
@ -118,7 +158,6 @@ module.exports = class ForceCloseSlashCommand extends SlashCommand {
}); });
} }
let confirmed = false;
const collectorTime = ms('15s'); const collectorTime = ms('15s');
const confirmationM = await interaction.editReply({ const confirmationM = await interaction.editReply({
components: [ components: [
@ -157,58 +196,53 @@ module.exports = class ForceCloseSlashCommand extends SlashCommand {
], ],
}); });
confirmationM.awaitMessageComponent({ confirmationM.awaitMessageComponent({
componentType: ComponentType.Button, componentType: ComponentType.Button,
filter: i => { filter: i => i.user.id === interaction.user.id,
i.deferUpdate();
return i.user.id === interaction.user.id;
},
time: collectorTime, time: collectorTime,
}) })
.then(i => { .then(async i => {
if (JSON.parse(i.customId).id === 'close') { if (JSON.parse(i.customId).id === 'close') {
confirmed = true; await i.reply({
// TODO: i.editReply components: [],
embeds: [
new ExtendedEmbedBuilder({
iconURL: interaction.guild.iconURL(),
text: settings.footer,
})
.setColor(settings.successColour)
.setTitle(getMessage('commands.slash.force-close.confirmed_multiple.title', tickets.length, tickets.length))
.setDescription(getMessage('commands.slash.force-close.confirmed_multiple.description')),
],
ephemeral: true,
});
setTimeout(async () => {
for (const ticket of tickets) {
await client.tickets.finallyClose(ticket.id, {
closedBy: interaction.user.id,
reason: interaction.options.getString('reason', false),
});
}
}, ms('3s'));
} else { } else {
// TODO: cancelled await interaction.deleteReply();
} }
}) })
.catch(() => interaction.editReply({ .catch(async error => {
components: [], client.log.error(error);
embeds: [ await interaction.reply({
new ExtendedEmbedBuilder({ components: [],
iconURL: interaction.guild.iconURL(), embeds: [
text: settings.footer, new ExtendedEmbedBuilder({
}) iconURL: interaction.guild.iconURL(),
.setColor(settings.errorColour) text: settings.footer,
.setTitle(getMessage('misc.expired.title')) })
.setDescription(getMessage('misc.expired.description', { time: ms(time, { long: true }) })), .setColor(settings.errorColour)
], .setTitle(getMessage('misc.expired.title'))
})); .setDescription(getMessage('misc.expired.description', { time: ms(time, { long: true }) })),
],
if (!confirmed) return; });
// TODO: tickets: for each, close (check reason)
} else if (interaction.options.getString('ticket', false)) { // if ticket option is passed
ticket = await client.prisma.ticket.findUnique({
include: { category: true },
where: { id: interaction.options.getString('ticket', false) },
});
if (!ticket) {
return await interaction.editReply({
embeds: [
new ExtendedEmbedBuilder({
iconURL: interaction.guild.iconURL(),
text: settings.footer,
})
.setColor(settings.errorColour)
.setTitle(getMessage('misc.invalid_ticket.title'))
.setDescription(getMessage('misc.invalid_ticket.description')),
],
}); });
}
} else { } else {
ticket = await client.prisma.ticket.findUnique({ ticket = await client.prisma.ticket.findUnique({
include: { category: true }, include: { category: true },
@ -228,6 +262,25 @@ module.exports = class ForceCloseSlashCommand extends SlashCommand {
], ],
}); });
} }
await interaction.editReply({
embeds: [
new ExtendedEmbedBuilder({
iconURL: interaction.guild.iconURL(),
text: settings.footer,
})
.setColor(settings.successColour)
.setTitle(getMessage('commands.slash.force-close.closed_one.title'))
.setDescription(getMessage('commands.slash.force-close.closed_one.description', { ticket: ticket.id })),
],
});
setTimeout(async () => {
await client.tickets.finallyClose(ticket.id, {
closedBy: interaction.user.id,
reason: interaction.options.getString('reason', false),
});
}, ms('3s'));
} }
} }
}; };

View File

@ -3,7 +3,7 @@ buttons:
emoji: emoji:
text: Accept text: Accept
cancel: cancel:
emoji: ✖️ emoji:
text: Cancel text: Cancel
claim: claim:
emoji: 🙌 emoji: 🙌
@ -78,6 +78,9 @@ commands:
description: The reason for closing the ticket description: The reason for closing the ticket
name: reason name: reason
force-close: force-close:
closed_one:
description: The channel will be deleted in a few seconds.
title: ✅ Ticket closed
confirm_multiple: confirm_multiple:
description: > description: >
You are about to close **{count}** tickets that have been inactive You are about to close **{count}** tickets that have been inactive
@ -85,6 +88,11 @@ commands:
{tickets} {tickets}
title: ❓ Are you sure? title: ❓ Are you sure?
confirmed_multiple:
description: The channels will be deleted in a few seconds.
title:
- ✅ Closing %d ticket
- ✅ Closing %d tickets
description: Forcibly close a ticket description: Forcibly close a ticket
name: force-close name: force-close
no_tickets: no_tickets:
@ -97,8 +105,9 @@ commands:
title: ❌ Error title: ❌ Error
options: options:
category: category:
description: >- description:
Close all tickets in the specified category (can be used with `time`) Close all tickets in the specified category (must be used with
`time`)
name: category name: category
reason: reason:
description: The reason for closing the ticket(s) description: The reason for closing the ticket(s)
@ -107,9 +116,7 @@ commands:
description: The ticket to close description: The ticket to close
name: ticket name: ticket
time: time:
description: >- description: Close all tickets that have been inactive for the specified time
Close all tickets that have been inactive for the specified time
(can be used with `category`)
name: time name: time
help: help:
description: Show the help menu description: Show the help menu