From 8483c490cb69e9f82780d8e2fd069d3c3bf9e178 Mon Sep 17 00:00:00 2001 From: Fretux Date: Mon, 26 Jan 2026 11:34:48 +0100 Subject: [PATCH] Refactor command and event loading --- deploy-commands.js | 53 +++++++++++++++++---------------------------- index.js | 39 ++++++++++++++------------------- loaders/commands.js | 41 +++++++++++++++++++++++++++++++++++ loaders/events.js | 23 ++++++++++++++++++++ 4 files changed, 100 insertions(+), 56 deletions(-) create mode 100644 loaders/commands.js create mode 100644 loaders/events.js diff --git a/deploy-commands.js b/deploy-commands.js index fd3b346..de5dd15 100644 --- a/deploy-commands.js +++ b/deploy-commands.js @@ -1,27 +1,14 @@ -const { REST, Routes } = require('discord.js'); -const { clientId, guildId, token } = require('./config.json'); -const fs = require('node:fs'); const path = require('node:path'); +const { REST, Routes } = require('discord.js'); +const { clientId, token } = require('./config.json'); +const { loadCommandModules } = require('./loaders/commands'); -const commands = []; -// Grab all the command folders from the commands directory you created earlier -const foldersPath = path.join(__dirname, 'commands'); -const commandFolders = fs.readdirSync(foldersPath); +const commandsPath = path.join(__dirname, 'commands'); +const { commands, invalidCommands } = loadCommandModules(commandsPath); +const commandsData = commands.map((command) => command.data.toJSON()); -for (const folder of commandFolders) { - // Grab all the command files from the commands directory you created earlier - const commandsPath = path.join(foldersPath, folder); - const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); - // Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment - for (const file of commandFiles) { - const filePath = path.join(commandsPath, file); - const command = require(filePath); - if ('data' in command && 'execute' in command) { - commands.push(command.data.toJSON()); - } else { - console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`); - } - } +for (const filePath of invalidCommands) { + console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`); } // Construct and prepare an instance of the REST module @@ -29,18 +16,18 @@ const rest = new REST().setToken(token); // and deploy your commands! (async () => { - try { - console.log(`Started refreshing ${commands.length} application (/) commands.`); + try { + console.log(`Started refreshing ${commandsData.length} application (/) commands.`); - // The put method is used to fully refresh all commands in the guild with the current set - const data = await rest.put( - Routes.applicationCommands(clientId), - { body: commands }, - ); + // The put method is used to fully refresh all commands in the guild with the current set + const data = await rest.put( + Routes.applicationCommands(clientId), + { body: commandsData }, + ); - console.log(`Successfully reloaded ${data.length} application (/) commands.`); - } catch (error) { - // And of course, make sure you catch and log any errors! - console.error(error); - } + console.log(`Successfully reloaded ${data.length} application (/) commands.`); + } catch (error) { + // And of course, make sure you catch and log any errors! + console.error(error); + } })(); diff --git a/index.js b/index.js index 4552850..87f3086 100644 --- a/index.js +++ b/index.js @@ -1,36 +1,29 @@ -const fs = require('node:fs'); const path = require('node:path'); const { Client, Collection, GatewayIntentBits } = require('discord.js'); const { token } = require('./config.json'); +const { loadCommandModules } = require('./loaders/commands'); +const { loadEventModules } = require('./loaders/events'); const client = new Client({ intents: [GatewayIntentBits.Guilds] }); -// Retreaves commands from the command folder +// Retrieves commands from the command folder client.commands = new Collection(); -const foldersPath = path.join(__dirname, 'commands'); -const commandFolders = fs.readdirSync(foldersPath); +const commandsPath = path.join(__dirname, 'commands'); +const { commands, invalidCommands } = loadCommandModules(commandsPath); -for (const folder of commandFolders) { - const commandsPath = path.join(foldersPath, folder); - const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); - for (const file of commandFiles) { - const filePath = path.join(commandsPath, file); - const command = require(filePath); - if ('data' in command && 'execute' in command) { - client.commands.set(command.data.name, command); - } else { - console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`); - } - } +for (const command of commands) { + client.commands.set(command.data.name, command); } -// Retreaves Events from the events folder -const eventsPath = path.join(__dirname, 'events'); -const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js')); +for (const filePath of invalidCommands) { + console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`); +} -for (const file of eventFiles) { - const filePath = path.join(eventsPath, file); - const event = require(filePath); +// Retrieves events from the events folder +const eventsPath = path.join(__dirname, 'events'); +const eventModules = loadEventModules(eventsPath); + +for (const { event } of eventModules) { if (event.once) { client.once(event.name, (...args) => event.execute(...args)); } else { @@ -38,4 +31,4 @@ for (const file of eventFiles) { } } -client.login(token); \ No newline at end of file +client.login(token); diff --git a/loaders/commands.js b/loaders/commands.js new file mode 100644 index 0000000..94f0d35 --- /dev/null +++ b/loaders/commands.js @@ -0,0 +1,41 @@ +const fs = require('node:fs'); +const path = require('node:path'); + +const isJavaScriptFile = (file) => file.endsWith('.js'); + +const getCommandFilePaths = (commandsPath) => { + const commandFolders = fs + .readdirSync(commandsPath, { withFileTypes: true }) + .filter((entry) => entry.isDirectory()) + .map((entry) => entry.name); + + return commandFolders.flatMap((folder) => { + const folderPath = path.join(commandsPath, folder); + return fs + .readdirSync(folderPath) + .filter(isJavaScriptFile) + .map((file) => path.join(folderPath, file)); + }); +}; + +const loadCommandModules = (commandsPath) => { + const commandFiles = getCommandFilePaths(commandsPath); + const commands = []; + const invalidCommands = []; + + for (const filePath of commandFiles) { + const command = require(filePath); + + if ('data' in command && 'execute' in command) { + commands.push(command); + } else { + invalidCommands.push(filePath); + } + } + + return { commands, invalidCommands }; +}; + +module.exports = { + loadCommandModules, +}; diff --git a/loaders/events.js b/loaders/events.js new file mode 100644 index 0000000..e1668fc --- /dev/null +++ b/loaders/events.js @@ -0,0 +1,23 @@ +const fs = require('node:fs'); +const path = require('node:path'); + +const isJavaScriptFile = (file) => file.endsWith('.js'); + +const getEventFilePaths = (eventsPath) => + fs + .readdirSync(eventsPath) + .filter(isJavaScriptFile) + .map((file) => path.join(eventsPath, file)); + +const loadEventModules = (eventsPath) => { + const eventFiles = getEventFilePaths(eventsPath); + + return eventFiles.map((filePath) => ({ + filePath, + event: require(filePath), + })); +}; + +module.exports = { + loadEventModules, +};