diff --git a/commands/examples/login.example.js b/commands/examples/login.example.js new file mode 100644 index 0000000..cf37c63 --- /dev/null +++ b/commands/examples/login.example.js @@ -0,0 +1,36 @@ +import { + ActionRowBuilder, + ModalBuilder, + SlashCommandBuilder, + TextInputBuilder, + TextInputStyle +} from 'discord.js'; + +export const data = new SlashCommandBuilder() + .setName('login') + .setDescription('Opens a login pop-up.'); +export async function modalSubmit(interaction) { + await interaction.reply({ content: 'Successfully submitted Form!', ephemeral: true }); +} +export async function execute(interaction) { + const modal = new ModalBuilder().setCustomId('login-modal').setTitle('Login Form'); + + const user = new ActionRowBuilder().addComponents( + new TextInputBuilder() + .setCustomId('user') + .setLabel('Enter username:') + .setStyle(TextInputStyle.Short) + .setRequired(true) + ); + const password = new ActionRowBuilder().addComponents( + new TextInputBuilder() + .setCustomId('password') + .setLabel('Enter password:') + .setStyle(TextInputStyle.Short) + .setRequired(true) + ); + + modal.addComponents(user, password); + + await interaction.showModal(modal); +} diff --git a/commands/examples/ping.example.js b/commands/examples/ping.example.js new file mode 100644 index 0000000..42bb665 --- /dev/null +++ b/commands/examples/ping.example.js @@ -0,0 +1,6 @@ +import { SlashCommandBuilder } from 'discord.js'; + +export const data = new SlashCommandBuilder().setName('ping').setDescription('Replies with Pong!'); +export async function execute(interaction) { + await interaction.reply({ content: 'Pong!', ephemeral: true }); +} diff --git a/commands/examples/role.example.js b/commands/examples/role.example.js new file mode 100644 index 0000000..50cd61e --- /dev/null +++ b/commands/examples/role.example.js @@ -0,0 +1,42 @@ +import { + ActionRowBuilder, + ComponentType, + RoleSelectMenuBuilder, + SlashCommandBuilder +} from 'discord.js'; + +export const data = new SlashCommandBuilder() + .setName('role') + .setDMPermission(false) + .setDescription('Provides a role selector.'); +export async function execute(interaction) { + const roles = await interaction.guild.roles.fetch(); + const choices = roles.filter((r) => r.name.startsWith('test')).map((r) => r.id); + + const button = new RoleSelectMenuBuilder() + .setMinValues(1) + .setMaxValues(25) + .setCustomId('role') + .setDefaultRoles(choices) + .setPlaceholder('Select at least one role.'); + + const row = new ActionRowBuilder().addComponents(button); + + const response = await interaction.reply({ + components: [row], + ephemeral: true + }); + + const collector = response.createMessageComponentCollector({ + componentType: ComponentType.RoleSelect, + time: 120_000 + }); + + collector.on('collect', async (i) => { + const selection = roles + .filter((r) => i.values.includes(r.id)) + .map((r) => r.name) + .join(', '); + await i.reply({ content: `You have selected: "${selection}".`, ephemeral: true }); + }); +} 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 eb777a6..65b0944 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,5 @@ import { Client, Collection, GatewayIntentBits } from 'discord.js'; -import { readdir, stat } from 'fs/promises'; +import { getFiles, importAndCheck } from './shared.js'; import { Partials } from 'discord.js'; import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; @@ -7,9 +7,6 @@ import { config } from 'dotenv'; config(); -const required = ['data', 'execute']; -const optional = ['autocomplete', 'modalSubmit']; - const runClient = (commands, events) => { // Create a new client instance const client = new Client({ @@ -37,51 +34,16 @@ const runClient = (commands, events) => { const __dirname = dirname(fileURLToPath(import.meta.url)); const cmdPath = join(__dirname, 'commands'); const evtPath = join(__dirname, 'events'); -readdir(cmdPath) - .then(async (categories) => - // For each category directory - await Promise.all( - categories.map(async (category) => { - const catPath = join(cmdPath, category); - const content = await readdir(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) +getFiles(cmdPath) + // For each command file + .then(async (files) => + (await Promise.all(files.map(importAndCheck))) + .filter((module) => module !== 0) ).then(async (commands) => { - const content = await readdir(evtPath); - const files = content.filter((file) => file.endsWith('.js')); + 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/package-lock.json b/package-lock.json index 14d32f9..3b9f3b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,6 @@ "dependencies": { "discord.js": "^14.14.1", "dotenv": "^16.3.1", - "proxy-agent": "^6.3.1", "sequelize": "^6.35.2", "sqlite3": "^5.1.7" }, @@ -330,11 +329,6 @@ "node": ">= 6" } }, - "node_modules/@tootallnate/quickjs-emscripten": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" - }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -411,17 +405,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/agentkeepalive": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", @@ -512,17 +495,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -548,14 +520,6 @@ } ] }, - "node_modules/basic-ftp": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.3.tgz", - "integrity": "sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g==", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", @@ -743,14 +707,6 @@ "node": ">= 8" } }, - "node_modules/data-uri-to-buffer": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.1.tgz", - "integrity": "sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg==", - "engines": { - "node": ">= 14" - } - }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -795,19 +751,6 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "node_modules/degenerator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", - "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "dependencies": { - "ast-types": "^0.13.4", - "escodegen": "^2.1.0", - "esprima": "^4.0.1" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -929,26 +872,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, "node_modules/eslint": { "version": "8.56.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", @@ -1061,18 +984,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/esquery": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", @@ -1101,6 +1012,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "engines": { "node": ">=4.0" } @@ -1109,6 +1021,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -1205,19 +1118,6 @@ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, "node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", @@ -1254,20 +1154,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/get-uri": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.2.tgz", - "integrity": "sha512-5KLucCJobh8vBY1K07EFV4+cPZH3mrV9YeAruUseCQKHB58SGjjT2l9/eA9LD082IiuMjSlFJEcdJ27TXvbZNw==", - "dependencies": { - "basic-ftp": "^5.0.2", - "data-uri-to-buffer": "^6.0.0", - "debug": "^4.3.4", - "fs-extra": "^8.1.0" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", @@ -1323,7 +1209,8 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "optional": true }, "node_modules/graphemer": { "version": "1.4.0", @@ -1352,30 +1239,6 @@ "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "optional": true }, - "node_modules/http-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", - "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", - "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", @@ -1493,11 +1356,6 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, - "node_modules/ip": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", - "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==" - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1579,14 +1437,6 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -1640,14 +1490,6 @@ "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" }, - "node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "engines": { - "node": ">=12" - } - }, "node_modules/magic-bytes.js": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.7.0.tgz", @@ -1924,14 +1766,6 @@ "node": ">= 0.6" } }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/node-abi": { "version": "3.54.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.54.0.tgz", @@ -2075,37 +1909,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pac-proxy-agent": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", - "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", - "dependencies": { - "@tootallnate/quickjs-emscripten": "^0.23.0", - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "get-uri": "^6.0.1", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", - "pac-resolver": "^7.0.0", - "socks-proxy-agent": "^8.0.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-resolver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz", - "integrity": "sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==", - "dependencies": { - "degenerator": "^5.0.0", - "ip": "^1.1.8", - "netmask": "^2.0.2" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -2218,29 +2021,6 @@ "node": ">=10" } }, - "node_modules/proxy-agent": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", - "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.0.1", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -2584,6 +2364,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "optional": true, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -2593,6 +2374,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "optional": true, "dependencies": { "ip": "^2.0.0", "smart-buffer": "^4.2.0" @@ -2602,32 +2384,11 @@ "npm": ">= 3.0.0" } }, - "node_modules/socks-proxy-agent": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", - "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "socks": "^2.7.1" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/socks/node_modules/ip": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "optional": true, - "engines": { - "node": ">=0.10.0" - } + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "optional": true }, "node_modules/sqlite3": { "version": "5.1.7", @@ -2867,14 +2628,6 @@ "imurmurhash": "^0.1.4" } }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", diff --git a/package.json b/package.json index e7b8f61..6dad1df 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,6 @@ "dependencies": { "discord.js": "^14.14.1", "dotenv": "^16.3.1", - "proxy-agent": "^6.3.1", "sequelize": "^6.35.2", "sqlite3": "^5.1.7" }, diff --git a/shared.js b/shared.js index 9a8984d..3740d7d 100644 --- a/shared.js +++ b/shared.js @@ -58,3 +58,41 @@ export const addSelfRoles = async (interaction, msgID, role, emoji) => { }); } } +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; +};