From a816129dd235c03a81186524bbe36313faa2472f Mon Sep 17 00:00:00 2001 From: Vermium Sifell Date: Sun, 1 Oct 2023 16:10:58 +0200 Subject: [PATCH] feat: :recycle: centralized error classes I have cleaned up some code by moving some regular used throw new messages to a error class file --- .../groups/bonus/subcommands/daily/index.ts | 18 ++++------- .../groups/bonus/subcommands/monthly/index.ts | 17 ++++------ .../groups/bonus/subcommands/weekly/index.ts | 18 ++++------- .../credits/subcommands/balance/index.ts | 7 ++-- .../credits/subcommands/gift/index.ts | 13 ++++---- src/commands/credits/subcommands/top/index.ts | 6 ++-- .../credits/subcommands/work/index.ts | 14 ++------ .../groups/credits/subcommands/give/index.ts | 11 ++----- .../credits/subcommands/giveaway/index.ts | 14 +++----- .../groups/credits/subcommands/set/index.ts | 15 +++------ .../groups/credits/subcommands/take/index.ts | 15 +++------ .../credits/subcommands/transfer/index.ts | 16 +++------- .../moderation/subcommands/prune/index.ts | 18 +++++++---- src/commands/quotes/subcommands/post/index.ts | 14 +++++--- .../reputation/subcommands/check/index.ts | 5 +-- .../reputation/subcommands/repute/index.ts | 13 ++------ .../settings/subcommands/credits/index.ts | 23 ++++--------- .../settings/subcommands/ctrlpanel/index.ts | 10 +++--- .../settings/subcommands/quotes/index.ts | 13 +++----- src/commands/shop/subcommands/ctrlpanel.ts | 9 +++--- src/commands/utils/subcommands/about/index.ts | 8 ++--- .../utils/subcommands/avatar/index.ts | 4 +-- src/utils/ensureGuildExists.ts | 10 ++++++ src/utils/ensureUserExists.ts | 10 ++++++ src/utils/errors.ts | 32 +++++++++++++++++++ 25 files changed, 151 insertions(+), 182 deletions(-) create mode 100644 src/utils/ensureGuildExists.ts create mode 100644 src/utils/ensureUserExists.ts create mode 100644 src/utils/errors.ts diff --git a/src/commands/credits/groups/bonus/subcommands/daily/index.ts b/src/commands/credits/groups/bonus/subcommands/daily/index.ts index bfd78f6..60ad8d2 100644 --- a/src/commands/credits/groups/bonus/subcommands/daily/index.ts +++ b/src/commands/credits/groups/bonus/subcommands/daily/index.ts @@ -9,6 +9,10 @@ import CreditsManager from "../../../../../../handlers/CreditsManager"; import prisma from "../../../../../../handlers/prisma"; import generateCooldownName from "../../../../../../helpers/generateCooldownName"; import deferReply from "../../../../../../utils/deferReply"; +import { + GuildNotFoundError, + UserNotFoundError, +} from "../../../../../../utils/errors"; import sendResponse from "../../../../../../utils/sendResponse"; const cooldownManager = new CooldownManager(); @@ -22,18 +26,8 @@ export const execute = async (interaction: ChatInputCommandInteraction) => { const { guild, user } = interaction; await deferReply(interaction, false); - - if (!guild) { - throw new Error( - "Oops! It looks like you're not part of a guild. Join a guild to embark on this adventure!" - ); - } - - if (!user) { - throw new Error( - "Oops! We couldn't find your user information. Please try again or contact support for assistance." - ); - } + if (!guild) throw new GuildNotFoundError(); + if (!user) throw new UserNotFoundError(); const guildCreditsSettings = await prisma.guildCreditsSettings.upsert({ where: { id: guild.id }, diff --git a/src/commands/credits/groups/bonus/subcommands/monthly/index.ts b/src/commands/credits/groups/bonus/subcommands/monthly/index.ts index 25af652..41b7c73 100644 --- a/src/commands/credits/groups/bonus/subcommands/monthly/index.ts +++ b/src/commands/credits/groups/bonus/subcommands/monthly/index.ts @@ -9,6 +9,10 @@ import CreditsManager from "../../../../../../handlers/CreditsManager"; import prisma from "../../../../../../handlers/prisma"; import generateCooldownName from "../../../../../../helpers/generateCooldownName"; import deferReply from "../../../../../../utils/deferReply"; +import { + GuildNotFoundError, + UserNotFoundError, +} from "../../../../../../utils/errors"; import sendResponse from "../../../../../../utils/sendResponse"; const cooldownManager = new CooldownManager(); @@ -25,17 +29,8 @@ export const execute = async (interaction: ChatInputCommandInteraction) => { await deferReply(interaction, false); - if (!guild) { - throw new Error( - "Oops! It looks like you're not part of a guild. Join a guild to embark on this adventure!" - ); - } - - if (!user) { - throw new Error( - "Oops! We couldn't find your user information. Please try again or contact support for assistance." - ); - } + if (!guild) throw new GuildNotFoundError(); + if (!user) throw new UserNotFoundError(); const guildCreditsSettings = await prisma.guildCreditsSettings.upsert({ where: { id: guild.id }, diff --git a/src/commands/credits/groups/bonus/subcommands/weekly/index.ts b/src/commands/credits/groups/bonus/subcommands/weekly/index.ts index 5cca376..42d1428 100644 --- a/src/commands/credits/groups/bonus/subcommands/weekly/index.ts +++ b/src/commands/credits/groups/bonus/subcommands/weekly/index.ts @@ -9,6 +9,10 @@ import CreditsManager from "../../../../../../handlers/CreditsManager"; import prisma from "../../../../../../handlers/prisma"; import generateCooldownName from "../../../../../../helpers/generateCooldownName"; import deferReply from "../../../../../../utils/deferReply"; +import { + GuildNotFoundError, + UserNotFoundError, +} from "../../../../../../utils/errors"; import sendResponse from "../../../../../../utils/sendResponse"; const cooldownManager = new CooldownManager(); @@ -24,18 +28,8 @@ export const execute = async (interaction: ChatInputCommandInteraction) => { const { guild, user } = interaction; await deferReply(interaction, false); - - if (!guild) { - throw new Error( - "Oops! It looks like you're not part of a guild. Join a guild to embark on this adventure!" - ); - } - - if (!user) { - throw new Error( - "Oops! We couldn't find your user information. Please try again or contact support for assistance." - ); - } + if (!guild) throw new GuildNotFoundError(); + if (!user) throw new UserNotFoundError(); const guildCreditsSettings = await prisma.guildCreditsSettings.upsert({ where: { id: guild.id }, diff --git a/src/commands/credits/subcommands/balance/index.ts b/src/commands/credits/subcommands/balance/index.ts index 2f73384..84b0e18 100644 --- a/src/commands/credits/subcommands/balance/index.ts +++ b/src/commands/credits/subcommands/balance/index.ts @@ -7,6 +7,7 @@ import { } from "discord.js"; import CreditsManager from "../../../../handlers/CreditsManager"; import deferReply from "../../../../utils/deferReply"; +import { GuildNotFoundError } from "../../../../utils/errors"; import sendResponse from "../../../../utils/sendResponse"; const creditsManager = new CreditsManager(); @@ -26,11 +27,9 @@ export const builder = (command: SlashCommandSubcommandBuilder) => { export const execute = async (interaction: ChatInputCommandInteraction) => { const { options, user, guild } = interaction; - await deferReply(interaction, false); - if (!guild) { - throw new Error("This command can only be used in guild environments. ❌"); - } + await deferReply(interaction, false); + if (!guild) throw new GuildNotFoundError(); const checkAccount = options.getUser("account") || user; const creditAccount = await creditsManager.balance(guild, checkAccount); diff --git a/src/commands/credits/subcommands/gift/index.ts b/src/commands/credits/subcommands/gift/index.ts index 348c98d..e4285a7 100644 --- a/src/commands/credits/subcommands/gift/index.ts +++ b/src/commands/credits/subcommands/gift/index.ts @@ -9,6 +9,7 @@ import { import CreditsManager from "../../../../handlers/CreditsManager"; import upsertGuildMember from "../../../../helpers/upsertGuildMember"; import deferReply from "../../../../utils/deferReply"; +import { GuildNotFoundError } from "../../../../utils/errors"; import sendResponse from "../../../../utils/sendResponse"; const creditsManager = new CreditsManager(); @@ -39,17 +40,15 @@ export const builder = (command: SlashCommandSubcommandBuilder) => { }; export const execute = async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - const { options, user, guild } = interaction; - const recipient = options.getUser("account"); + + await deferReply(interaction, true); + if (!guild) throw new GuildNotFoundError(); + + const recipient = options.getUser("account", true); const amount = options.getInteger("amount"); const message = options.getString("message"); - if (!guild || !user || !recipient) { - throw new Error("Invalid interaction data"); - } - if (typeof amount !== "number" || amount < 1) { throw new Error("Please enter a valid number of credits to gift"); } diff --git a/src/commands/credits/subcommands/top/index.ts b/src/commands/credits/subcommands/top/index.ts index 3d6c701..ac6153f 100644 --- a/src/commands/credits/subcommands/top/index.ts +++ b/src/commands/credits/subcommands/top/index.ts @@ -6,6 +6,7 @@ import { } from "discord.js"; import CreditsManager from "../../../../handlers/CreditsManager"; import deferReply from "../../../../utils/deferReply"; +import { GuildNotFoundError } from "../../../../utils/errors"; import sendResponse from "../../../../utils/sendResponse"; const creditsManager = new CreditsManager(); @@ -20,10 +21,7 @@ export const execute = async (interaction: CommandInteraction) => { const { guild, client, user } = interaction; await deferReply(interaction, false); - - if (!guild) { - throw new Error("Unable to find the guild."); - } + if (!guild) throw new GuildNotFoundError(); const topTen = await creditsManager.topUsers(guild, 10); diff --git a/src/commands/credits/subcommands/work/index.ts b/src/commands/credits/subcommands/work/index.ts index 487b6fa..8708931 100644 --- a/src/commands/credits/subcommands/work/index.ts +++ b/src/commands/credits/subcommands/work/index.ts @@ -10,6 +10,7 @@ import CreditsManager from "../../../../handlers/CreditsManager"; import prisma from "../../../../handlers/prisma"; import generateCooldownName from "../../../../helpers/generateCooldownName"; import deferReply from "../../../../utils/deferReply"; +import { GuildNotFoundError } from "../../../../utils/errors"; import sendResponse from "../../../../utils/sendResponse"; import jobs from "./jobs"; @@ -28,18 +29,7 @@ export const execute = async (interaction: ChatInputCommandInteraction) => { const { guild, user } = interaction; await deferReply(interaction, false); - - if (!guild) { - throw new Error( - "Oops! It seems like you're not part of a guild. Join a guild to use this command!" - ); - } - - if (!user) { - throw new Error( - "Oops! It looks like we couldn't find your user information. Please try again or contact support for assistance." - ); - } + if (!guild) throw new GuildNotFoundError(); const chance = new Chance(); diff --git a/src/commands/manage/groups/credits/subcommands/give/index.ts b/src/commands/manage/groups/credits/subcommands/give/index.ts index 472e792..b371590 100644 --- a/src/commands/manage/groups/credits/subcommands/give/index.ts +++ b/src/commands/manage/groups/credits/subcommands/give/index.ts @@ -7,6 +7,7 @@ import { import CreditsManager from "../../../../../../handlers/CreditsManager"; import checkPermission from "../../../../../../utils/checkPermission"; import deferReply from "../../../../../../utils/deferReply"; +import { GuildNotFoundError } from "../../../../../../utils/errors"; import sendResponse from "../../../../../../utils/sendResponse"; const creditsManager = new CreditsManager(); @@ -40,19 +41,11 @@ export const execute = async ( await deferReply(interaction, false); checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - - if (!guild) { - throw new Error("We could not get the current guild from Discord."); - } + if (!guild) throw new GuildNotFoundError(); const discordReceiver = options.getUser("user", true); const creditsAmount = options.getInteger("amount", true); - if (!discordReceiver || typeof creditsAmount !== "number") { - await sendResponse(interaction, "Invalid user or credit amount provided."); - return; - } - const embedSuccess = new EmbedBuilder() .setColor(process.env.EMBED_COLOR_SUCCESS) .setAuthor({ name: "💳 Credits Manager" }) diff --git a/src/commands/manage/groups/credits/subcommands/giveaway/index.ts b/src/commands/manage/groups/credits/subcommands/giveaway/index.ts index 70629e0..14355b3 100644 --- a/src/commands/manage/groups/credits/subcommands/giveaway/index.ts +++ b/src/commands/manage/groups/credits/subcommands/giveaway/index.ts @@ -14,6 +14,7 @@ import { v4 as uuidv4 } from "uuid"; import CtrlPanelAPI from "../../../../../../services/CtrlPanelAPI"; import checkPermission from "../../../../../../utils/checkPermission"; import deferReply from "../../../../../../utils/deferReply"; +import { GuildNotFoundError } from "../../../../../../utils/errors"; import sendResponse from "../../../../../../utils/sendResponse"; // Function @@ -47,18 +48,13 @@ export const execute = async (interaction: ChatInputCommandInteraction) => { await deferReply(interaction, true); checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); + if (!guild) throw new GuildNotFoundError(); - if (!guild) throw new Error("This command can only be used in guilds"); const ctrlPanelAPI = new CtrlPanelAPI(guild); - const uses = options?.getInteger("uses"); - const creditAmount = options?.getInteger("credit"); - const channel = options?.getChannel("channel"); - - if (!uses) throw new Error("Amount of uses is required."); - if (!creditAmount) throw new Error("Amount of credits is required."); - if (!channel) throw new Error("Channel is required."); - if (!guild) throw new Error("Guild is required."); + const uses = options?.getInteger("uses", true); + const creditAmount = options?.getInteger("credit", true); + const channel = options?.getChannel("channel", true); const embedSuccess = new EmbedBuilder() .setTitle(":toolbox:︱Giveaway") diff --git a/src/commands/manage/groups/credits/subcommands/set/index.ts b/src/commands/manage/groups/credits/subcommands/set/index.ts index 9cf342a..af35b6f 100644 --- a/src/commands/manage/groups/credits/subcommands/set/index.ts +++ b/src/commands/manage/groups/credits/subcommands/set/index.ts @@ -7,6 +7,7 @@ import { import CreditsManager from "../../../../../../handlers/CreditsManager"; import checkPermission from "../../../../../../utils/checkPermission"; import deferReply from "../../../../../../utils/deferReply"; +import { GuildNotFoundError } from "../../../../../../utils/errors"; import sendResponse from "../../../../../../utils/sendResponse"; const creditsManager = new CreditsManager(); @@ -38,18 +39,10 @@ export const execute = async ( await deferReply(interaction, false); checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); + if (!guild) throw new GuildNotFoundError(); - if (!guild) { - throw new Error("We could not get the current guild from Discord."); - } - - const discordReceiver = options.getUser("user"); - const creditsAmount = options.getInteger("amount"); - - if (!discordReceiver || typeof creditsAmount !== "number") { - await sendResponse(interaction, "Invalid user or credit amount provided."); - return; - } + const discordReceiver = options.getUser("user", true); + const creditsAmount = options.getInteger("amount", true); const embedSuccess = new EmbedBuilder() .setColor(process.env.EMBED_COLOR_SUCCESS) diff --git a/src/commands/manage/groups/credits/subcommands/take/index.ts b/src/commands/manage/groups/credits/subcommands/take/index.ts index eb815d9..2df72d7 100644 --- a/src/commands/manage/groups/credits/subcommands/take/index.ts +++ b/src/commands/manage/groups/credits/subcommands/take/index.ts @@ -7,6 +7,7 @@ import { import CreditsManager from "../../../../../../handlers/CreditsManager"; import checkPermission from "../../../../../../utils/checkPermission"; import deferReply from "../../../../../../utils/deferReply"; +import { GuildNotFoundError } from "../../../../../../utils/errors"; import sendResponse from "../../../../../../utils/sendResponse"; const creditsManager = new CreditsManager(); @@ -38,18 +39,10 @@ export const execute = async ( await deferReply(interaction, false); checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); + if (!guild) throw new GuildNotFoundError(); - if (!guild) { - throw new Error("We could not get the current guild from Discord."); - } - - const discordReceiver = options.getUser("user"); - const creditsAmount = options.getInteger("amount"); - - if (!discordReceiver || typeof creditsAmount !== "number") { - await sendResponse(interaction, "Invalid user or credit amount provided."); - return; - } + const discordReceiver = options.getUser("user", true); + const creditsAmount = options.getInteger("amount", true); const embedSuccess = new EmbedBuilder() .setColor(process.env.EMBED_COLOR_SUCCESS) diff --git a/src/commands/manage/groups/credits/subcommands/transfer/index.ts b/src/commands/manage/groups/credits/subcommands/transfer/index.ts index 9a0a00e..3af877d 100644 --- a/src/commands/manage/groups/credits/subcommands/transfer/index.ts +++ b/src/commands/manage/groups/credits/subcommands/transfer/index.ts @@ -7,6 +7,7 @@ import { import CreditsManager from "../../../../../../handlers/CreditsManager"; import checkPermission from "../../../../../../utils/checkPermission"; import deferReply from "../../../../../../utils/deferReply"; +import { GuildNotFoundError } from "../../../../../../utils/errors"; import sendResponse from "../../../../../../utils/sendResponse"; const creditsManager = new CreditsManager(); @@ -44,18 +45,11 @@ export const execute = async ( await deferReply(interaction, false); checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); + if (!guild) throw new GuildNotFoundError(); - if (!guild) { - throw new Error("We could not get the current guild from Discord."); - } - - const fromUser = options.getUser("from-user"); - const toUser = options.getUser("to-user"); - const creditsAmount = options.getInteger("amount"); - - if (!fromUser || !toUser || typeof creditsAmount !== "number") { - throw new Error("Invalid user(s) or credit amount provided."); - } + const fromUser = options.getUser("from-user", true); + const toUser = options.getUser("to-user", true); + const creditsAmount = options.getInteger("amount", true); const transactionResult = await creditsManager.transfer( guild, diff --git a/src/commands/moderation/subcommands/prune/index.ts b/src/commands/moderation/subcommands/prune/index.ts index db112d7..068062f 100644 --- a/src/commands/moderation/subcommands/prune/index.ts +++ b/src/commands/moderation/subcommands/prune/index.ts @@ -8,6 +8,10 @@ import { } from "discord.js"; import checkPermission from "../../../../utils/checkPermission"; import deferReply from "../../../../utils/deferReply"; +import { + ChannelNotFoundError, + GuildNotFoundError, +} from "../../../../utils/errors"; import sendResponse from "../../../../utils/sendResponse"; // Function @@ -31,23 +35,23 @@ export const builder = (command: SlashCommandSubcommandBuilder) => { }; export const execute = async (interaction: ChatInputCommandInteraction) => { - const { user, options, channel } = interaction; - if (!channel) { - throw new Error("The bot failed to find the channel to prune messages in."); - } + const { guild, user, options, channel } = interaction; await deferReply(interaction, false); checkPermission(interaction, PermissionsBitField.Flags.ManageMessages); + if (!guild) throw new GuildNotFoundError(); + if (!channel) throw new ChannelNotFoundError(); - const count = options.getInteger("count"); + const count = options.getInteger("count", true); const bots = options.getBoolean("bots"); - if (!count || count < 1 || count > 99) { + if (count < 1 || count > 99) { throw new Error( "Please provide a number between 1 and 99 for the prune command." ); } - if (channel.type !== ChannelType.GuildText) return; + if (channel.type !== ChannelType.GuildText) + throw new Error("This channel is not a text channel in a guild!"); const messagesToDelete = await channel.messages .fetch({ limit: count + 1 }) // Fetch count + 1 messages to exclude the interaction message itself diff --git a/src/commands/quotes/subcommands/post/index.ts b/src/commands/quotes/subcommands/post/index.ts index 644ac84..de21a97 100644 --- a/src/commands/quotes/subcommands/post/index.ts +++ b/src/commands/quotes/subcommands/post/index.ts @@ -10,6 +10,10 @@ import prisma from "../../../../handlers/prisma"; import generateCooldownName from "../../../../helpers/generateCooldownName"; import upsertGuildMember from "../../../../helpers/upsertGuildMember"; import deferReply from "../../../../utils/deferReply"; +import { + ChannelNotFoundError, + GuildNotFoundError, +} from "../../../../utils/errors"; import sendResponse from "../../../../utils/sendResponse"; const cooldownManager = new CooldownManager(); @@ -35,16 +39,16 @@ export const builder = (command: SlashCommandSubcommandBuilder) => { export const execute = async ( interaction: ChatInputCommandInteraction ): Promise => { - await deferReply(interaction, true); - const { options, guild, user } = interaction; - if (!guild) throw new Error("A guild is required."); + + await deferReply(interaction, true); + if (!guild) throw new GuildNotFoundError(); const quoteUser = options.getUser("user", true); const quoteString = options.getString("message", true); if (quoteUser.id == user.id) throw new Error("One cannot quote oneself."); - + await upsertGuildMember(guild, user); await upsertGuildMember(guild, quoteUser); @@ -61,7 +65,7 @@ export const execute = async ( guildQuotesSettings.quoteChannelId ); - if (!channel) throw new Error("No channel found."); + if (!channel) throw new ChannelNotFoundError(); if (channel.type !== ChannelType.GuildText) throw new Error("The channel is not a text channel."); diff --git a/src/commands/reputation/subcommands/check/index.ts b/src/commands/reputation/subcommands/check/index.ts index 6259da8..c711f46 100644 --- a/src/commands/reputation/subcommands/check/index.ts +++ b/src/commands/reputation/subcommands/check/index.ts @@ -22,14 +22,11 @@ export const builder = (command: SlashCommandSubcommandBuilder) => { }; export const execute = async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, false); - const { options, user } = interaction; + await deferReply(interaction, false); const checkUser = options.getUser("user") || user; - if (!user) throw new Error("User unavailable"); - const userReputation = await reputationManager.check(checkUser); const interactionEmbed = new EmbedBuilder() diff --git a/src/commands/reputation/subcommands/repute/index.ts b/src/commands/reputation/subcommands/repute/index.ts index 3708b11..84c3cb8 100644 --- a/src/commands/reputation/subcommands/repute/index.ts +++ b/src/commands/reputation/subcommands/repute/index.ts @@ -8,6 +8,7 @@ import CooldownManager from "../../../../handlers/CooldownManager"; import ReputationManager from "../../../../handlers/ReputationManager"; import generateCooldownName from "../../../../helpers/generateCooldownName"; import deferReply from "../../../../utils/deferReply"; +import { GuildNotFoundError } from "../../../../utils/errors"; import sendResponse from "../../../../utils/sendResponse"; const cooldownManager = new CooldownManager(); @@ -37,21 +38,13 @@ export const builder = (command: SlashCommandSubcommandBuilder) => { export const execute = async (interaction: ChatInputCommandInteraction) => { const { options, user, guild } = interaction; - await deferReply(interaction, true); - if (!guild) { - throw new Error("This command can only be used in guilds"); - } + await deferReply(interaction, true); + if (!guild) throw new GuildNotFoundError(); const targetUser = options.getUser("user", true); const reputationType = options.getString("type", true); - if (!targetUser) { - throw new Error( - "Sorry, we were unable to find the user you are trying to give reputation to." - ); - } - if (reputationType !== "positive" && reputationType !== "negative") { throw new Error("Invalid reputation type"); } diff --git a/src/commands/settings/subcommands/credits/index.ts b/src/commands/settings/subcommands/credits/index.ts index aeda841..fdde4c4 100644 --- a/src/commands/settings/subcommands/credits/index.ts +++ b/src/commands/settings/subcommands/credits/index.ts @@ -7,6 +7,7 @@ import { import prisma from "../../../../handlers/prisma"; import checkPermission from "../../../../utils/checkPermission"; import deferReply from "../../../../utils/deferReply"; +import { GuildNotFoundError } from "../../../../utils/errors"; import sendResponse from "../../../../utils/sendResponse"; export const builder = (command: SlashCommandSubcommandBuilder) => { @@ -32,26 +33,14 @@ export const builder = (command: SlashCommandSubcommandBuilder) => { }; export const execute = async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - const { guild, options, user } = interaction; - const workBonusChance = options.getNumber("work-bonus-chance"); - const workPenaltyChance = options.getNumber("work-penalty-chance"); + await deferReply(interaction, true); + checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); + if (!guild) throw new GuildNotFoundError(); - if (!guild) { - throw new Error("Guild not found."); - } - - if (typeof workBonusChance !== "number") { - throw new Error("Work Bonus Chance must be a number."); - } - - if (typeof workPenaltyChance !== "number") { - throw new Error("Work Penalty Chance must be a number."); - } + const workBonusChance = options.getNumber("work-bonus-chance", true); + const workPenaltyChance = options.getNumber("work-penalty-chance", true); const upsertGuildCreditsSettings = await prisma.guildCreditsSettings.upsert({ where: { diff --git a/src/commands/settings/subcommands/ctrlpanel/index.ts b/src/commands/settings/subcommands/ctrlpanel/index.ts index 130b8b8..889df0d 100644 --- a/src/commands/settings/subcommands/ctrlpanel/index.ts +++ b/src/commands/settings/subcommands/ctrlpanel/index.ts @@ -9,6 +9,7 @@ import CtrlPanelAPI, { } from "../../../../services/CtrlPanelAPI"; import checkPermission from "../../../../utils/checkPermission"; import deferReply from "../../../../utils/deferReply"; +import { GuildNotFoundError } from "../../../../utils/errors"; import logger from "../../../../utils/logger"; import sendResponse from "../../../../utils/sendResponse"; @@ -35,12 +36,11 @@ export const builder = (command: SlashCommandSubcommandBuilder) => { }; export const execute = async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - const { guild, options, user } = interaction; - if (!guild) throw new Error("Guild unavailable"); + + await deferReply(interaction, true); + checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); + if (!guild) throw new GuildNotFoundError(); const scheme = options.getString("scheme", true); const domain = options.getString("domain", true); diff --git a/src/commands/settings/subcommands/quotes/index.ts b/src/commands/settings/subcommands/quotes/index.ts index 5b086fb..09e4411 100644 --- a/src/commands/settings/subcommands/quotes/index.ts +++ b/src/commands/settings/subcommands/quotes/index.ts @@ -7,6 +7,7 @@ import { import prisma from "../../../../handlers/prisma"; import checkPermission from "../../../../utils/checkPermission"; import deferReply from "../../../../utils/deferReply"; +import { GuildNotFoundError } from "../../../../utils/errors"; import sendResponse from "../../../../utils/sendResponse"; export const builder = (command: SlashCommandSubcommandBuilder) => { @@ -22,19 +23,15 @@ export const builder = (command: SlashCommandSubcommandBuilder) => { }; export const execute = async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - const { guild, options, user } = interaction; + await deferReply(interaction, true); + checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); + if (!guild) throw new GuildNotFoundError(); + const quoteStatus = options.getBoolean("status", true); const quoteChannel = options.getChannel("channel", true); - if (!guild) { - throw new Error("Guild not found."); - } - const upsertGuildQuotesSettings = await prisma.guildQuotesSettings.upsert({ where: { id: guild.id, diff --git a/src/commands/shop/subcommands/ctrlpanel.ts b/src/commands/shop/subcommands/ctrlpanel.ts index e454483..ddb6be0 100644 --- a/src/commands/shop/subcommands/ctrlpanel.ts +++ b/src/commands/shop/subcommands/ctrlpanel.ts @@ -11,6 +11,7 @@ import { v4 as uuidv4 } from "uuid"; import CreditsManager from "../../../handlers/CreditsManager"; import CtrlPanelAPI from "../../../services/CtrlPanelAPI"; import deferReply from "../../../utils/deferReply"; +import { GuildNotFoundError } from "../../../utils/errors"; import sendResponse from "../../../utils/sendResponse"; const creditsManager = new CreditsManager(); @@ -30,15 +31,13 @@ export const builder = (command: SlashCommandSubcommandBuilder) => { }; export const execute = async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - const { options, guild, user, client } = interaction; - if (!guild) throw new Error("This command can only be executed in a guild"); + + await deferReply(interaction, true); + if (!guild) throw new GuildNotFoundError(); const ctrlPanelAPI = new CtrlPanelAPI(guild); - const withdrawalAmount = options.getInteger("withdraw", true); - await creditsManager.take(guild, user, withdrawalAmount); const voucherCode = uuidv4(); diff --git a/src/commands/utils/subcommands/about/index.ts b/src/commands/utils/subcommands/about/index.ts index eb11307..cd72331 100644 --- a/src/commands/utils/subcommands/about/index.ts +++ b/src/commands/utils/subcommands/about/index.ts @@ -8,6 +8,7 @@ import { SlashCommandSubcommandBuilder, } from "discord.js"; import deferReply from "../../../../utils/deferReply"; +import { GuildNotFoundError } from "../../../../utils/errors"; import sendResponse from "../../../../utils/sendResponse"; export const builder = (command: SlashCommandSubcommandBuilder) => { @@ -17,13 +18,10 @@ export const builder = (command: SlashCommandSubcommandBuilder) => { }; export const execute = async (interaction: CommandInteraction) => { - await deferReply(interaction, false); - const { user, guild, client } = interaction; - if (!guild) { - throw new Error("This command is only available in guilds"); - } + await deferReply(interaction, false); + if (!guild) throw new GuildNotFoundError(); const guildCount = client.guilds.cache.size; const memberCount = client.guilds.cache.reduce( diff --git a/src/commands/utils/subcommands/avatar/index.ts b/src/commands/utils/subcommands/avatar/index.ts index 975167e..b46e049 100644 --- a/src/commands/utils/subcommands/avatar/index.ts +++ b/src/commands/utils/subcommands/avatar/index.ts @@ -18,12 +18,10 @@ export const builder = (command: SlashCommandSubcommandBuilder) => { }; export const execute = async (interaction: CommandInteraction) => { - await deferReply(interaction, false); - const { options, user } = interaction; + await deferReply(interaction, false); const userOption = options.getUser("user"); - const targetUser = userOption || user; const embed = new EmbedBuilder() diff --git a/src/utils/ensureGuildExists.ts b/src/utils/ensureGuildExists.ts new file mode 100644 index 0000000..276b03c --- /dev/null +++ b/src/utils/ensureGuildExists.ts @@ -0,0 +1,10 @@ +import { Guild, Interaction } from "discord.js"; + +export default function ensureGuildExists(interaction: Interaction): Guild { + if (!interaction.guild) { + throw new Error( + "Oops! It looks like you're not part of a guild. Join a guild to embark on this adventure!" + ); + } + return interaction.guild; +} diff --git a/src/utils/ensureUserExists.ts b/src/utils/ensureUserExists.ts new file mode 100644 index 0000000..54bac32 --- /dev/null +++ b/src/utils/ensureUserExists.ts @@ -0,0 +1,10 @@ +import { Interaction, User } from "discord.js"; + +export default function ensureUserExists(interaction: Interaction): User { + if (!interaction.user) { + throw new Error( + "Oops! We couldn't find your user information. Please try again or contact support for assistance." + ); + } + return interaction.user; +} diff --git a/src/utils/errors.ts b/src/utils/errors.ts new file mode 100644 index 0000000..444641c --- /dev/null +++ b/src/utils/errors.ts @@ -0,0 +1,32 @@ +class CustomError extends Error { + constructor(message: string) { + super(message); + this.name = this.constructor.name; + } +} + +class GuildNotFoundError extends CustomError { + constructor() { + super( + "Guild not found: You are not part of a guild. Join a guild to embark on this adventure." + ); + } +} + +class UserNotFoundError extends CustomError { + constructor() { + super( + "User not found: We couldn't retrieve your user information. Please try again or contact support for assistance." + ); + } +} + +class ChannelNotFoundError extends CustomError { + constructor() { + super( + "Channel not found: We couldn't retrieve the channel. Please try again or contact support for assistance." + ); + } +} + +export { GuildNotFoundError, UserNotFoundError, ChannelNotFoundError };