From 1b98cdd98ae8eb99d373202ad18a87434b9daf94 Mon Sep 17 00:00:00 2001 From: Jag Date: Wed, 29 Jan 2025 20:43:23 -0800 Subject: [PATCH 1/2] step one --- src/commands/moderation/purge.ts | 27 ++++++++++----------------- src/commands/moderation/warn.ts | 11 ++++------- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/src/commands/moderation/purge.ts b/src/commands/moderation/purge.ts index bdb3412..177043e 100644 --- a/src/commands/moderation/purge.ts +++ b/src/commands/moderation/purge.ts @@ -46,14 +46,16 @@ const Purge: Command = { return; } + interaction.deferReply({ ephemeral: true }); + if (subcommand === 'any') { try { const messages = await interaction.channel.messages.fetch({ limit: count ?? undefined }); await interaction.channel.bulkDelete(messages, true); - await interaction.reply({ content: `Successfully deleted ${messages.size} messages.`, ephemeral: true }); + await interaction.editReply(`Successfully deleted ${messages.size} messages.`); } catch (error) { logger.error(error); - await interaction.reply({ content: 'An error occurred while deleting messages.', ephemeral: true }); + await interaction.editReply('An error occurred while deleting messages.'); } } else if (subcommand === 'user') { const user = interaction.options.getUser('user', true); @@ -64,16 +66,10 @@ const Purge: Command = { const messagesToDelete = userMessages.first(count ?? 0); const deletedMessages = await interaction.channel.bulkDelete(messagesToDelete, true); - await interaction.reply({ - content: `Successfully deleted ${deletedMessages.size} messages from ${user.tag}.`, - ephemeral: true, - }); + await interaction.editReply(`Successfully deleted ${deletedMessages.size} messages from ${user.tag}.`); } catch (error) { logger.error(error); - await interaction.reply({ - content: 'An error occurred while deleting messages.', - ephemeral: true, - }); + await interaction.editReply('An error occurred while deleting messages.'); } } @@ -82,7 +78,7 @@ const Purge: Command = { const countOption = interaction.options.getInteger('count'); if (!messageIdOption) { - await interaction.reply({ content: 'Invalid message ID.', ephemeral: true }); + await interaction.editReply('Invalid message ID.'); return; } @@ -95,7 +91,7 @@ const Purge: Command = { const startIndex = messagesArray.findIndex((m) => m.id === messageId); if (startIndex === -1) { - await interaction.reply({ content: 'Message ID not found in the last 100 messages.', ephemeral: true }); + await interaction.editReply('Message ID not found in the last 100 messages.'); return; } @@ -104,13 +100,10 @@ const Purge: Command = { messagesAfterSpecified.length > count ? messagesAfterSpecified.slice(0, count) : messagesAfterSpecified; await interaction.channel.bulkDelete(messagesToDelete, true); - await interaction.reply({ - content: `Successfully deleted ${messagesToDelete.length} messages after the specified message.`, - ephemeral: true, - }); + await interaction.editReply(`Successfully deleted ${messagesToDelete.length} messages after the specified message.`); } catch (error) { logger.error(error); - await interaction.reply({ content: 'An error occurred while deleting messages.', ephemeral: true }); + await interaction.editReply('An error occurred while deleting messages.'); } } }, diff --git a/src/commands/moderation/warn.ts b/src/commands/moderation/warn.ts index 5e775a0..dd41275 100644 --- a/src/commands/moderation/warn.ts +++ b/src/commands/moderation/warn.ts @@ -16,6 +16,7 @@ const Warn: Command = { data: new SlashCommandBuilder() .setName('warn') .setDescription('Issue a warning to a user') + .setDefaultMemberPermissions(PermissionFlagsBits.KickMembers) .addUserOption((option) => option.setName('user').setDescription('The user to warn').setRequired(true)) .addStringOption((option) => option.setName('reason').setDescription('The reason for the warning').setRequired(true) @@ -27,11 +28,6 @@ const Warn: Command = { return; } - if (!interaction.memberPermissions?.has(PermissionFlagsBits.KickMembers)) { - await interaction.reply({ content: 'Insufficient permissions.', ephemeral: true }); - return; - } - const userOption = interaction.options.getUser('user', true); const reasonOptionRaw = interaction.options.getString('reason'); @@ -85,9 +81,10 @@ const Warn: Command = { // await interaction.followUp(`<@${userOption.id}> has been warned. Reason: ${reasonOptionRaw}`); await interaction.channel?.send(`<@${userOption.id}> has been warned. Reason: ${reasonOptionRaw}`); + await interaction.editReply(`Successfully warned <@${userOption.id}>. User is timed out for ${combinedTimeoutDuration / 60000} minutes.`) } catch (error) { logger.error('Error fetching guild member:', error); - await interaction.followUp({ content: 'Failed to find the specified user in the guild.' }); + await interaction.editReply({ content: 'Failed to find the specified user in the guild.' }); return; } } catch (error) { @@ -101,7 +98,7 @@ const Warn: Command = { } else if (error instanceof Error && error.name === 'PermissionError') { errorMessage = `Permission error: ${error.message}`; } - await interaction.followUp({ content: errorMessage }); + await interaction.editReply({ content: errorMessage }); } }, }; From 63f8ed63726754fa859791f4eff307ca0b6370cc Mon Sep 17 00:00:00 2001 From: Jag Date: Wed, 29 Jan 2025 22:10:32 -0800 Subject: [PATCH 2/2] The rest of the updates --- src/commands/fun/magic8ball.ts | 7 +++---- src/commands/fun/rps.ts | 6 +++--- src/commands/misc/guild.ts | 7 ++++--- src/commands/moderation/ban.ts | 21 ++++++++------------- src/commands/moderation/bulkunban.ts | 13 ++++--------- src/commands/moderation/clearwarns.ts | 24 ++++++++---------------- src/commands/moderation/editwarning.ts | 26 +++++++------------------- src/commands/moderation/kick.ts | 6 +----- src/commands/moderation/unban.ts | 12 +++++------- src/commands/ox/docs.ts | 9 ++++----- src/commands/ox/issue.ts | 6 +++--- src/commands/ox/repo.ts | 14 ++++++++------ 12 files changed, 58 insertions(+), 93 deletions(-) diff --git a/src/commands/fun/magic8ball.ts b/src/commands/fun/magic8ball.ts index bd636c7..1efb7a2 100644 --- a/src/commands/fun/magic8ball.ts +++ b/src/commands/fun/magic8ball.ts @@ -1,4 +1,4 @@ -import { CommandInteraction, SlashCommandBuilder } from 'discord.js'; +import { ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js'; import { Command } from '../../interfaces/command'; const responses = [ @@ -31,9 +31,8 @@ const Magic8Ball: Command = { .addStringOption((option) => option.setName('question').setDescription('Your question for the magic 8-ball').setRequired(true) ), - async run(interaction: CommandInteraction) { - const questionOption = interaction.options.get('question', true); - const question = questionOption.value; + async run(interaction: ChatInputCommandInteraction) { + const question = interaction.options.getString('question', true); const answer = responses[Math.floor(Math.random() * responses.length)]; await interaction.reply(`šŸŽ± *Question:* ${question}\nšŸ”® *Answer:* ${answer}`); }, diff --git a/src/commands/fun/rps.ts b/src/commands/fun/rps.ts index e808689..5ee3336 100644 --- a/src/commands/fun/rps.ts +++ b/src/commands/fun/rps.ts @@ -1,4 +1,4 @@ -import { CommandInteraction, SlashCommandBuilder } from 'discord.js'; +import { ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js'; import { Command } from '../../interfaces/command'; const choices = ['rock', 'paper', 'scissors']; @@ -32,8 +32,8 @@ const RockPaperScissors: Command = { .setRequired(true) .addChoices(...choices.map((choice) => ({ name: choice, value: choice }))) ), - async run(interaction: CommandInteraction) { - const userChoice = interaction.options.get('choice', true)?.value as string; + async run(interaction: ChatInputCommandInteraction) { + const userChoice = interaction.options.getString('choice', true); const botChoice = choices[Math.floor(Math.random() * choices.length)]; const result = determineWinner(userChoice, botChoice); diff --git a/src/commands/misc/guild.ts b/src/commands/misc/guild.ts index d910e52..ea76cef 100644 --- a/src/commands/misc/guild.ts +++ b/src/commands/misc/guild.ts @@ -1,4 +1,4 @@ -import { SlashCommandBuilder } from 'discord.js'; +import { ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js'; import { Command } from '../../interfaces/command'; const Guild: Command = { @@ -18,8 +18,9 @@ const Guild: Command = { { name: 'Cfx.re', value: 'cfx' } ) ), - run: async (interaction) => { - const guildName = interaction.options.get('name')?.value as string; + + run: async (interaction: ChatInputCommandInteraction) => { + const guildName = interaction.options.getString('name'); switch (guildName) { case 'qbox': diff --git a/src/commands/moderation/ban.ts b/src/commands/moderation/ban.ts index 796cf06..ab3aa9a 100644 --- a/src/commands/moderation/ban.ts +++ b/src/commands/moderation/ban.ts @@ -1,4 +1,4 @@ -import { SlashCommandBuilder, PermissionFlagsBits, CommandInteraction } from 'discord.js'; +import { SlashCommandBuilder, PermissionFlagsBits, ChatInputCommandInteraction } from 'discord.js'; import { PrismaClient } from '@prisma/client'; import { Command } from '../../interfaces/command'; import logger from '../../utils/logger'; @@ -9,6 +9,7 @@ const Ban: Command = { data: new SlashCommandBuilder() .setName('ban') .setDescription('Ban a user') + .setDefaultMemberPermissions(PermissionFlagsBits.BanMembers) .addUserOption((option) => option.setName('user').setDescription('The user to ban').setRequired(true)) .addStringOption((option) => option.setName('reason').setDescription('The reason for the ban').setRequired(false)) .addIntegerOption((option) => @@ -18,24 +19,18 @@ const Ban: Command = { .setRequired(false) ), - async run(interaction: CommandInteraction) { + async run(interaction: ChatInputCommandInteraction) { if (!interaction.guild) { await interaction.reply({ content: 'This command can only be used in a guild.', ephemeral: true }); return; } - if (!interaction.memberPermissions?.has(PermissionFlagsBits.BanMembers)) { - await interaction.reply({ content: 'Insufficient permissions.', ephemeral: true }); - return; - } - - const userOption = interaction.options.get('user'); - const reasonOption = interaction.options.get('reason'); - const deleteMessageDaysOption = interaction.options.get('delete_message_days'); + const user = interaction.options.getUser('user', true); + const reasonOption = interaction.options.getString('reason'); + const deleteMessageDaysOption = interaction.options.getInteger('delete_message_days'); - const user = userOption?.user; - const reason = (reasonOption?.value as string) || 'No reason provided'; - const deleteMessageDays = deleteMessageDaysOption ? parseInt(deleteMessageDaysOption.value as string) : 0; + const reason = (reasonOption as string) || 'No reason provided'; + const deleteMessageDays = deleteMessageDaysOption || 0; if (!user) { await interaction.reply({ content: 'User not found!', ephemeral: true }); diff --git a/src/commands/moderation/bulkunban.ts b/src/commands/moderation/bulkunban.ts index c642eed..e7304a8 100644 --- a/src/commands/moderation/bulkunban.ts +++ b/src/commands/moderation/bulkunban.ts @@ -1,4 +1,4 @@ -import { SlashCommandBuilder, PermissionFlagsBits } from 'discord.js'; +import { SlashCommandBuilder, PermissionFlagsBits, ChatInputCommandInteraction } from 'discord.js'; import { Command } from '../../interfaces/command'; import logger from '../../utils/logger'; @@ -6,25 +6,20 @@ const BulkUnban: Command = { data: new SlashCommandBuilder() .setName('bulkunban') .setDescription('Unban all people with the reason included') + .setDefaultMemberPermissions(PermissionFlagsBits.BanMembers) .addStringOption((option) => option .setName('reason') .setDescription('The reason to check for, this checks if the provided string is included in the reason') .setRequired(true) ), - async run(interaction) { + async run(interaction: ChatInputCommandInteraction) { if (!interaction.guild) { await interaction.reply('This command can only be run in a guild.'); return; } - if (!interaction.memberPermissions?.has(PermissionFlagsBits.BanMembers)) { - await interaction.reply('Insufficient permissions.'); - return; - } - - const reasonOptionRaw = interaction.options.get('reason')?.value; - const reasonOption = typeof reasonOptionRaw === 'string' ? reasonOptionRaw : 'No reason provided'; + const reasonOption = interaction.options.getString('reason', true); let amount = 0; diff --git a/src/commands/moderation/clearwarns.ts b/src/commands/moderation/clearwarns.ts index ba70cd5..f6c2236 100644 --- a/src/commands/moderation/clearwarns.ts +++ b/src/commands/moderation/clearwarns.ts @@ -9,6 +9,7 @@ const ClearWarn: Command = { data: new SlashCommandBuilder() .setName('clearwarn') .setDescription('Clear warnings of a user') + .setDefaultMemberPermissions(PermissionFlagsBits.KickMembers) .addUserOption((option) => option.setName('user').setDescription('The user whose warnings will be cleared').setRequired(true) ) @@ -25,16 +26,13 @@ const ClearWarn: Command = { return; } - if (!interaction.memberPermissions?.has(PermissionFlagsBits.KickMembers)) { - await interaction.reply({ content: 'Insufficient permissions.', ephemeral: true }); - return; - } + interaction.deferReply({ ephemeral: true }); const userOption = interaction.options.getUser('user', true); const member: GuildMember | null = await interaction.guild.members.fetch(userOption.id).catch(() => null); if (!member) { - await interaction.reply({ content: 'User not found in the guild.', ephemeral: true }); + await interaction.editReply('User not found in the guild.'); return; } const warnIdOption = interaction.options.getString('warnid', true); @@ -55,15 +53,12 @@ const ClearWarn: Command = { await member.timeout(null); } - await interaction.reply({ - content: `Cleared all warnings and removed timeout for <@${userOption.id}>.`, - ephemeral: true, - }); + await interaction.editReply(`Cleared all warnings and removed timeout for <@${userOption.id}>.`); } else { // Clear specific warning const warnId = parseInt(warnIdOption); if (isNaN(warnId)) { - await interaction.reply({ content: 'Invalid warning ID provided.', ephemeral: true }); + await interaction.editReply('Invalid warning ID provided.'); return; } @@ -75,17 +70,14 @@ const ClearWarn: Command = { }); if (result.count === 0) { - await interaction.reply({ content: 'No warning found with the provided ID for this user.', ephemeral: true }); + await interaction.editReply('No warning found with the provided ID for this user.'); } else { - await interaction.reply({ - content: `Cleared warning ID ${warnId} for <@${userOption.id}>.`, - ephemeral: true, - }); + await interaction.editReply(`Cleared warning ID ${warnId} for <@${userOption.id}>.`); } } } catch (error) { logger.error(error); - await interaction.reply({ content: 'An error occurred while clearing the warnings.', ephemeral: true }); + await interaction.editReply('An error occurred while clearing the warnings.'); } }, }; diff --git a/src/commands/moderation/editwarning.ts b/src/commands/moderation/editwarning.ts index a576ffb..7a2fb42 100644 --- a/src/commands/moderation/editwarning.ts +++ b/src/commands/moderation/editwarning.ts @@ -1,4 +1,4 @@ -import { SlashCommandBuilder, PermissionFlagsBits, CommandInteraction } from 'discord.js'; +import { SlashCommandBuilder, PermissionFlagsBits, ChatInputCommandInteraction } from 'discord.js'; import { PrismaClient, Prisma } from '@prisma/client'; import { Command } from '../../interfaces/command'; import logger from '../../utils/logger'; @@ -9,6 +9,7 @@ const EditWarning: Command = { data: new SlashCommandBuilder() .setName('editwarning') .setDescription('Edit the reason for a given warning') + .setDefaultMemberPermissions(PermissionFlagsBits.KickMembers) .addIntegerOption((option) => option.setName('id').setDescription('The ID of the warning to edit').setRequired(true) ) @@ -16,32 +17,19 @@ const EditWarning: Command = { option.setName('newmessage').setDescription('The new warning message').setRequired(true) ), - async run(interaction: CommandInteraction) { + async run(interaction: ChatInputCommandInteraction) { if (!interaction.guild) { await interaction.reply({ content: 'This command can only be used in a guild.', ephemeral: true }); return; } - if (!interaction.memberPermissions?.has(PermissionFlagsBits.KickMembers)) { - await interaction.reply({ content: 'Insufficient permissions.', ephemeral: true }); - return; - } - - const warningIdOption = interaction.options.get('id'); - const newMessageOption = interaction.options.get('newmessage'); - - const warningId = warningIdOption ? parseInt(warningIdOption.value as string) : null; - const newMessage = newMessageOption ? (newMessageOption.value as string) : null; - - if (warningId === null || newMessage === null) { - await interaction.reply({ content: 'Invalid command usage.', ephemeral: true }); - return; - } + const warningIdOption = interaction.options.getInteger('id', true); + const newMessageOption = interaction.options.getString('newmessage', true); try { const updatedWarning = await prisma.warn.update({ - where: { id: warningId }, - data: { reason: newMessage }, + where: { id: warningIdOption }, + data: { reason: newMessageOption }, }); await interaction.reply({ content: `Warning ID ${updatedWarning.id} has been updated.`, ephemeral: true }); diff --git a/src/commands/moderation/kick.ts b/src/commands/moderation/kick.ts index 323e7f4..8d8c979 100644 --- a/src/commands/moderation/kick.ts +++ b/src/commands/moderation/kick.ts @@ -6,6 +6,7 @@ const Kick: Command = { data: new SlashCommandBuilder() .setName('kick') .setDescription('Kick a user from the server') + .setDefaultMemberPermissions(PermissionFlagsBits.KickMembers) .addUserOption((option) => option.setName('user').setDescription('User to kick').setRequired(true)) .addStringOption((option) => option.setName('reason').setDescription('Reason for kicking')), @@ -15,11 +16,6 @@ const Kick: Command = { return; } - if (!interaction.memberPermissions?.has(PermissionFlagsBits.KickMembers)) { - await interaction.reply({ content: 'You do not have permission to kick members.', ephemeral: true }); - return; - } - const memberOption = interaction.options.getMember('user'); const member = memberOption as GuildMember | null; diff --git a/src/commands/moderation/unban.ts b/src/commands/moderation/unban.ts index 6001a23..9c4e386 100644 --- a/src/commands/moderation/unban.ts +++ b/src/commands/moderation/unban.ts @@ -9,6 +9,7 @@ const Unban: Command = { data: new SlashCommandBuilder() .setName('unban') .setDescription('Unban a user') + .setDefaultMemberPermissions(PermissionFlagsBits.BanMembers) .addUserOption((option) => option.setName('user').setDescription('The user to unban').setRequired(true)) .addStringOption((option) => option.setName('reason').setDescription('The reason for the unban').setRequired(false) @@ -20,10 +21,7 @@ const Unban: Command = { return; } - if (!interaction.memberPermissions?.has(PermissionFlagsBits.BanMembers)) { - await interaction.reply({ content: 'Insufficient permissions.', ephemeral: true }); - return; - } + await interaction.deferReply({ ephemeral: true }); const userOption = interaction.options.get('user'); const reasonOption = interaction.options.get('reason'); @@ -32,7 +30,7 @@ const Unban: Command = { const reason = (reasonOption?.value as string) || 'No reason provided'; if (!user) { - await interaction.reply({ content: 'User not found!', ephemeral: true }); + await interaction.editReply('User not found!'); return; } @@ -52,10 +50,10 @@ const Unban: Command = { } await interaction.guild.members.unban(user, reason); - await interaction.reply({ content: `Unbanned <@${user.id}>. Reason: ${reason}`, ephemeral: true }); + await interaction.editReply(`Unbanned <@${user.id}>. Reason: ${reason}`); } catch (error) { logger.error(error); - await interaction.reply({ content: 'An error occurred while processing the unban.', ephemeral: true }); + await interaction.editReply('An error occurred while processing the unban.'); } }, }; diff --git a/src/commands/ox/docs.ts b/src/commands/ox/docs.ts index 5c97de6..09ff635 100644 --- a/src/commands/ox/docs.ts +++ b/src/commands/ox/docs.ts @@ -1,4 +1,4 @@ -import { CommandInteraction, EmbedBuilder, SlashCommandBuilder } from 'discord.js'; +import { ChatInputCommandInteraction, EmbedBuilder, SlashCommandBuilder } from 'discord.js'; import { Command } from '../../interfaces/command'; import { DocsUrl, ResourceChoices } from '../../constants'; @@ -13,14 +13,13 @@ const Docs: Command = { .setRequired(true) .addChoices(...ResourceChoices) ), - async run(interaction: CommandInteraction) { - const resourceOption = interaction.options.get('resource'); - const resource = resourceOption?.value as string; + async run(interaction: ChatInputCommandInteraction) { + const resource = interaction.options.getString('resource', true); await sendDocumentationEmbed(interaction, resource); }, }; -const sendDocumentationEmbed = async (interaction: CommandInteraction, resource: string) => { +const sendDocumentationEmbed = async (interaction: ChatInputCommandInteraction, resource: string) => { const docsEmbed = new EmbedBuilder() .setTitle('Documentation') .setDescription('Please read the documentation thoroughly and carefully.') diff --git a/src/commands/ox/issue.ts b/src/commands/ox/issue.ts index 43ed15f..ae4eaa6 100644 --- a/src/commands/ox/issue.ts +++ b/src/commands/ox/issue.ts @@ -1,4 +1,4 @@ -import { CommandInteraction, SlashCommandBuilder } from 'discord.js'; +import { ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js'; import { Command } from '../../interfaces/command'; import { GithubUrl, ResourceChoices } from '../../constants'; @@ -13,8 +13,8 @@ const Issue: Command = { .setRequired(true) .addChoices(...ResourceChoices) ), - async run(interaction: CommandInteraction) { - const repo = interaction.options.get('repository')?.value as string; + async run(interaction: ChatInputCommandInteraction) { + const repo = interaction.options.getString('repository', true); if (!repo) { await interaction.reply({ content: 'Invalid repository selected.', ephemeral: true }); return; diff --git a/src/commands/ox/repo.ts b/src/commands/ox/repo.ts index 82b6403..1e8d117 100644 --- a/src/commands/ox/repo.ts +++ b/src/commands/ox/repo.ts @@ -1,4 +1,4 @@ -import { CommandInteraction, EmbedBuilder, SlashCommandBuilder } from 'discord.js'; +import { ChatInputCommandInteraction, EmbedBuilder, SlashCommandBuilder } from 'discord.js'; import { Command } from '../../interfaces/command'; import { GithubApi, GithubUrl, ResourceChoices } from '../../constants'; import axios from 'axios'; @@ -15,14 +15,16 @@ const Repo: Command = { .setRequired(true) .addChoices(...ResourceChoices) ), - async run(interaction: CommandInteraction) { - const repositoryName = interaction.options.get('name')?.value as string; + async run(interaction: ChatInputCommandInteraction) { + const repositoryName = interaction.options.getString('name', true); await newEmbed(interaction, repositoryName); }, }; -const newEmbed = async (interaction: CommandInteraction, repository: string) => { +const newEmbed = async (interaction: ChatInputCommandInteraction, repository: string) => { try { + interaction.deferReply(); + const response = await axios.get(`${GithubApi}/${repository}`); const data = response.data; @@ -39,10 +41,10 @@ const newEmbed = async (interaction: CommandInteraction, repository: string) => ) .setURL(`${GithubUrl}/${repository}`); - return interaction.reply({ embeds: [repoEmbed] }); + return interaction.editReply({ embeds: [repoEmbed] }); } catch (error) { logger.error('Error fetching repository data:', error); - return interaction.reply('An error occurred while fetching repository data.'); + return interaction.editReply('An error occurred while fetching repository data.'); } };