From f70912e4fd8c7ce745d217df752a4ba8faf5359a Mon Sep 17 00:00:00 2001 From: Baipyrus Date: Tue, 6 Feb 2024 15:25:58 +0100 Subject: [PATCH] read filesystem overhaul. sharing functions across files --- deploy.js | 52 +++++++--------------------------------- index.js | 72 +++++++++++++++---------------------------------------- shared.js | 38 +++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 96 deletions(-) create mode 100644 shared.js diff --git a/deploy.js b/deploy.js index d1bc276..9319cee 100644 --- a/deploy.js +++ b/deploy.js @@ -1,15 +1,10 @@ +import { getFiles, importAndCheck } from './shared.js'; import { REST, Routes } from 'discord.js'; import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; -import { promisify } from 'util'; import { config } from 'dotenv'; -import { readdir } from 'fs'; config(); -const readdirAsync = promisify(readdir); - -const required = ['data', 'execute']; -const optional = ['autocomplete', 'modalSubmit']; // Construct and prepare an instance of the REST module const rest = new REST().setToken(process.env.TOKEN); @@ -32,40 +27,11 @@ const putCommands = async (commands) => { // Register commands from sub-directories const __dirname = dirname(fileURLToPath(import.meta.url)); -const mainPath = join(__dirname, 'commands'); -readdirAsync(mainPath) - .then( - async (categories) => - // For each category directory - await Promise.all( - categories.map(async (category) => { - const catPath = join(mainPath, category); - const files = (await readdirAsync(catPath)).filter((file) => file.endsWith('.js') && !file.endsWith('.example.js')); - // For each command file - return await Promise.all( - files.map(async (current) => { - const filePath = join(catPath, current); - const command = await import(filePath); - // Warn incomplete commands - if (!required.every((name) => name in command)) { - console.error( - `[ERROR] The command at ${filePath} is missing a required "data" or "execute" property.` - ); - return 0; - } - const properties = optional.filter((name) => !(name in command)); - if (properties.length > 0) - properties.forEach((name) => - console.warn( - `[WARNING] The command at ${filePath} is missing a optional "${name}" property.` - ) - ); - // Add command to collection - return command.data.toJSON(); - }) - ); - }) - ) - ) - .then((commands) => commands.reduce((a, i) => a.concat(i), []).filter((e) => e !== 0)) - .then(putCommands); +const cmdPath = join(__dirname, 'commands'); +getFiles(cmdPath) + // For each command file + .then(async (files) => + (await Promise.all(files.map(importAndCheck))) + .filter((module) => module !== 0) + .map((module) => module.data.toJSON()) + ).then(putCommands); diff --git a/index.js b/index.js index 7112316..c5cf1ae 100644 --- a/index.js +++ b/index.js @@ -1,19 +1,21 @@ import { Client, Collection, GatewayIntentBits } from 'discord.js'; +import { getFiles, importAndCheck } from './shared.js'; +import { Partials } from 'discord.js'; import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; -import { promisify } from 'util'; import { config } from 'dotenv'; -import { readdir } from 'fs'; config(); -const readdirAsync = promisify(readdir); - -const required = ['data', 'execute']; -const optional = ['autocomplete', 'modalSubmit']; const runClient = (commands, events) => { // Create a new client instance - const client = new Client({ intents: [GatewayIntentBits.Guilds] }); + const client = new Client({ + intents: [ + GatewayIntentBits.Guilds, + GatewayIntentBits.GuildMessages, + ], + partials: [Partials.Message, Partials.Reaction] + }); client.commands = new Collection(); commands.forEach((c) => client.commands.set(c.data.name, c)); events.forEach((e) => @@ -30,52 +32,16 @@ const runClient = (commands, events) => { const __dirname = dirname(fileURLToPath(import.meta.url)); const cmdPath = join(__dirname, 'commands'); const evtPath = join(__dirname, 'events'); -readdirAsync(cmdPath) - .then( - async (categories) => - // For each category directory - await Promise.all( - categories.map(async (category) => { - const catPath = join(cmdPath, category); - const content = await readdirAsync(catPath); - const files = content.filter((file) => file.endsWith('.js') && !file.endsWith('.example.js')); - // For each command file - return await Promise.all( - files.map(async (current) => { - const filePath = join(catPath, current); - const command = await import(filePath); - // Warn incomplete commands - if (!required.every((name) => name in command)) { - console.error( - `[ERROR] The command at ${filePath} is missing a required "data" or "execute" property.` - ); - return 0; - } - const properties = optional.filter((name) => !(name in command)); - if (properties.length > 0) - properties.forEach((name) => - console.warn( - `[WARNING] The command at ${filePath} is missing a optional "${name}" property.` - ) - ); - // Add command to collection - return command; - }) - ); - }) - ) - ) - .then((commands) => commands.reduce((a, i) => a.concat(i), []).filter((e) => e !== 0)) - .then(async (commands) => { - const content = await readdirAsync(evtPath); - const files = content.filter((file) => file.endsWith('.js')); +getFiles(cmdPath) + // For each command file + .then(async (files) => + (await Promise.all(files.map(importAndCheck))) + .filter((module) => module !== 0) + ).then(async (commands) => { + const files = await getFiles(evtPath); const events = await Promise.all( - files.map(async (current) => { - const filePath = join(evtPath, current); - const command = await import(filePath); - // Add event to collection - return command; - }) - ); + files.map(async (filePath) => + await import(filePath) + )); runClient(commands, events); }); diff --git a/shared.js b/shared.js new file mode 100644 index 0000000..8147564 --- /dev/null +++ b/shared.js @@ -0,0 +1,38 @@ +import { join } from 'path'; +import { readdir } from 'fs/promises'; + +const required = ['data', 'execute']; +const optional = ['autocomplete', 'modalSubmit']; + +export const getFiles = async (dir) => { + const dirents = await readdir(dir, { withFileTypes: true }); + const files = await Promise.all(dirents.map((dirent) => { + const res = join(dir, dirent.name); + return dirent.isDirectory() ? getFiles(res) : res; + })); + return Array.prototype.concat(...files); +}; + +export const importAndCheck = async (filePath) => { + if (!filePath.endsWith('.js') || filePath.endsWith('.example.js')) { + // Skip this file + return 0; + } + const command = await import(filePath); + // Warn incomplete commands + if (!required.every((name) => name in command)) { + console.error( + `[ERROR] The command at ${filePath} is missing a required "data" or "execute" property.` + ); + return 0; + } + const properties = optional.filter((name) => !(name in command)); + if (properties.length > 0) + properties.forEach((name) => + console.warn( + `[WARNING] The command at ${filePath} is missing an optional "${name}" property.` + ) + ); + // Add command to collection + return command; +};