UNPKG

simplify-cord

Version:

SimplifyCord is an unofficial extension of the 'discord.js' library. Our extension aims to simplify the development of Discord bots, promoting cleaner code and easier maintenance.

317 lines (316 loc) 14.7 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.bootstrapApp = void 0; const discord_js_1 = require("discord.js"); const index_1 = __importStar(require("../handlers/commands/index")); const index_2 = require("../handlers/interactions/index"); const Event_1 = require("./Event"); const url_1 = require("url"); const index_3 = require("../functions/index"); const zod_1 = require("zod"); const path = __importStar(require("path")); const logger_1 = require("../functions/logger"); const discord_js_2 = require("discord.js"); const chalk_1 = __importDefault(require("chalk")); const intents_1 = require("../lib/constants/intents"); class bootstrapApp extends discord_js_1.Client { customOptions; slashCommands = new discord_js_1.Collection(); slashArray = []; commands; constructor(options) { const intentsValidation = zod_1.z.array(zod_1.z.nativeEnum(discord_js_1.GatewayIntentBits), { invalid_type_error: "Intents list must be a GatewayIntentBits object from discord" }); intentsValidation.parse(options.intents || intents_1.DEFAULT_INTENTS); const tokenValidation = zod_1.z.string({ required_error: "Token is required", invalid_type_error: "Token must be a string" }); tokenValidation.parse(options.token); const clientOptions = { intents: options.intents || intents_1.DEFAULT_INTENTS }; super(clientOptions); this.customOptions = options; this.commands = options.commands; this.slashCommands = new discord_js_1.Collection(); this.slashArray = []; this.startListening(); this.loadAutoImportPaths().then(() => { Event_1.Event.register(this); this.login(options.token); }); } async invokeInteraction(interactionName, interaction, params = {}) { try { const handler = index_2.interactionHandlers.get(interactionName); if (!handler) { logger_1.Logger.error(`No handler found for interaction: ${interactionName}`); if (!interaction.replied && !interaction.deferred) { await interaction.reply({ content: 'Interaction handler not found.', ephemeral: true }); } return; } return await handler.run(this, interaction, params); } catch (error) { logger_1.Logger.error(`Error invoking interaction "${interactionName}"`, error); if (!interaction.replied && !interaction.deferred) { await interaction.reply({ content: 'An error occurred while processing this interaction.', ephemeral: true }); } } } async invokeCommand(commandName, interaction) { const command = this.slashCommands.get(commandName); if (!command) { logger_1.Logger.error(`Command "${commandName}" not found!`); return; } try { await command.run(this, interaction); } catch (error) { logger_1.Logger.error(`Error in command "${commandName}"`, error); } } async reloadCommands() { try { this.slashCommands = new discord_js_1.Collection(); this.slashArray = []; for (const [name, command] of index_1.slashCommandHandlers) { if (this.slashCommands.has(name)) { continue; } this.slashCommands.set(name, command); const commandData = { name: command.name, description: command.description, type: command.type, options: (command.options || []).map(option => ({ ...option, autocomplete: option.autocomplete ?? false })) }; this.slashArray.push(commandData); } if (this.slashArray.length === 0) { logger_1.Logger.warn("Warning: No commands to register."); return; } if (this.guilds.cache.size === 0) { logger_1.Logger.warn("Warning: No guilds found. Commands will be registered when joining a guild."); return; } if (this.commands?.guilds && this.commands.guilds.length > 0) { for (const guildId of this.commands.guilds) { const guild = this.guilds.cache.get(guildId); if (!guild) { logger_1.Logger.warn(`Guild with ID ${guildId} not found. Make sure the bot is in the guild.`); continue; } try { await guild.commands.set(this.slashArray); logger_1.Logger.success(`Commands registered in guild: ${guild.name} (${this.slashArray.length} commands)`); } catch (error) { logger_1.Logger.error(`Failed to register commands in guild ${guild.name}`, error); } } } else { try { await this.application?.commands.set(this.slashArray); logger_1.Logger.success(`Commands registered globally (${this.slashArray.length} commands)`); } catch (error) { logger_1.Logger.error("Failed to register commands globally", error); } } } catch (error) { logger_1.Logger.error("Error reloading commands", error); } } async loadAutoImportPaths() { const root_path = path.resolve(); const autoImportPath = this.customOptions?.autoImport; if (autoImportPath) { for (const importPath of autoImportPath) { const files = index_3.utils.getRecursiveFiles(`${root_path}/${importPath}`); if (!files) { logger_1.Logger.warn(`Auto Import path not found: '${importPath}'`); logger_1.Logger.info("Make sure to provide a valid path to the components folder"); continue; } for (const file of files) { const isValidFile = file.endsWith('.mjs') || file.endsWith('.js') || file.endsWith(".ts"); if (!isValidFile) continue; try { const componentPath = (0, url_1.pathToFileURL)(file).href; await import(componentPath); } catch (error) { logger_1.Logger.error(`Failed to import component: ${file}`, error); } } } } this.slashCommands = new discord_js_1.Collection(); this.slashArray = []; for (const [name, command] of index_1.slashCommandHandlers) { this.slashCommands.set(name, command); const commandData = { name: command.name, description: command.description, type: command.type, options: (command.options || []).map(option => ({ ...option, autocomplete: option.autocomplete ?? false })) }; this.slashArray.push(commandData); } } startListening() { this.once(discord_js_1.Events.ClientReady, async (client) => { console.log(); await this.loadAutoImportPaths(); if (this.customOptions?.loadLogs !== false) { index_1.default.loadLogs(); Event_1.Event.loadLogs(); logger_1.Logger.separator(); } logger_1.Logger.info(`${chalk_1.default.green.bold(`discord.js`)} @${chalk_1.default.white.bold(discord_js_2.version)} / ${chalk_1.default.green.bold(`NodeJs`)} @${chalk_1.default.white.bold(process.versions.node)}`); logger_1.Logger.separator(); logger_1.Logger.ready(`Online as ${logger_1.Logger.highlight(client.user.username)}`); await this.reloadCommands(); }); this.on(discord_js_1.Events.InteractionCreate, async (interaction) => { if (interaction.isCommand()) { const command = this.slashCommands.get(interaction.commandName); if (!command) { logger_1.Logger.error(`Command "${interaction.commandName}" not found!`); logger_1.Logger.info(`Available commands: ${Array.from(this.slashCommands.keys()).join(", ")}`); if (!interaction.replied && !interaction.deferred) { await interaction.reply({ content: 'Command not found. Please try again later.', ephemeral: true }); } return; } try { await command.run(this, interaction); } catch (error) { logger_1.Logger.error(`Error in command "${interaction.commandName}"`, error); if (!interaction.replied && !interaction.deferred) { await interaction.reply({ content: 'An error occurred while executing this command.', ephemeral: true }); } } } if (interaction.isButton() || interaction.isAnySelectMenu() || interaction.isModalSubmit()) { try { const runInteractionHandler = this.getInteractionCallback(interaction.customId, interaction); if (!runInteractionHandler) { logger_1.Logger.error(`No handler found for interaction: ${interaction.customId}`); if (!interaction.replied && !interaction.deferred) { await interaction.reply({ content: 'Interaction handler not found.', ephemeral: true }); } return; } await runInteractionHandler(); } catch (error) { logger_1.Logger.error(`Error in interaction "${interaction.customId}"`, error); if (!interaction.replied && !interaction.deferred) { await interaction.reply({ content: 'An error occurred while processing this interaction.', ephemeral: true }); } } } if (interaction.isAutocomplete()) { const command = this.slashCommands.get(interaction.commandName); if (!command) { return logger_1.Logger.error('Error on interaction autocomplete! Command not found.'); } if (command.autocomplete) { try { await command.autocomplete(interaction); } catch (error) { logger_1.Logger.error('Error in autocomplete interaction', error); } } } }); this.on(discord_js_1.Events.GuildCreate, async () => { await this.reloadCommands(); }); } parsePattern(pattern, customId) { const patternParts = pattern.split('/'); const customIdParts = customId.split('/'); if (patternParts.length !== customIdParts.length) { return null; } const params = {}; for (let i = 0; i < patternParts.length; i++) { if (patternParts[i].startsWith(':')) { const paramName = patternParts[i].slice(1); params[paramName] = customIdParts[i]; } else if (patternParts[i] !== customIdParts[i]) { return null; } } return params; } getInteractionCallback(customId, interaction) { if (interaction.isButton() || interaction.isAnySelectMenu() || interaction.isCommand() || interaction.isModalSubmit()) { try { const useOptionInLastParam = customId.includes("(OILP)"); const cleanCustomId = customId.replace("(OILP)", ""); for (const [pattern, handler] of index_2.interactionHandlers.entries()) { const params = this.parsePattern(pattern, cleanCustomId); if (params) { if (interaction.isAnySelectMenu() && useOptionInLastParam && interaction.values.length > 0) { params.value = interaction.values[0]; } const callback = handler.run; if (!callback) { logger_1.Logger.error(`Callback not found for pattern: ${pattern}`); return; } return callback.bind(null, this, interaction, params); } } logger_1.Logger.warn(`No matching handler found for customId: ${customId}`); } catch (error) { logger_1.Logger.error(`Error processing interaction for customId ${customId}`, error); } } } } exports.default = bootstrapApp; exports.bootstrapApp = bootstrapApp;