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;
let categories = await client.prisma.category.findMany({ where: { guildId: interaction.guild.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;
await interaction.respond(
options

View File

@ -59,7 +59,7 @@ module.exports = class ForceCloseSlashCommand extends SlashCommand {
/** @type {import("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 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));
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({
where: {
categoryId: categoryId ?? undefined, // must be undefined not null
lastMessageAt: { lte: new Date(Date.now() - time) },
open: true,
},
@ -118,7 +158,6 @@ module.exports = class ForceCloseSlashCommand extends SlashCommand {
});
}
let confirmed = false;
const collectorTime = ms('15s');
const confirmationM = await interaction.editReply({
components: [
@ -157,24 +196,41 @@ module.exports = class ForceCloseSlashCommand extends SlashCommand {
],
});
confirmationM.awaitMessageComponent({
componentType: ComponentType.Button,
filter: i => {
i.deferUpdate();
return i.user.id === interaction.user.id;
},
filter: i => i.user.id === interaction.user.id,
time: collectorTime,
})
.then(i => {
.then(async i => {
if (JSON.parse(i.customId).id === 'close') {
confirmed = true;
// TODO: i.editReply
await i.reply({
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 {
// TODO: cancelled
await interaction.deleteReply();
}
})
.catch(() => interaction.editReply({
.catch(async error => {
client.log.error(error);
await interaction.reply({
components: [],
embeds: [
new ExtendedEmbedBuilder({
@ -185,30 +241,8 @@ module.exports = class ForceCloseSlashCommand extends SlashCommand {
.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 {
ticket = await client.prisma.ticket.findUnique({
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:
text: Accept
cancel:
emoji: ✖️
emoji:
text: Cancel
claim:
emoji: 🙌
@ -78,6 +78,9 @@ commands:
description: The reason for closing the ticket
name: reason
force-close:
closed_one:
description: The channel will be deleted in a few seconds.
title: ✅ Ticket closed
confirm_multiple:
description: >
You are about to close **{count}** tickets that have been inactive
@ -85,6 +88,11 @@ commands:
{tickets}
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
name: force-close
no_tickets:
@ -97,8 +105,9 @@ commands:
title: ❌ Error
options:
category:
description: >-
Close all tickets in the specified category (can be used with `time`)
description:
Close all tickets in the specified category (must be used with
`time`)
name: category
reason:
description: The reason for closing the ticket(s)
@ -107,9 +116,7 @@ commands:
description: The ticket to close
name: ticket
time:
description: >-
Close all tickets that have been inactive for the specified time
(can be used with `category`)
description: Close all tickets that have been inactive for the specified time
name: time
help:
description: Show the help menu