diff --git a/src/commands/tag.ts b/src/commands/tag.ts index 1efb503..b8791af 100644 --- a/src/commands/tag.ts +++ b/src/commands/tag.ts @@ -11,7 +11,7 @@ import { TextChannel } from 'discord.js'; import { contributorsRole, teamRole, devRole, supportCategory } from '../../config.json'; -import { getTag, getTagNames } from '../functions/mongo'; +import { deleteTag, getTag, getTagNames } from '../functions/mongo'; import { Tag as TagType } from '../types/main'; import { GuildMember } from 'discord.js'; @@ -19,6 +19,22 @@ export const data = new SlashCommandBuilder() .setName('tag') .setDescription('Tag preset texts') .addSubcommand((subcommand) => subcommand.setName('add').setDescription('Add a new tag')) + .addSubcommand((subcommand) => + subcommand + .setName('edit') + .setDescription('Edit a tag') + .addStringOption((option) => + option.setName('name').setDescription('The name of the tag').setRequired(true).setAutocomplete(true) + ) + ) + .addSubcommand((subcommand) => + subcommand + .setName('delete') + .setDescription('Delete a tag') + .addStringOption((option) => + option.setName('name').setDescription('The name of the tag').setRequired(true).setAutocomplete(true) + ) + ) .addSubcommand((subcommand) => subcommand .setName('send') @@ -39,7 +55,12 @@ export const autoComplete = async (interaction: AutocompleteInteraction) => { const input = focusedOption.value; const names = (await getTagNames()).names as string[]; let choices: string | any[] = []; - if ('send' === interaction.options.getSubcommand() && 'name' === focusedOption.name) { + if ( + ('send' === interaction.options.getSubcommand() || + 'edit' === interaction.options.getSubcommand() || + 'delete' === interaction.options.getSubcommand()) && + 'name' === focusedOption.name + ) { choices = names.filter((name) => name.includes(input)); } const displayedChoices = choices.slice(0, 25); @@ -81,6 +102,51 @@ export const execute = async (interaction: ChatInputCommandInteraction) => { } break; } + case 'edit': { + const name = (interaction.options.getString('name') as string).toLowerCase(); + if (memberRoles.some((role) => [teamRole, devRole].includes(role))) { + const modal = new ModalBuilder() + .setCustomId(`t.e.${name}`) + .setTitle('Please enter the updated tag information'); + + const tagFormContent = new TextInputBuilder() + .setStyle(TextInputStyle.Paragraph) + .setCustomId('tagFormUpdatedContent') + .setLabel('New Tag Content') + .setRequired(true); + + const tagFormContentReason = new ActionRowBuilder().addComponents( + tagFormContent + ); + modal.addComponents(tagFormContentReason); + await interaction.showModal(modal); + } else { + return await interaction.reply({ + content: 'You do not have permission to use this command', + ephemeral: true + }); + } + break; + } + case 'delete': { + if (memberRoles.some((role) => [teamRole, devRole].includes(role))) { + const inputTag = await deleteTag((interaction.options.getString('name') as string).toLowerCase()); + if (inputTag.success) { + return await interaction.reply({ + content: 'Tag deleted successfully', + ephemeral: true + }); + } + return await interaction.reply({ + content: 'Tag not found', + ephemeral: true + }); + } + return await interaction.reply({ + content: 'You do not have permission to use this command', + ephemeral: true + }); + } case 'send': { const name = (interaction.options.getString('name') as string).toLowerCase(); let messageLink = interaction.options.getString('message-link') || null; diff --git a/src/events/interactionCreate.ts b/src/events/interactionCreate.ts index 835243a..e6a4642 100644 --- a/src/events/interactionCreate.ts +++ b/src/events/interactionCreate.ts @@ -1,11 +1,13 @@ /* eslint-disable no-console */ -import { Interaction, Events, InteractionType, EmbedBuilder } from 'discord.js'; +import { Interaction, Events, InteractionType, EmbedBuilder, GuildMember } from 'discord.js'; +import { teamRole, devRole } from '../../config.json'; +import { Tag, modifyTag } from '../functions/mongo'; import { eventMessage } from '../functions/logger'; -import { Tag } from '../functions/mongo'; export const name = Events.InteractionCreate; export const execute = async (interaction: Interaction) => { try { + const memberRoles = (interaction.member as GuildMember).roles.cache.map((role) => role.id); if (interaction.isChatInputCommand()) { const command = interaction.client.commands.get(interaction.commandName); if (!command) return; @@ -48,6 +50,23 @@ export const execute = async (interaction: Interaction) => { .setDescription(`The tag \`${name}\` has been added successfully`); await interaction.reply({ embeds: [embed], ephemeral: true }); } + if (interaction.customId.startsWith('t.e.')) { + if (memberRoles.some((role) => [teamRole, devRole].includes(role))) return; + const name = interaction.customId.split('.')[2]; + const content = interaction.fields.getTextInputValue('tagFormUpdatedContent'); + + const updatedTag = await modifyTag(name, new Tag(name, content, interaction.user.id, 'approved')); + if (updatedTag.success) { + const embed = new EmbedBuilder() + .setTitle('Tag Updated') + .setDescription(`The tag \`${name}\` has been added successfully`); + await interaction.reply({ embeds: [embed], ephemeral: true }); + } else if (false === updatedTag.success && 'Tag not found' === updatedTag.info) { + await interaction.reply({ content: 'This tag does not exist!', ephemeral: true }); + } else { + await interaction.reply({ content: 'An error occurred', ephemeral: true }); + } + } } } catch (error: any) { console.log(error); diff --git a/src/functions/mongo.ts b/src/functions/mongo.ts index fc0fb65..d6e4e61 100644 --- a/src/functions/mongo.ts +++ b/src/functions/mongo.ts @@ -52,6 +52,18 @@ export const modifyTag = async (name: string, tag: TagType) => { } }; +export const deleteTag = async (name: string) => { + try { + const tag = await TagModel.deleteOne({ name: name }); + if (tag) { + return { success: true, info: 'Tag deleted successfully' }; + } + return { success: false, info: 'Tag not found' }; + } catch (error) { + return { success: false, info: 'An error occurred', error: error }; + } +}; + export const getTag = async (name: string) => { try { const tag = await TagModel.findOne({ name: name });