From 14d10468d14e6bb463ed509717c71b886bb251a8 Mon Sep 17 00:00:00 2001 From: HEYYYYYYYYYYYYYYYY Date: Tue, 12 Aug 2025 01:37:02 +0200 Subject: [PATCH 1/5] feat(add): add role handling to add commands --- src/commands/slash/add.js | 95 ++++++++++++++++++++++++++++----------- src/i18n/en-GB.yml | 5 ++- 2 files changed, 72 insertions(+), 28 deletions(-) diff --git a/src/commands/slash/add.js b/src/commands/slash/add.js index b8a54bf59..dfe4bd7eb 100644 --- a/src/commands/slash/add.js +++ b/src/commands/slash/add.js @@ -17,9 +17,14 @@ module.exports = class AddSlashCommand extends SlashCommand { options: [ { name: 'member', - required: true, + required: false, type: ApplicationCommandOptionType.User, }, + { + name: 'role', + required: false, + type: ApplicationCommandOptionType.Role, + }, { autocomplete: true, name: 'ticket', @@ -36,10 +41,10 @@ module.exports = class AddSlashCommand extends SlashCommand { } /** - * @param {import("discord.js").ChatInputCommandInteraction} interaction + * @param {import('discord.js').ChatInputCommandInteraction} interaction */ async run(interaction) { - /** @type {import("client")} */ + /** @type {import('client')} */ const client = this.client; await interaction.deferReply({ ephemeral: true }); @@ -85,32 +90,68 @@ module.exports = class AddSlashCommand extends SlashCommand { }); } - /** @type {import("discord.js").TextChannel} */ + /** @type {import('discord.js').TextChannel} */ const ticketChannel = await interaction.guild.channels.fetch(ticket.id); const member = interaction.options.getMember('member', true); + const role = interaction.options.getRole('role', false); - await ticketChannel.permissionOverwrites.edit( - member, - { - AttachFiles: true, - EmbedLinks: true, - ReadMessageHistory: true, - SendMessages: true, - ViewChannel: true, - }, - `${interaction.user.tag} added ${member.user.tag} to the ticket`, - ); - await ticketChannel.send({ - embeds: [ - new ExtendedEmbedBuilder() - .setColor(ticket.guild.primaryColour) - .setDescription(getMessage('commands.slash.add.added', { - added: member.toString(), - by: interaction.member.toString(), - })), - ], - }); + if (member) { + + await ticketChannel.permissionOverwrites.edit( + member, + { + AttachFiles: true, + EmbedLinks: true, + ReadMessageHistory: true, + SendMessages: true, + ViewChannel: true, + }, + `${interaction.user.tag} added ${member.user.tag} to the ticket`, + ); + + + await ticketChannel.send({ + embeds: [ + new ExtendedEmbedBuilder() + .setColor(ticket.guild.primaryColour) + .setDescription(getMessage('commands.slash.add.added', { + added: member.toString(), + by: interaction.member.toString(), + })), + ], + }); + + } + + if (role) { + + await ticketChannel.permissionOverwrites.edit( + role, + { + AttachFiles: true, + EmbedLinks: true, + ReadMessageHistory: true, + SendMessages: true, + ViewChannel: true, + }, + `${interaction.user.tag} added ${role.name} to the ticket`, + ); + + + await ticketChannel.send({ + embeds: [ + new ExtendedEmbedBuilder() + .setColor(ticket.guild.primaryColour) + .setDescription(getMessage('commands.slash.add.added', { + added: role.toString(), + by: interaction.member.toString(), + })), + ], + }); + + } + await interaction.editReply({ embeds: [ @@ -121,7 +162,7 @@ module.exports = class AddSlashCommand extends SlashCommand { .setColor(ticket.guild.successColour) .setTitle(getMessage('commands.slash.add.success.title')) .setDescription(getMessage('commands.slash.add.success.description', { - member: member.toString(), + args: (member ? member.toString() : '') + (role ? ` and ${role.toString()}` : ''), ticket: ticketChannel.toString(), })), ], @@ -141,4 +182,4 @@ module.exports = class AddSlashCommand extends SlashCommand { }); } -}; \ No newline at end of file +}; diff --git a/src/i18n/en-GB.yml b/src/i18n/en-GB.yml index 803f57432..a17fe6911 100644 --- a/src/i18n/en-GB.yml +++ b/src/i18n/en-GB.yml @@ -55,11 +55,14 @@ commands: member: description: The member to add to the ticket name: member + role: + description: The role to add to the ticket + name: role ticket: description: The ticket to add the member to name: ticket success: - description: "{member} has been added to {ticket}." + description: "{args} has been added to {ticket}." title: ✅ Added claim: description: Claim a ticket From 8e6111a6ed7bb9fc2ecaba1d70bf63fa49396320 Mon Sep 17 00:00:00 2001 From: HEYYYYYYYYYYYYYYYY Date: Tue, 12 Aug 2025 01:38:58 +0200 Subject: [PATCH 2/5] feat(add): handle missing member or role arguments in add commands --- src/commands/slash/add.js | 13 +++++++++++++ src/i18n/en-GB.yml | 3 +++ 2 files changed, 16 insertions(+) diff --git a/src/commands/slash/add.js b/src/commands/slash/add.js index dfe4bd7eb..574be087d 100644 --- a/src/commands/slash/add.js +++ b/src/commands/slash/add.js @@ -95,6 +95,19 @@ module.exports = class AddSlashCommand extends SlashCommand { const member = interaction.options.getMember('member', true); const role = interaction.options.getRole('role', false); + if (!member && !role) { + return await interaction.editReply({ + embeds: [ + new ExtendedEmbedBuilder({ + iconURL: interaction.guild.iconURL(), + text: ticket.guild.footer, + }) + .setColor(ticket.guild.errorColour) + .setTitle(getMessage('commands.slash.add.no_args.title')) + .setDescription(getMessage('commands.slash.add.no_args.description')), + ], + }); + } if (member) { diff --git a/src/i18n/en-GB.yml b/src/i18n/en-GB.yml index a17fe6911..7cd43354e 100644 --- a/src/i18n/en-GB.yml +++ b/src/i18n/en-GB.yml @@ -51,6 +51,9 @@ commands: not_staff: description: Only staff members can add members to others' tickets. title: ❌ Error + no_args: + description: You must specify a member or a role to add to the ticket. + title: ❌ Missing arguments options: member: description: The member to add to the ticket From 1a0d9ba3506196acca1093addd9f161221a312d6 Mon Sep 17 00:00:00 2001 From: HEYYYYYYYYYYYYYYYY Date: Tue, 28 Oct 2025 13:51:46 +0100 Subject: [PATCH 3/5] Apply change requested --- src/commands/slash/add.js | 50 +++++++++++++++++++++++---------- src/i18n/en-GB.yml | 58 +++++++++++++++++++++++++++++++++++---- 2 files changed, 88 insertions(+), 20 deletions(-) diff --git a/src/commands/slash/add.js b/src/commands/slash/add.js index 574be087d..c4c7c84f2 100644 --- a/src/commands/slash/add.js +++ b/src/commands/slash/add.js @@ -1,5 +1,8 @@ const { SlashCommand } = require('@eartharoid/dbf'); -const { ApplicationCommandOptionType } = require('discord.js'); +const { + ApplicationCommandOptionType, + MessageFlags, +} = require('discord.js'); const ExtendedEmbedBuilder = require('../../lib/embed'); const { isStaff } = require('../../lib/users'); const { logTicketEvent } = require('../../lib/logging'); @@ -47,7 +50,7 @@ module.exports = class AddSlashCommand extends SlashCommand { /** @type {import('client')} */ const client = this.client; - await interaction.deferReply({ ephemeral: true }); + await interaction.deferReply({ flags: MessageFlags.Ephemeral }); const ticket = await client.prisma.ticket.findUnique({ include: { guild: true }, @@ -175,24 +178,41 @@ module.exports = class AddSlashCommand extends SlashCommand { .setColor(ticket.guild.successColour) .setTitle(getMessage('commands.slash.add.success.title')) .setDescription(getMessage('commands.slash.add.success.description', { - args: (member ? member.toString() : '') + (role ? ` and ${role.toString()}` : ''), + args: [member?.toString(), role?.toString()].filter(Boolean).join(' & '), ticket: ticketChannel.toString(), })), ], }); - logTicketEvent(this.client, { - action: 'update', - diff: { - original: {}, - updated: { [getMessage('log.ticket.added')]: member.user.tag }, - }, - target: { - id: ticket.id, - name: `<#${ticket.id}>`, - }, - userId: interaction.user.id, - }); + if (member) { + logTicketEvent(this.client, { + action: 'update', + diff: { + original: {}, + updated: { [getMessage('log.ticket.addedMember')]: member.user.tag }, + }, + target: { + id: ticket.id, + name: `<#${ticket.id}>`, + }, + userId: interaction.user.id, + }); + } + + if (role) { + logTicketEvent(this.client, { + action: 'update', + diff: { + original: {}, + updated: { [getMessage('log.ticket.addedRole')]: role.name }, + }, + target: { + id: ticket.id, + name: `<#${ticket.id}>`, + }, + userId: interaction.user.id, + }); + } } }; diff --git a/src/i18n/en-GB.yml b/src/i18n/en-GB.yml index 7cd43354e..1595998ff 100644 --- a/src/i18n/en-GB.yml +++ b/src/i18n/en-GB.yml @@ -23,6 +23,9 @@ buttons: reject_close_request: emoji: ✖️ text: Reject + transcript: + emoji: 📄 + text: Transcript unclaim: emoji: ♻️ text: Release @@ -193,6 +196,28 @@ commands: success: description: "{member} has been removed from {ticket}." title: ✅ Removed + rename: + description: Rename a ticket channel + error: There was an error while renaming the channel. + invalid: + description: The name must be between 1 and 100 characters in length. + title: Invalid name + name: rename + not_staff: + description: Only staff members can rename tickets. + title: ❌ Error + options: + name: + description: The new name for the ticket channel. + name: name + ratelimited: + description: + You have already renamed this channel twice within the last 10 + minutes. Please wait before trying again. + title: Rate Limit Reached + success: + description: The ticket channel has been renamed to `{name}`. + title: Channel renamed tag: description: Use a tag name: tag @@ -234,6 +259,9 @@ commands: transcript: description: Get the transcript of a ticket name: transcript + not_staff: + description: Only staff members can read the transcripts of others' tickets. + title: ❌ Error options: member: description: The member to search for tickets of @@ -264,11 +292,12 @@ commands: title: ✅ Prompt sent dm: closed: - archived: Use the `/transcript` command in **{guild}** to view the archived messages. fields: closed: name: Closed at - value: "{timestamp} (after {duration})" + value: |- + {timestamp} + (after {duration}) closed_by: Closed by created: Created at feedback: Your feedback @@ -310,7 +339,8 @@ log: delete: deleted update: updated ticket: - added: Added members + addedMember: Added member + addedRole: Added role description: "{user} {verb} a ticket" removed: Removed members ticket: Ticket @@ -343,7 +373,6 @@ misc: Sorry, an unexpected error occurred. Please give this information to an administrator. fields: - code: Error code identifier: Identifier title: ⚠️ Something went wrong expired: @@ -368,14 +397,33 @@ misc: this category. title: ❌ Insufficient roles no_categories: - description: No ticket categories have been configured. + description: |- + No ticket categories have been configured. + Configure your server at {url}. title: ❌ There are no ticket categories not_ticket: description: You can only use this command in tickets. title: ❌ This isn't a ticket channel + permissions_error: + description: Sorry, the operation failed due to insufficient permissions. + fields: + for_admins: + name: For server administrators + value: > + [Click here]({url}) for resolution instructions. + title: ⚠️ Something went wrong ratelimited: description: Try again in a few seconds. title: 🐢 Please slow down + role_error: + description: Sorry, the operation failed because of an invalid configuration. + fields: + for_admins: + name: For server administrators + value: > + An invalid user or role was supplied, which usually means a staff role + has been deleted. [Click here]({url}) for resolution instructions. + title: ⚠️ Something went wrong unknown_category: description: Please try a different category. title: ❌ That ticket category doesn't exist From 15e06cf8cb9edd457f71a0cbd8722f903a5cdb99 Mon Sep 17 00:00:00 2001 From: HEYYYYYYYYYYYYYYYY Date: Tue, 4 Nov 2025 20:49:08 +0100 Subject: [PATCH 4/5] Aplly change requested --- src/commands/slash/add.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/slash/add.js b/src/commands/slash/add.js index c4c7c84f2..dc1256c90 100644 --- a/src/commands/slash/add.js +++ b/src/commands/slash/add.js @@ -95,7 +95,7 @@ module.exports = class AddSlashCommand extends SlashCommand { /** @type {import('discord.js').TextChannel} */ const ticketChannel = await interaction.guild.channels.fetch(ticket.id); - const member = interaction.options.getMember('member', true); + const member = interaction.options.getMember('member', false); const role = interaction.options.getRole('role', false); if (!member && !role) { From aedf26c27f81ebc47a202784aa6cb19633689f0f Mon Sep 17 00:00:00 2001 From: HEYYYYYYYYYYYYYYYY Date: Fri, 28 Nov 2025 19:09:04 +0100 Subject: [PATCH 5/5] feat(add): add validation for invalid member targets in add commands --- src/commands/slash/add.js | 14 ++++++++++++++ src/i18n/en-GB.yml | 3 +++ 2 files changed, 17 insertions(+) diff --git a/src/commands/slash/add.js b/src/commands/slash/add.js index dc1256c90..e56179ef7 100644 --- a/src/commands/slash/add.js +++ b/src/commands/slash/add.js @@ -112,6 +112,20 @@ module.exports = class AddSlashCommand extends SlashCommand { }); } + if (member && (member.id === client.user.id || member.id === ticket.createdById)) { + return await interaction.editReply({ + embeds: [ + new ExtendedEmbedBuilder({ + iconURL: interaction.guild.iconURL(), + text: ticket.guild.footer, + }) + .setColor(ticket.guild.errorColour) + .setTitle(getMessage('commands.slash.add.invalid_target.title')) + .setDescription(getMessage('commands.slash.add.invalid_target.description')), + ], + }); + } + if (member) { await ticketChannel.permissionOverwrites.edit( diff --git a/src/i18n/en-GB.yml b/src/i18n/en-GB.yml index 1595998ff..d2a09b3ac 100644 --- a/src/i18n/en-GB.yml +++ b/src/i18n/en-GB.yml @@ -57,6 +57,9 @@ commands: no_args: description: You must specify a member or a role to add to the ticket. title: ❌ Missing arguments + invalid_target: + description: Your target is invalid. + title: ❌ Invalid target options: member: description: The member to add to the ticket