diff --git a/src/commands/Moderation/ban.js b/src/commands/Moderation/ban.js index 657359233..884081b22 100644 --- a/src/commands/Moderation/ban.js +++ b/src/commands/Moderation/ban.js @@ -1,10 +1,10 @@ -import { SlashCommandBuilder, PermissionFlagsBits, PermissionsBitField, ChannelType } from 'discord.js'; -import { createEmbed, errorEmbed, successEmbed, infoEmbed, warningEmbed } from '../../utils/embeds.js'; +import { SlashCommandBuilder, PermissionFlagsBits } from 'discord.js'; +import { errorEmbed, successEmbed } from '../../utils/embeds.js'; import { logModerationAction } from '../../utils/moderation.js'; import { logger } from '../../utils/logger.js'; import { InteractionHelper } from '../../utils/interactionHelper.js'; -import { ModerationService } from '../../services/moderationService.js'; import { handleInteractionError } from '../../utils/errorHandler.js'; + export default { data: new SlashCommandBuilder() .setName("ban") @@ -18,43 +18,85 @@ export default { .addStringOption((option) => option.setName("reason").setDescription("Reason for the ban"), ) -.setDefaultMemberPermissions(PermissionFlagsBits.BanMembers), + .setDefaultMemberPermissions(PermissionFlagsBits.BanMembers), category: "moderation", async execute(interaction, config, client) { + const deferSuccess = await InteractionHelper.safeDefer(interaction); + if (!deferSuccess) { + logger.warn(`Ban interaction defer failed`, { + userId: interaction.user.id, + guildId: interaction.guildId, + commandName: 'ban' + }); + return; + } + try { - const user = interaction.options.getUser("target"); + if (!interaction.member.permissions.has(PermissionFlagsBits.BanMembers)) { + throw new Error("You do not have permission to ban members."); + } + + const targetUser = interaction.options.getUser("target"); const reason = interaction.options.getString("reason") || "No reason provided"; - if (user.id === interaction.user.id) { + if (!targetUser) { + throw new Error("Could not find the target user."); + } + + if (targetUser.id === interaction.user.id) { throw new Error("You cannot ban yourself."); } - if (user.id === client.user.id) { + + if (targetUser.id === client.user.id) { throw new Error("You cannot ban the bot."); } - - const result = await ModerationService.banUser({ + // Ban the user + await interaction.guild.bans.create(targetUser.id, { reason }); + + const caseId = await logModerationAction({ + client, guild: interaction.guild, - user, - moderator: interaction.member, - reason + event: { + action: "Member Banned", + target: `${targetUser.tag} (${targetUser.id})`, + executor: `${interaction.user.tag} (${interaction.user.id})`, + reason: reason, + metadata: { + userId: targetUser.id, + moderatorId: interaction.user.id, + } + } }); - await InteractionHelper.universalReply(interaction, { + await InteractionHelper.safeEditReply(interaction, { embeds: [ successEmbed( - `🚫 **Banned** ${user.tag}`, - `**Reason:** ${reason}\n**Case ID:** #${result.caseId}`, + `🚫 **Banned** ${targetUser.tag}`, + `**Reason:** ${reason}\n**Case ID:** #${caseId}`, ), ], }); + + logger.info('User banned', { + guildId: interaction.guildId, + userId: targetUser.id, + moderatorId: interaction.user.id, + reason: reason + }); + } catch (error) { logger.error('Ban command error:', error); - await handleInteractionError(interaction, error, { subtype: 'ban_failed' }); + await InteractionHelper.safeEditReply(interaction, { + embeds: [ + errorEmbed( + "Ban Failed", + error.message || "An unexpected error occurred during the ban action. Please check my role permissions." + ), + ], + }); } }, }; - - diff --git a/src/commands/Moderation/kick.js b/src/commands/Moderation/kick.js index d1902f906..6d7926516 100644 --- a/src/commands/Moderation/kick.js +++ b/src/commands/Moderation/kick.js @@ -1,125 +1,126 @@ -import { SlashCommandBuilder, PermissionFlagsBits, PermissionsBitField, ChannelType } from 'discord.js'; -import { createEmbed, errorEmbed, successEmbed, infoEmbed, warningEmbed } from '../../utils/embeds.js'; +import { SlashCommandBuilder, PermissionFlagsBits } from 'discord.js'; +import { errorEmbed, successEmbed } from '../../utils/embeds.js'; import { logModerationAction } from '../../utils/moderation.js'; import { logger } from '../../utils/logger.js'; -import { InteractionHelper } from '../../utils/interactionHelper.js'; import { TitanBotError, ErrorTypes } from '../../utils/errorHandler.js'; +import { InteractionHelper } from '../../utils/interactionHelper.js'; export default { data: new SlashCommandBuilder() - .setName("kick") - .setDescription("Kick a user from the server") - .addUserOption((option) => - option - .setName("target") - .setDescription("The user to kick") - .setRequired(true), - ) - .addStringOption((option) => - option.setName("reason").setDescription("Reason for the kick"), - ) -.setDefaultMemberPermissions(PermissionFlagsBits.KickMembers), - category: "moderation", + .setName("kick") + .setDescription("Kick a user from the server") + .addUserOption((option) => + option + .setName("target") + .setDescription("The user to kick") + .setRequired(true), + ) + .addStringOption((option) => + option.setName("reason").setDescription("Reason for the kick"), + ) + .setDefaultMemberPermissions(PermissionFlagsBits.KickMembers), + category: "moderation", - async execute(interaction, config, client) { - try { - - if (!interaction.member.permissions.has(PermissionFlagsBits.KickMembers)) { - throw new TitanBotError( - "User lacks permission", - ErrorTypes.PERMISSION, - "You do not have permission to kick members." - ); - } + async execute(interaction, config, client) { + const deferSuccess = await InteractionHelper.safeDefer(interaction); + if (!deferSuccess) { + logger.warn(`Kick interaction defer failed`, { + userId: interaction.user.id, + guildId: interaction.guildId, + commandName: 'kick' + }); + return; + } - const targetUser = interaction.options.getUser("target"); - const member = interaction.options.getMember("target"); - const reason = interaction.options.getString("reason") || "No reason provided"; + try { + if (!interaction.member.permissions.has(PermissionFlagsBits.KickMembers)) { + throw new TitanBotError( + "User lacks permission", + ErrorTypes.PERMISSION, + "You do not have permission to kick members." + ); + } - - if (targetUser.id === interaction.user.id) { - throw new TitanBotError( - "Cannot kick self", - ErrorTypes.VALIDATION, - "You cannot kick yourself." - ); - } + const targetUser = interaction.options.getUser("target"); + const member = interaction.options.getMember("target"); + const reason = interaction.options.getString("reason") || "No reason provided"; - - if (targetUser.id === client.user.id) { - throw new TitanBotError( - "Cannot kick bot", - ErrorTypes.VALIDATION, - "You cannot kick the bot." - ); - } + if (!targetUser) { + throw new TitanBotError( + "Target not found", + ErrorTypes.USER_INPUT, + "Could not find the target user." + ); + } - - if (!member) { - throw new TitanBotError( - "Target not found", - ErrorTypes.USER_INPUT, - "The target user is not currently in this server.", - { subtype: 'user_not_found' } - ); - } + if (targetUser.id === interaction.user.id) { + throw new TitanBotError( + "Cannot kick self", + ErrorTypes.VALIDATION, + "You cannot kick yourself." + ); + } - - if (interaction.member.roles.highest.position <= member.roles.highest.position) { - throw new TitanBotError( - "Cannot kick user", - ErrorTypes.PERMISSION, - "You cannot kick a user with an equal or higher role than you." - ); - } + if (targetUser.id === client.user.id) { + throw new TitanBotError( + "Cannot kick bot", + ErrorTypes.VALIDATION, + "You cannot kick the bot." + ); + } - - if (!member.kickable) { - throw new TitanBotError( - "Bot cannot kick", - ErrorTypes.PERMISSION, - "I cannot kick this user. Please check my role position relative to the target user." - ); - } + if (!member) { + throw new TitanBotError( + "Target not found", + ErrorTypes.USER_INPUT, + "The target user is not currently in this server." + ); + } - - await member.kick(reason); + if (!member.kickable) { + throw new TitanBotError( + "Cannot kick member", + ErrorTypes.PERMISSION, + "I cannot kick this user. They might have a higher role than me or you." + ); + } - - const caseId = await logModerationAction({ - client, - guild: interaction.guild, - event: { - action: "Member Kicked", - target: `${targetUser.tag} (${targetUser.id})`, - executor: `${interaction.user.tag} (${interaction.user.id})`, - reason, - metadata: { - userId: targetUser.id, - moderatorId: interaction.user.id - } - } - }); + await member.kick(reason); - - await InteractionHelper.universalReply(interaction, { - embeds: [ - successEmbed( - `👢 **Kicked** ${targetUser.tag}`, - `**Reason:** ${reason}\n**Case ID:** #${caseId}`, - ), - ], - }); - } catch (error) { - logger.error('Kick command error:', error); - const errorEmbed_default = errorEmbed( - "An unexpected error occurred while trying to kick the user.", - error.message || "Could not kick the user" - ); - await InteractionHelper.universalReply(interaction, { embeds: [errorEmbed_default] }); + const caseId = await logModerationAction({ + client, + guild: interaction.guild, + event: { + action: "Member Kicked", + target: `${targetUser.tag} (${targetUser.id})`, + executor: `${interaction.user.tag} (${interaction.user.id})`, + reason: reason, + metadata: { + userId: targetUser.id, + moderatorId: interaction.user.id, + } + } + }); + + await InteractionHelper.safeEditReply(interaction, { + embeds: [ + successEmbed( + `👢 **Kicked** ${targetUser.tag}`, + `**Reason:** ${reason}\n**Case ID:** #${caseId}`, + ), + ], + }); + } catch (error) { + logger.error('Kick command error:', error); + await InteractionHelper.safeEditReply(interaction, { + embeds: [ + errorEmbed( + "Kick Failed", + error.userMessage || "An unexpected error occurred during the kick action. Please check my role permissions." + ), + ], + }); + } } - } }; - - diff --git a/src/commands/Moderation/timeout.js b/src/commands/Moderation/timeout.js index 04f205a3f..f18160445 100644 --- a/src/commands/Moderation/timeout.js +++ b/src/commands/Moderation/timeout.js @@ -1,11 +1,10 @@ -import { SlashCommandBuilder, PermissionFlagsBits, PermissionsBitField, ChannelType } from 'discord.js'; -import { createEmbed, errorEmbed, successEmbed, infoEmbed, warningEmbed } from '../../utils/embeds.js'; +import { SlashCommandBuilder, PermissionFlagsBits } from 'discord.js'; +import { errorEmbed, successEmbed } from '../../utils/embeds.js'; import { logModerationAction } from '../../utils/moderation.js'; import { logger } from '../../utils/logger.js'; import { TitanBotError, ErrorTypes } from '../../utils/errorHandler.js'; - - import { InteractionHelper } from '../../utils/interactionHelper.js'; + const durationChoices = [ { name: "5 minutes", value: 5 }, { name: "10 minutes", value: 10 }, @@ -15,6 +14,7 @@ const durationChoices = [ { name: "1 day", value: 1440 }, { name: "1 week", value: 10080 }, ]; + export default { data: new SlashCommandBuilder() .setName("timeout") @@ -25,18 +25,17 @@ export default { .setDescription("User to timeout") .setRequired(true), ) - .addIntegerOption( - (option) => - option - .setName("duration") - .setDescription("Duration of the timeout") - .setRequired(true) -.addChoices(...durationChoices), + .addIntegerOption((option) => + option + .setName("duration") + .setDescription("Duration of the timeout") + .setRequired(true) + .addChoices(...durationChoices), ) .addStringOption((option) => option.setName("reason").setDescription("Reason for the timeout"), ) -.setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers), + .setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers), category: "moderation", async execute(interaction, config, client) { @@ -64,6 +63,14 @@ export default { const durationMinutes = interaction.options.getInteger("duration"); const reason = interaction.options.getString("reason") || "No reason provided"; + if (!targetUser) { + throw new TitanBotError( + "Target not found", + ErrorTypes.USER_INPUT, + "Could not find the target user." + ); + } + if (targetUser.id === interaction.user.id) { throw new TitanBotError( "Cannot timeout self", @@ -71,6 +78,7 @@ export default { "You cannot timeout yourself." ); } + if (targetUser.id === client.user.id) { throw new TitanBotError( "Cannot timeout bot", @@ -78,6 +86,7 @@ export default { "You cannot timeout the bot." ); } + if (!member) { throw new TitanBotError( "Target not found", @@ -132,7 +141,8 @@ export default { await InteractionHelper.safeEditReply(interaction, { embeds: [ errorEmbed( - error.userMessage || "An unexpected error occurred during the timeout action. Please check my role permissions.", + "Timeout Failed", + error.userMessage || "An unexpected error occurred during the timeout action. Please check my role permissions." ), ], }); @@ -140,5 +150,3 @@ export default { } }; - - diff --git a/src/commands/Moderation/warn.js b/src/commands/Moderation/warn.js index 571214ece..d797ec150 100644 --- a/src/commands/Moderation/warn.js +++ b/src/commands/Moderation/warn.js @@ -1,10 +1,11 @@ -import { SlashCommandBuilder, PermissionFlagsBits, PermissionsBitField, ChannelType, MessageFlags } from 'discord.js'; -import { createEmbed, errorEmbed, successEmbed, infoEmbed, warningEmbed } from '../../utils/embeds.js'; +import { SlashCommandBuilder, PermissionFlagsBits } from 'discord.js'; +import { errorEmbed, successEmbed } from '../../utils/embeds.js'; import { logModerationAction } from '../../utils/moderation.js'; import { logger } from '../../utils/logger.js'; import { WarningService } from '../../services/warningService.js'; import { handleInteractionError } from '../../utils/errorHandler.js'; import { InteractionHelper } from '../../utils/interactionHelper.js'; + export default { data: new SlashCommandBuilder() .setName("warn") @@ -36,67 +37,85 @@ export default { } try { - if (!interaction.member.permissions.has(PermissionFlagsBits.ModerateMembers)) { - throw new Error("You need the `Moderate Members` permission to issue warnings."); - } + if (!interaction.member.permissions.has(PermissionFlagsBits.ModerateMembers)) { + throw new Error("You need the `Moderate Members` permission to issue warnings."); + } - const target = interaction.options.getUser("target"); - const member = interaction.options.getMember("target"); - const reason = interaction.options.getString("reason"); - const moderator = interaction.user; - const guildId = interaction.guildId; + const target = interaction.options.getUser("target"); + const member = interaction.options.getMember("target"); + const reason = interaction.options.getString("reason"); + const moderator = interaction.user; + const guildId = interaction.guildId; - if (!member) { - throw new Error("The target user is not currently in this server."); - } + if (!target) { + throw new Error("Could not find the target user."); + } - - const result = await WarningService.addWarning({ - guildId, - userId: target.id, - moderatorId: moderator.id, - reason, - timestamp: Date.now() - }); + if (!member) { + throw new Error("The target user is not currently in this server."); + } - if (!result.success) { - throw new Error("Failed to store warning in database"); - } + // Add warning + const result = await WarningService.addWarning({ + guildId, + userId: target.id, + moderatorId: moderator.id, + reason, + timestamp: Date.now() + }); + + if (!result.success) { + throw new Error("Failed to store warning in database"); + } - const totalWarns = result.totalCount; + const totalWarns = result.totalCount; - await logModerationAction({ - client, - guild: interaction.guild, - event: { - action: "User Warned", - target: `${target.tag} (${target.id})`, - executor: `${moderator.tag} (${moderator.id})`, - reason, - metadata: { - userId: target.id, - moderatorId: moderator.id, - totalWarns, - warningNumber: totalWarns, - warningId: result.id - } + await logModerationAction({ + client, + guild: interaction.guild, + event: { + action: "User Warned", + target: `${target.tag} (${target.id})`, + executor: `${moderator.tag} (${moderator.id})`, + reason, + metadata: { + userId: target.id, + moderatorId: moderator.id, + totalWarns, + warningNumber: totalWarns, + warningId: result.id } - }); + } + }); + + await InteractionHelper.safeEditReply(interaction, { + embeds: [ + successEmbed( + `⚠️ **Warned** ${target.tag}`, + `**Reason:** ${reason}\n**Total Warns:** ${totalWarns}`, + ), + ], + }); + + logger.info('User warned', { + guildId: interaction.guildId, + userId: target.id, + moderatorId: moderator.id, + reason: reason, + totalWarns: totalWarns + }); - await InteractionHelper.safeEditReply(interaction, { - embeds: [ - successEmbed( - `⚠️ **Warned** ${target.tag}`, - `**Reason:** ${reason}\n**Total Warns:** ${totalWarns}`, - ), - ], - }); } catch (error) { logger.error('Warn command error:', error); - await handleInteractionError(interaction, error, { subtype: 'warn_failed' }); + await InteractionHelper.safeEditReply(interaction, { + embeds: [ + errorEmbed( + "Warning Failed", + error.message || "An unexpected error occurred while issuing the warning." + ), + ], + }); } } }; - - diff --git a/src/commands/Ticket/ticket.js b/src/commands/Ticket/ticket.js index e3a1a5015..9fcb0ee92 100644 --- a/src/commands/Ticket/ticket.js +++ b/src/commands/Ticket/ticket.js @@ -1,6 +1,16 @@ +```js import { getColor } from '../../config/bot.js'; -import { SlashCommandBuilder, PermissionFlagsBits, PermissionsBitField, ChannelType, ActionRowBuilder, ButtonBuilder, ButtonStyle, MessageFlags } from 'discord.js'; -import { createEmbed, errorEmbed, successEmbed, infoEmbed, warningEmbed } from '../../utils/embeds.js'; +import { + SlashCommandBuilder, + PermissionFlagsBits, + ChannelType, + ActionRowBuilder, + ButtonBuilder, + ButtonStyle, + MessageFlags +} from 'discord.js'; + +import { createEmbed, errorEmbed, successEmbed } from '../../utils/embeds.js'; import { getGuildConfig } from '../../services/guildConfig.js'; import { InteractionHelper } from '../../utils/interactionHelper.js'; import { logger } from '../../utils/logger.js'; @@ -13,324 +23,141 @@ export default { .setName("ticket") .setDescription("Manages the server's ticket system.") .setDefaultMemberPermissions(PermissionFlagsBits.ManageChannels) + .addSubcommand((subcommand) => subcommand .setName("setup") - .setDescription( - "Sets up the ticket creation panel in a specified channel.", - ) - .addChannelOption((option) => - option -.setName("panel_channel") - .setDescription( - "The channel where the ticket panel will be sent.", - ) + .setDescription("Sets up the ticket panel") + + .addChannelOption(option => + option.setName("panel_channel") + .setDescription("Channel for the panel") .addChannelTypes(ChannelType.GuildText) - .setRequired(true), + .setRequired(true) ) - .addStringOption((option) => - option - .setName("panel_message") - .setDescription( - "The main message/description for the ticket panel.", - ) - .setRequired(true), - ) - .addStringOption((option) => - option - .setName("button_label") - .setDescription( - "The label for the ticket creation button (default: Create Ticket)", - ) - .setRequired(false), + .addStringOption(option => + option.setName("panel_message") + .setDescription("Message for the panel") + .setRequired(true) ) - .addChannelOption((option) => - option - .setName("category") - .setDescription( - "The category where new tickets will be created (optional).", - ) - .addChannelTypes(ChannelType.GuildCategory) - .setRequired(false), + + .addStringOption(option => + option.setName("button_label") + .setDescription("Button label") + .setRequired(false) ) - .addChannelOption((option) => - option - .setName("closed_category") - .setDescription( - "The category where closed tickets will be moved (optional).", - ) + + .addChannelOption(option => + option.setName("category") + .setDescription("Ticket category") .addChannelTypes(ChannelType.GuildCategory) - .setRequired(false), + .setRequired(false) ) - .addRoleOption((option) => - option - .setName("staff_role") - .setDescription( - "The role that can access tickets (optional).", - ) - .setRequired(false), - ) - .addIntegerOption((option) => - option - .setName("max_tickets_per_user") - .setDescription("Maximum number of tickets a user can create (default: 3)") - .setMinValue(1) - .setMaxValue(10) - .setRequired(false), - ) - .addBooleanOption((option) => - option - .setName("dm_on_close") - .setDescription("Send DM to user when their ticket is closed (default: true)") - .setRequired(false), - ), ) + .addSubcommand((subcommand) => subcommand .setName("dashboard") - .setDescription("Open the interactive ticket system dashboard"), + .setDescription("Open dashboard") ), + category: "ticket", async execute(interaction, config, client) { try { - const deferred = await InteractionHelper.safeDefer(interaction, { flags: MessageFlags.Ephemeral }); - if (!deferred) { - return; - } + if (!deferred) return; - if ( - !interaction.member.permissions.has( - PermissionFlagsBits.ManageChannels, - ) - ) { - logger.warn('Ticket command permission denied', { - userId: interaction.user.id, - guildId: interaction.guildId, - commandName: 'ticket' - }); + if (!interaction.member.permissions.has(PermissionFlagsBits.ManageChannels)) { return await InteractionHelper.safeEditReply(interaction, { embeds: [ errorEmbed( "Permission Denied", - "You need the `Manage Channels` permission for this action.", - ), - ], + "You need Manage Channels permission." + ) + ] }); } const subcommand = interaction.options.getSubcommand(); - if (subcommand === "dashboard") { - return ticketConfig.execute(interaction, config, client); - } - - if (subcommand === "setup") { - const existingConfig = await getGuildConfig(client, interaction.guildId); - if (existingConfig?.ticketPanelChannelId) { - return await InteractionHelper.safeEditReply(interaction, { - embeds: [ - errorEmbed( - 'Ticket System Already Active', - `This server already has a ticket system set up (panel in <#${existingConfig.ticketPanelChannelId}>).\n\nOnly one ticket system is supported per server. Use \`/ticket dashboard\` to edit or update the existing setup, or select **Delete System** from the dashboard to remove it and start fresh.`, - ), - ], - }); + if (subcommand === "dashboard") { + return ticketConfig.execute(interaction, config, client); } - const panelChannel = - interaction.options.getChannel("panel_channel"); - const categoryChannel = interaction.options.getChannel("category"); - const closedCategoryChannel = interaction.options.getChannel("closed_category"); - const staffRole = interaction.options.getRole("staff_role"); -const panelMessage = interaction.options.getString("panel_message") || "Click the button below to create a support ticket."; - const buttonLabel = - interaction.options.getString("button_label") || -"Create Ticket"; - const maxTicketsPerUser = interaction.options.getInteger("max_tickets_per_user") || 3; -const dmOnClose = interaction.options.getBoolean("dm_on_close") !== false; + if (subcommand === "setup") { - const setupEmbed = createEmbed({ - title: "🎫 Support Tickets", -description: panelMessage, - color: getColor('info') - }); + const existingConfig = await getGuildConfig(client, interaction.guildId); - const ticketButton = new ActionRowBuilder().addComponents( - new ButtonBuilder() - .setCustomId("create_ticket") -.setLabel(buttonLabel) - .setStyle(ButtonStyle.Primary) - .setEmoji("📩"), - ); + if (existingConfig?.ticketPanelChannelId) { + return await InteractionHelper.safeEditReply(interaction, { + embeds: [ + errorEmbed( + "Already Setup", + `Panel already exists in <#${existingConfig.ticketPanelChannelId}>` + ) + ] + }); + } + + const panelChannel = interaction.options.getChannel("panel_channel"); + const categoryChannel = interaction.options.getChannel("category"); + + const panelMessage = interaction.options.getString("panel_message"); + const buttonLabel = interaction.options.getString("button_label") || "Create Ticket"; + + const embed = createEmbed({ + title: "🎫 Support Tickets", + description: panelMessage, + color: getColor('info') + }); + + const row = new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setCustomId("create_ticket") + .setLabel(buttonLabel) + .setStyle(ButtonStyle.Primary) + .setEmoji("📩") + ); - try { await panelChannel.send({ - embeds: [setupEmbed], - components: [ticketButton], + embeds: [embed], + components: [row] }); - if (client.db && interaction.guildId) { - const currentConfig = existingConfig; + if (client.db) { + const currentConfig = existingConfig || {}; + currentConfig.ticketCategoryId = categoryChannel ? categoryChannel.id : null; - currentConfig.ticketClosedCategoryId = closedCategoryChannel ? closedCategoryChannel.id : null; - currentConfig.ticketStaffRoleId = staffRole ? staffRole.id : null; currentConfig.ticketPanelChannelId = panelChannel.id; currentConfig.ticketPanelMessage = panelMessage; - currentConfig.ticketButtonLabel = buttonLabel; - currentConfig.maxTicketsPerUser = maxTicketsPerUser; - currentConfig.dmOnClose = dmOnClose; - const { getGuildConfigKey } = await import('../../utils/database.js'); - const configKey = getGuildConfigKey(interaction.guildId); - await client.db.set(configKey, currentConfig); - logger.info('Ticket configuration saved', { - guildId: interaction.guildId, - categoryId: categoryChannel?.id, - closedCategoryId: closedCategoryChannel?.id, - staffRoleId: staffRole?.id, - maxTickets: maxTicketsPerUser, - dmOnClose: dmOnClose - }); - } + const { getGuildConfigKey } = await import('../../utils/database.js'); + const key = getGuildConfigKey(interaction.guildId); - let successMessage = `The ticket creation panel has been sent to ${panelChannel}. `; - - if (categoryChannel) { - successMessage += `New tickets will be created in the **${categoryChannel.name}** category. `; - } else { - successMessage += 'New tickets will be created in a new "Tickets" category. '; - } - - if (closedCategoryChannel) { - successMessage += `Closed tickets will be moved to **${closedCategoryChannel.name}**. `; + await client.db.set(key, currentConfig); } - - if (staffRole) { - successMessage += `**${staffRole.name}** role will have access to tickets. `; - } - - successMessage += `\n\n**Max Tickets Per User:** ${maxTicketsPerUser}\n**DM on Close:** ${dmOnClose ? 'Enabled' : 'Disabled'}`; - await InteractionHelper.safeEditReply(interaction, { + return await InteractionHelper.safeEditReply(interaction, { embeds: [ successEmbed( - "Ticket Panel Set Up", - successMessage, - ), - ], - }); - - logger.info('Ticket panel setup completed', { - userId: interaction.user.id, - userTag: interaction.user.tag, - guildId: interaction.guildId, - panelChannelId: panelChannel.id, - categoryId: categoryChannel?.id, - closedCategoryId: closedCategoryChannel?.id, - staffRoleId: staffRole?.id, - maxTickets: maxTicketsPerUser, - dmOnClose: dmOnClose, - commandName: 'ticket_setup' - }); - - const logEmbed = createEmbed({ - title: "🔧 Ticket System Setup (Configuration Log)", - description: `The ticket panel was set up in ${panelChannel} by ${interaction.user}.`, - color: getColor('warning') - }) - .addFields( - { - name: "Panel Channel", - value: panelChannel.toString(), - inline: true, - }, - { - name: "Ticket Category", - value: categoryChannel - ? categoryChannel.toString() - : "None specified.", - inline: true, - }, - { - name: "Closed Category", - value: closedCategoryChannel - ? closedCategoryChannel.toString() - : "None specified.", - inline: true, - }, - { - name: "Staff Role", - value: staffRole - ? staffRole.toString() - : "None specified.", - inline: true, - }, - { - name: "Max Tickets Per User", - value: maxTicketsPerUser.toString(), - inline: true, - }, - { - name: "DM on Close", - value: dmOnClose ? 'Enabled' : 'Disabled', - inline: true, - }, - { - name: "Moderator", - value: `${interaction.user.tag} (${interaction.user.id})`, - inline: false, - }, - ); - - - } catch (error) { - logger.error('Ticket setup error', { - error: error.message, - stack: error.stack, - userId: interaction.user.id, - guildId: interaction.guildId, - commandName: 'ticket_setup' + "Setup Complete", + `Panel sent to ${panelChannel}` + ) + ] }); - if (interaction.deferred || interaction.replied) { - await InteractionHelper.safeEditReply(interaction, { - embeds: [ - errorEmbed( - "Setup Failed", - "Could not send the ticket panel or save configuration. Check the bot's permissions (especially the ability to send messages in the target channel) and database connection.", - ), - ], - }).catch(err => { - logger.error('Failed to send error reply', { - error: err.message, - guildId: interaction.guildId - }); - }); - } else { - await handleInteractionError(interaction, error, { - commandName: 'ticket_setup', - source: 'ticket_setup_command' - }); - } } - } + } catch (error) { - logger.error('Error executing ticket command', { + logger.error('Ticket command error', { error: error.message, - stack: error.stack, - userId: interaction.user.id, - guildId: interaction.guildId, - commandName: 'ticket' - }); - await handleInteractionError(interaction, error, { - commandName: 'ticket', - source: 'ticket_command_main' + stack: error.stack }); + + await handleInteractionError(interaction, error); } } }; - - +``` diff --git a/src/config/bot.js b/src/config/bot.js index 36e588cd4..f2ff63282 100644 --- a/src/config/bot.js +++ b/src/config/bot.js @@ -25,9 +25,9 @@ export const botConfig = { activities: [ { // Text users will see (example: "Playing /help | Titan Bot"). - name: "Made with ❤️", + name: "Officiële Pixel Lounge bot | /help | Moderatie, Tickets, Minigames en meer |", // Activity type number (0 = Playing). - type: 0, + type: 4, }, ], },