From 9f18958c7574510ebcb2b4c3283e2d712832967a Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 31 Oct 2022 21:15:44 +0000 Subject: [PATCH] feat: add `/move` command --- src/autocomplete/category.js | 23 ++++++++- src/commands/slash/close.js | 6 --- src/commands/slash/move.js | 89 +++++++++++++++++++++++++++++++++- src/commands/slash/transfer.js | 19 ++++++-- src/i18n/en-GB.yml | 5 +- src/lib/tickets/manager.js | 4 +- 6 files changed, 130 insertions(+), 16 deletions(-) diff --git a/src/autocomplete/category.js b/src/autocomplete/category.js index e8c25a1..2b78d6e 100644 --- a/src/autocomplete/category.js +++ b/src/autocomplete/category.js @@ -8,5 +8,26 @@ module.exports = class CategoryCompleter extends Autocompleter { }); } - async run(value, comamnd, interaction) { } + /** + * @param {string} value + * @param {*} command + * @param {import("discord.js").AutocompleteInteraction} interaction + */ + async run(value, command, interaction) { + /** @type {import("client")} */ + const client = this.client; + + 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); + const options = value ? categories.filter(category => category.name.match(new RegExp(value, 'i'))) : categories; + await interaction.respond( + options + .slice(0, 25) + .map(category => ({ + name: category.name, + value: category.id, + })), + ); + } }; \ No newline at end of file diff --git a/src/commands/slash/close.js b/src/commands/slash/close.js index fc94113..0086c0a 100644 --- a/src/commands/slash/close.js +++ b/src/commands/slash/close.js @@ -17,12 +17,6 @@ module.exports = class CloseSlashCommand extends SlashCommand { required: false, type: ApplicationCommandOptionType.String, }, - { - autocomplete: true, - name: 'ticket', - required: false, - type: ApplicationCommandOptionType.String, - }, ].map(option => { option.descriptionLocalizations = client.i18n.getAllMessages(`commands.slash.${name}.options.${option.name}.description`); option.description = option.descriptionLocalizations['en-GB']; diff --git a/src/commands/slash/move.js b/src/commands/slash/move.js index b9fe64c..2dc3b04 100644 --- a/src/commands/slash/move.js +++ b/src/commands/slash/move.js @@ -1,5 +1,6 @@ const { SlashCommand } = require('@eartharoid/dbf'); const { ApplicationCommandOptionType } = require('discord.js'); +const ExtendedEmbedBuilder = require('../../lib/embed'); module.exports = class MoveSlashCommand extends SlashCommand { constructor(client, options) { @@ -27,8 +28,92 @@ module.exports = class MoveSlashCommand extends SlashCommand { }); } + /** + * @param {import("discord.js").ChatInputCommandInteraction} interaction + */ async run(interaction) { - // TODO: check discordCategory max but not category max (ignore) - // TODO: update cached count for both categories and category-members (from and to) + /** @type {import("client")} */ + const client = this.client; + + await interaction.deferReply({ ephemeral: false }); + + const ticket = await client.prisma.ticket.findUnique({ + include: { + category: true, + guild: true, + }, + where: { id: interaction.channel.id }, + }); + + if (!ticket) { + const { locale } = await client.prisma.guild.findUnique({ where: { id: interaction.guild.id } }); + const getMessage = client.i18n.getLocale(locale); + return await interaction.editReply({ + embeds: [ + new ExtendedEmbedBuilder({ + iconURL: interaction.guild.iconURL(), + text: ticket.guild.footer, + }) + .setColor(ticket.guild.errorColour) + .setTitle(getMessage('misc.not_ticket.title')) + .setDescription(getMessage('misc.not_ticket.description')), + ], + ephemeral: true, + }); + } + + const newCategory = await client.prisma.category.findUnique({ where: { id: interaction.options.getInteger('category', true) } }); + const discordCategory = await interaction.guild.channels.fetch(newCategory.discordCategory); + const getMessage = client.i18n.getLocale(ticket.guild.locale); + + if (discordCategory.children.cache.size === 50) { + return await interaction.editReply({ + embeds: [ + new ExtendedEmbedBuilder({ + iconURL: interaction.guild.iconURL(), + text: ticket.guild.footer, + }) + .setColor(ticket.guild.errorColour) + .setTitle(getMessage('misc.category_full.title')) + .setDescription(getMessage('misc.category_full.description')), + ], + ephemeral: true, + }); + } else { + await client.prisma.ticket.update({ + data: { category: { connect: { id: newCategory.id } } }, + where: { id: ticket.id }, + }); + + const $oldCategory = client.tickets.$.categories[ticket.categoryId]; + const $newCategory = client.tickets.$.categories[newCategory.id]; + + $oldCategory.total--; + $oldCategory[ticket.createdById]--; + + if (!$newCategory.total) $newCategory.total = 0; + $newCategory.total++; + + if (!$newCategory[ticket.createdById]) $newCategory[ticket.createdById] = 0; + $newCategory[ticket.createdById]++; + + await interaction.channel.setParent(discordCategory, { + lockPermissions: false, + reason: `Moved by ${interaction.user.tag}`, + }); + + await interaction.editReply({ + embeds: [ + new ExtendedEmbedBuilder() + .setColor(ticket.guild.primaryColour) + .setDescription(getMessage('commands.slash.move.moved', { + by: interaction.user.toString(), + from: ticket.category.name, + to: newCategory.name, + })), + ], + }); + + } } }; diff --git a/src/commands/slash/transfer.js b/src/commands/slash/transfer.js index 4a488c6..785ad0b 100644 --- a/src/commands/slash/transfer.js +++ b/src/commands/slash/transfer.js @@ -44,7 +44,7 @@ module.exports = class TransferSlashCommand extends SlashCommand { let ticket = await client.prisma.ticket.findUnique({ where: { id: interaction.channel.id } }); const from = ticket.createdById; - + console.log(1) ticket = await client.prisma.ticket.update({ data: { createdBy: { @@ -58,13 +58,11 @@ module.exports = class TransferSlashCommand extends SlashCommand { where: { id: interaction.channel.id }, }); - await interaction.channel.setTopic(`${member.toString()}${ticket.topic?.length > 0 ? ` | ${decrypt(ticket.topic)}` : ''}`); - await interaction.editReply({ embeds: [ new EmbedBuilder() .setColor(ticket.guild.primaryColour) - .setDescription(client.i18n.getMessage(ticket.guild.locale, 'commands.slash.transfer.transferred', { + .setDescription(client.i18n.getMessage(ticket.guild.locale, `commands.slash.transfer.transferred${interaction.member.id !== from ? '_from' : ''}`, { from: `<@${from}>`, to: member.toString(), user: interaction.user.toString(), @@ -72,5 +70,18 @@ module.exports = class TransferSlashCommand extends SlashCommand { ], }); + + await interaction.channel.setTopic(`${member.toString()}${ticket.topic?.length > 0 ? ` | ${decrypt(ticket.topic)}` : ''}`); + + await interaction.channel.permissionOverwrites.edit( + member, + { + AttachFiles: true, + EmbedLinks: true, + ReadMessageHistory: true, + SendMessages: true, + ViewChannel: true, + }, + ); } }; diff --git a/src/i18n/en-GB.yml b/src/i18n/en-GB.yml index da30ed4..9c9fd9c 100644 --- a/src/i18n/en-GB.yml +++ b/src/i18n/en-GB.yml @@ -118,6 +118,7 @@ commands: title: Help move: description: Move a ticket to another category + moved: 🗃️ {by} has moved this ticket from **{from}** to **{to}**. name: move options: category: @@ -285,7 +286,9 @@ misc: description: Please wait {time} before creating another ticket in this category. title: ❌ Please wait error: - description: Sorry, an unexpected error occurred. + description: | + Sorry, an unexpected error occurred. + Please give this information to an administrator. fields: code: Error code identifier: Identifier diff --git a/src/lib/tickets/manager.js b/src/lib/tickets/manager.js index 4e00194..1cf33b1 100644 --- a/src/lib/tickets/manager.js +++ b/src/lib/tickets/manager.js @@ -804,7 +804,7 @@ module.exports = class TicketManager { /** * @param {import("discord.js").ChatInputCommandInteraction|import("discord.js").ButtonInteraction} interaction */ - async preClose(interaction) { + async requestClose(interaction) { const ticket = await this.client.prisma.ticket.findUnique({ include: { category: true, @@ -821,7 +821,7 @@ module.exports = class TicketManager { * @param {boolean} skip * @param {string} reason */ - async close(ticketId, skip, reason) { + async final(ticketId, skip, reason) { // TODO: update cache/cat count // TODO: update cache/member count // TODO: set messageCount on ticket