mirror of
				https://github.com/keanuplayz/TravBot-v3.git
				synced 2024-08-15 02:33:12 +00:00 
			
		
		
		
	Added example of temporary solution for slash commands
This commit is contained in:
		
							parent
							
								
									69a8452574
								
							
						
					
					
						commit
						533ce58647
					
				
					 10 changed files with 309 additions and 30 deletions
				
			
		|  | @ -5,6 +5,7 @@ | |||
| .husky/ | ||||
| Dockerfile | ||||
| LICENSE | ||||
| *.txt | ||||
| 
 | ||||
| # Specific to this repository | ||||
| dist/ | ||||
|  |  | |||
							
								
								
									
										65
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										65
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							|  | @ -10,9 +10,11 @@ | |||
|             "hasInstallScript": true, | ||||
|             "license": "MIT", | ||||
|             "dependencies": { | ||||
|                 "@discordjs/builders": "^0.8.2", | ||||
|                 "canvas": "^2.8.0", | ||||
|                 "chalk": "^4.1.2", | ||||
|                 "discord.js": "^13.3.0", | ||||
|                 "dotenv": "^10.0.0", | ||||
|                 "figlet": "^1.5.2", | ||||
|                 "glob": "^7.2.0", | ||||
|                 "inquirer": "^8.2.0", | ||||
|  | @ -653,13 +655,13 @@ | |||
|             "dev": true | ||||
|         }, | ||||
|         "node_modules/@discordjs/builders": { | ||||
|             "version": "0.8.1", | ||||
|             "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.8.1.tgz", | ||||
|             "integrity": "sha512-kYJMvZ/BjRD1/6G2t1pQop2yoJNUmYvvKeG4mOBUCHFmfb7WIeBFmN/eSiP3cVSfRx3lbNiyxkdd5JzhjQnGbg==", | ||||
|             "version": "0.8.2", | ||||
|             "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.8.2.tgz", | ||||
|             "integrity": "sha512-/YRd11SrcluqXkKppq/FAVzLIPRVlIVmc6X8ZklspzMIHDtJ+A4W37D43SHvLdH//+NnK+SHW/WeOF4Ts54PeQ==", | ||||
|             "dependencies": { | ||||
|                 "@sindresorhus/is": "^4.2.0", | ||||
|                 "discord-api-types": "^0.24.0", | ||||
|                 "ow": "^0.28.1", | ||||
|                 "ow": "^0.27.0", | ||||
|                 "ts-mixer": "^6.0.0", | ||||
|                 "tslib": "^2.3.1" | ||||
|             }, | ||||
|  | @ -2172,6 +2174,14 @@ | |||
|                 "url": "https://github.com/sponsors/sindresorhus" | ||||
|             } | ||||
|         }, | ||||
|         "node_modules/dotenv": { | ||||
|             "version": "10.0.0", | ||||
|             "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", | ||||
|             "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", | ||||
|             "engines": { | ||||
|                 "node": ">=10" | ||||
|             } | ||||
|         }, | ||||
|         "node_modules/duplexer": { | ||||
|             "version": "0.1.2", | ||||
|             "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", | ||||
|  | @ -4523,15 +4533,15 @@ | |||
|             } | ||||
|         }, | ||||
|         "node_modules/ow": { | ||||
|             "version": "0.28.1", | ||||
|             "resolved": "https://registry.npmjs.org/ow/-/ow-0.28.1.tgz", | ||||
|             "integrity": "sha512-1EZTywPZeUKac9gD7q8np3Aj+V54kvfIcjNEVNDSbG2Ys5xA5foW2HquvMMqgyWGLqIFMlc0Iq/HmyMHqN48sA==", | ||||
|             "version": "0.27.0", | ||||
|             "resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz", | ||||
|             "integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==", | ||||
|             "dependencies": { | ||||
|                 "@sindresorhus/is": "^4.2.0", | ||||
|                 "@sindresorhus/is": "^4.0.1", | ||||
|                 "callsites": "^3.1.0", | ||||
|                 "dot-prop": "^6.0.1", | ||||
|                 "lodash.isequal": "^4.5.0", | ||||
|                 "type-fest": "^2.3.4", | ||||
|                 "type-fest": "^1.2.1", | ||||
|                 "vali-date": "^1.0.0" | ||||
|             }, | ||||
|             "engines": { | ||||
|  | @ -4542,11 +4552,11 @@ | |||
|             } | ||||
|         }, | ||||
|         "node_modules/ow/node_modules/type-fest": { | ||||
|             "version": "2.5.2", | ||||
|             "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.5.2.tgz", | ||||
|             "integrity": "sha512-WMbytmAs5PUTqwGJRE+WoRrD2S0bYFtHX8k4Y/1l18CG5kqA3keJud9pPQ/r30FE9n8XRFCXF9BbccHIZzRYJw==", | ||||
|             "version": "1.4.0", | ||||
|             "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", | ||||
|             "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", | ||||
|             "engines": { | ||||
|                 "node": ">=12.20" | ||||
|                 "node": ">=10" | ||||
|             }, | ||||
|             "funding": { | ||||
|                 "url": "https://github.com/sponsors/sindresorhus" | ||||
|  | @ -6378,13 +6388,13 @@ | |||
|             "dev": true | ||||
|         }, | ||||
|         "@discordjs/builders": { | ||||
|             "version": "0.8.1", | ||||
|             "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.8.1.tgz", | ||||
|             "integrity": "sha512-kYJMvZ/BjRD1/6G2t1pQop2yoJNUmYvvKeG4mOBUCHFmfb7WIeBFmN/eSiP3cVSfRx3lbNiyxkdd5JzhjQnGbg==", | ||||
|             "version": "0.8.2", | ||||
|             "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.8.2.tgz", | ||||
|             "integrity": "sha512-/YRd11SrcluqXkKppq/FAVzLIPRVlIVmc6X8ZklspzMIHDtJ+A4W37D43SHvLdH//+NnK+SHW/WeOF4Ts54PeQ==", | ||||
|             "requires": { | ||||
|                 "@sindresorhus/is": "^4.2.0", | ||||
|                 "discord-api-types": "^0.24.0", | ||||
|                 "ow": "^0.28.1", | ||||
|                 "ow": "^0.27.0", | ||||
|                 "ts-mixer": "^6.0.0", | ||||
|                 "tslib": "^2.3.1" | ||||
|             } | ||||
|  | @ -7576,6 +7586,11 @@ | |||
|                 "is-obj": "^2.0.0" | ||||
|             } | ||||
|         }, | ||||
|         "dotenv": { | ||||
|             "version": "10.0.0", | ||||
|             "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", | ||||
|             "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" | ||||
|         }, | ||||
|         "duplexer": { | ||||
|             "version": "0.1.2", | ||||
|             "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", | ||||
|  | @ -9265,22 +9280,22 @@ | |||
|             "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" | ||||
|         }, | ||||
|         "ow": { | ||||
|             "version": "0.28.1", | ||||
|             "resolved": "https://registry.npmjs.org/ow/-/ow-0.28.1.tgz", | ||||
|             "integrity": "sha512-1EZTywPZeUKac9gD7q8np3Aj+V54kvfIcjNEVNDSbG2Ys5xA5foW2HquvMMqgyWGLqIFMlc0Iq/HmyMHqN48sA==", | ||||
|             "version": "0.27.0", | ||||
|             "resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz", | ||||
|             "integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==", | ||||
|             "requires": { | ||||
|                 "@sindresorhus/is": "^4.2.0", | ||||
|                 "@sindresorhus/is": "^4.0.1", | ||||
|                 "callsites": "^3.1.0", | ||||
|                 "dot-prop": "^6.0.1", | ||||
|                 "lodash.isequal": "^4.5.0", | ||||
|                 "type-fest": "^2.3.4", | ||||
|                 "type-fest": "^1.2.1", | ||||
|                 "vali-date": "^1.0.0" | ||||
|             }, | ||||
|             "dependencies": { | ||||
|                 "type-fest": { | ||||
|                     "version": "2.5.2", | ||||
|                     "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.5.2.tgz", | ||||
|                     "integrity": "sha512-WMbytmAs5PUTqwGJRE+WoRrD2S0bYFtHX8k4Y/1l18CG5kqA3keJud9pPQ/r30FE9n8XRFCXF9BbccHIZzRYJw==" | ||||
|                     "version": "1.4.0", | ||||
|                     "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", | ||||
|                     "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==" | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|  |  | |||
|  | @ -5,19 +5,21 @@ | |||
|     "main": "dist/index.js", | ||||
|     "scripts": { | ||||
|         "build": "rimraf dist && tsc --project tsconfig.prod.json && npm prune --production", | ||||
|         "start": "node .", | ||||
|         "start": "node -r dotenv/config .", | ||||
|         "once": "tsc && npm start", | ||||
|         "dev": "tsc-watch --onSuccess \"npm run dev-instance\"", | ||||
|         "dev-fast": "tsc-watch --onSuccess \"node . dev\"", | ||||
|         "dev-instance": "rimraf dist && tsc && node . dev", | ||||
|         "dev-fast": "tsc-watch --onSuccess \"node -r dotenv/config . dev\"", | ||||
|         "dev-instance": "rimraf dist && tsc && node -r dotenv/config . dev", | ||||
|         "test": "jest", | ||||
|         "format": "prettier --write **/*", | ||||
|         "postinstall": "husky install" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@discordjs/builders": "^0.8.2", | ||||
|         "canvas": "^2.8.0", | ||||
|         "chalk": "^4.1.2", | ||||
|         "discord.js": "^13.3.0", | ||||
|         "dotenv": "^10.0.0", | ||||
|         "figlet": "^1.5.2", | ||||
|         "glob": "^7.2.0", | ||||
|         "inquirer": "^8.2.0", | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ module.exports = { | |||
|     jsxSingleQuote: false, | ||||
|     trailingComma: "none", | ||||
|     bracketSpacing: false, | ||||
|     jsxBracketSameLine: false, | ||||
|     bracketSameLine: false, | ||||
|     arrowParens: "always", | ||||
|     endOfLine: "auto" // Apparently, the GitHub repository still uses CRLF. I don't know how to force it to use LF, and until someone figures that out, I'm changing this to auto because I don't want more than one line ending commit.
 | ||||
| }; | ||||
|  |  | |||
							
								
								
									
										91
									
								
								slash-cmd-brainstorming.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								slash-cmd-brainstorming.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,91 @@ | |||
| -= [Fun] =- | ||||
| /8ball <question: string> | ||||
| /cookie all | ||||
| /cookie (<@user>) | ||||
| /eco show (<@user>) | ||||
| /eco daily - "... Same as /eco get." | ||||
| /eco get - "... Same as /eco daily." | ||||
| /eco pay <@user> <amount: int> | ||||
| /eco guild | ||||
| /eco leaderboard - "... Same as /eco top." | ||||
| /eco top - "... Same as /eco leaderboard." | ||||
| /eco buy <item: string> | ||||
| /eco shop | ||||
| /eco monday | ||||
| /eco bet <@user> <amount: int> <duration: string> | ||||
| /eco award <@user> (<amount: int>) | ||||
| /eco post | ||||
| /eco delete --- "Operation successful. 5000 rows affected." | ||||
| /figlet <input: string> | ||||
| /insult | ||||
| /love | ||||
| /ok | ||||
| /owoify <input> | ||||
| /party | ||||
| /pat (<@user>) | ||||
| /poll <question: string> (<seconds: int>) | ||||
| /ravi (<index: int>) | ||||
| /thonk (<text: string>) | ||||
| /urban <word: string> | ||||
| /vaporwave <text: string> | ||||
| /weather <city: string> | ||||
| /whoami | ||||
| /whois <@user> | ||||
| 
 | ||||
| -= [System] =- ("/admin other ..." if needed) | ||||
| /admin prefix (<prefix: string>) | ||||
| /admin messageembeds <enabled: boolean> | ||||
| /admin welcome type <[none, text, graphical]: string> | ||||
| /admin welcome channel <#channel> | ||||
| /admin stream <#channel> | ||||
| /admin defaultname (<name: string>) | ||||
| /admin logs (<verbosity: string>) | ||||
| /admin status | ||||
| /admin clear <amount: int> | ||||
| /admin nickname <nickname: string> | ||||
| /admin guilds | ||||
| /admin activity <type: string> (<description: string>) | ||||
| /admin syslog | ||||
| /admin autoroles list | ||||
| /admin autoroles reset | ||||
| /admin autoroles add <@role> | ||||
| /admin autoroles remove <@role> | ||||
| /admin streamroles set <@role> <category: string> | ||||
| /admin streamroles remove <@role> | ||||
| /webhook register <url: string> | ||||
| /webhook delete <url: string> | ||||
| 
 | ||||
| -= [Utility] =- | ||||
| /calc <expression: string> | ||||
| /code | ||||
| /desc <name: string> | ||||
| /docs <query: string> | ||||
| /emote <emotes: string> | ||||
| /info | ||||
| /info avatar (<@user>) | ||||
| /info bot | ||||
| /info guild <name: string> | ||||
| /info guild <id: int> | ||||
| /info <@user> | ||||
| /invite (<flag: int>) | ||||
| /lsemotes <regex: string> (<isCaseSensitive: boolean>) | ||||
| /purge | ||||
| /react <emotes: string> (<target: string>) | ||||
| /say <message: string> | ||||
| /scanemotes (<forceReset: boolean>) | ||||
| /shorten <url: string> | ||||
| /stream description set (<description: string>) | ||||
| /stream description remove | ||||
| /stream thumbnail set (<link: string>) | ||||
| /stream thumbnail remove | ||||
| /stream category set (<category: string>) | ||||
| /stream category remove | ||||
| /time show (<@user>) | ||||
| /time setup | ||||
| /time delete | ||||
| /time utc | ||||
| /time daylight | ||||
| /todo show | ||||
| /todo add <note: string> | ||||
| /todo remove <note: string> | ||||
| /todo clear | ||||
							
								
								
									
										16
									
								
								src/commands/fun/whoami.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/commands/fun/whoami.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | |||
| import {SlashCommandBuilder} from "@discordjs/builders"; | ||||
| import {CommandInteraction} from "discord.js"; | ||||
| import {registry} from "./whois"; | ||||
| 
 | ||||
| export const header = new SlashCommandBuilder().setDescription("Tells you who you are"); | ||||
| 
 | ||||
| export function handler(interaction: CommandInteraction) { | ||||
|     const {user} = interaction; | ||||
|     const id = user.id; | ||||
| 
 | ||||
|     if (id in registry) { | ||||
|         interaction.reply({content: `${user} ${registry[id]}`, allowedMentions: {parse: []}}); | ||||
|     } else { | ||||
|         interaction.reply("You haven't been added to the registry yet!"); | ||||
|     } | ||||
| } | ||||
|  | @ -1,8 +1,10 @@ | |||
| import {User} from "discord.js"; | ||||
| import {Command, NamedCommand, getUserByNickname, RestCommand} from "onion-lasers"; | ||||
| import {SlashCommandBuilder} from "@discordjs/builders"; | ||||
| import {CommandInteraction} from "discord.js"; | ||||
| 
 | ||||
| // Quotes must be used here or the numbers will change
 | ||||
| const registry: {[id: string]: string} = { | ||||
| export const registry: {[id: string]: string} = { | ||||
|     "465662909645848577": "You're an idiot, that's what.", | ||||
|     "306499531665833984": | ||||
|         "Kuma, you eldritch fuck, I demand you to release me from this Discord bot and let me see my Chromebook!", | ||||
|  | @ -50,6 +52,24 @@ const registry: {[id: string]: string} = { | |||
|     "138840343855497216": "your face is a whois entry" | ||||
| }; | ||||
| 
 | ||||
| export const header = new SlashCommandBuilder() | ||||
|     .setDescription("Tells you who the specified user is") | ||||
|     .addUserOption((option) => | ||||
|         option.setName("target").setDescription("The person to inquire about").setRequired(true) | ||||
|     ); | ||||
| 
 | ||||
| export function handler(interaction: CommandInteraction) { | ||||
|     const {options} = interaction; | ||||
|     const user = options.getUser("target", true); | ||||
|     const id = user.id; | ||||
| 
 | ||||
|     if (id in registry) { | ||||
|         interaction.reply({content: `${user} ${registry[id]}`, allowedMentions: {parse: []}}); | ||||
|     } else { | ||||
|         interaction.reply({content: `${user} hasn't been added to the registry yet!`, allowedMentions: {parse: []}}); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export default new NamedCommand({ | ||||
|     description: "Tells you who you or the specified user is.", | ||||
|     aliases: ["whoami"], | ||||
|  |  | |||
|  | @ -14,6 +14,9 @@ export const client = new Client({ | |||
|         Intents.FLAGS.GUILD_MESSAGES, | ||||
|         Intents.FLAGS.GUILD_MESSAGE_REACTIONS, | ||||
|         Intents.FLAGS.DIRECT_MESSAGES | ||||
|     ], | ||||
|     partials: [ | ||||
|         "CHANNEL" // Needed so the bot can receive DM messages
 | ||||
|     ] | ||||
| }); | ||||
| 
 | ||||
|  | @ -76,6 +79,7 @@ launch(client, path.join(__dirname, "commands"), { | |||
| }); | ||||
| 
 | ||||
| // Initialize Modules //
 | ||||
| import "./modules/slashCommands"; | ||||
| import "./modules/ready"; | ||||
| import "./modules/presence"; | ||||
| // TODO: Reimplement entire music system, contact Sink
 | ||||
|  |  | |||
							
								
								
									
										54
									
								
								src/modules/slashCommands.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/modules/slashCommands.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,54 @@ | |||
| import {client} from "../index"; | ||||
| import {join} from "path"; | ||||
| import {loadCommands} from "../modules/slashCommandsLoader"; | ||||
| 
 | ||||
| loadCommands(join(__dirname, "..", "commands")).then((result) => { | ||||
|     const [headers, handlers] = result; | ||||
|     const useDevGuild = IS_DEV_MODE && !!process.env.DEV_GUILD; | ||||
| 
 | ||||
|     // Send slash command data to Discord
 | ||||
| 
 | ||||
|     client.on("ready", async () => { | ||||
|         try { | ||||
|             if (useDevGuild) { | ||||
|                 await client.guilds.cache | ||||
|                     .get(process.env.DEV_GUILD!)! | ||||
|                     .commands.set(headers.map((header) => header.toJSON())); | ||||
|             } else { | ||||
|                 await client.application!.commands.set(headers.map((header) => header.toJSON())); | ||||
|             } | ||||
| 
 | ||||
|             console.log( | ||||
|                 `Successfully loaded command definitions into Discord using ${ | ||||
|                     useDevGuild ? "development" : "production" | ||||
|                 } mode.` | ||||
|             ); | ||||
|         } catch (error) { | ||||
|             console.error(error); | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     // Listen for slash commands
 | ||||
| 
 | ||||
|     client.on("interactionCreate", async (interaction) => { | ||||
|         if (interaction.isCommand()) { | ||||
|             if (handlers.has(interaction.commandName)) { | ||||
|                 try { | ||||
|                     await handlers.get(interaction.commandName)!(interaction); | ||||
|                 } catch (error) { | ||||
|                     console.error(error); | ||||
|                 } | ||||
| 
 | ||||
|                 // Use these when implementing subcommands and subcommand groups
 | ||||
|                 // interaction.options.getSubcommandGroup(false); // string if exists, null if not
 | ||||
|                 // interaction.options.getSubcommand(false); // string if exists, null if not
 | ||||
|             } else { | ||||
|                 interaction.reply({ | ||||
|                     content: | ||||
|                         "**Error:** Invalid command name! This probably means that the command definitions forgot to be updated.", | ||||
|                     ephemeral: true | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										76
									
								
								src/modules/slashCommandsLoader.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/modules/slashCommandsLoader.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,76 @@ | |||
| import {Collection, CommandInteraction} from "discord.js"; | ||||
| import {SlashCommandBuilder} from "@discordjs/builders"; | ||||
| import glob from "glob"; | ||||
| import path from "path"; | ||||
| 
 | ||||
| export async function loadCommands( | ||||
|     commandsDir: string | ||||
| ): Promise< | ||||
|     [Collection<string, SlashCommandBuilder>, Collection<string, (interaction: CommandInteraction) => Promise<any>>] | ||||
| > { | ||||
|     // Add a trailing separator so that the reduced filename list will reliably cut off the starting part.
 | ||||
|     // "C:/some/path/to/commands" --> "C:/some/path/to/commands/" (and likewise for \)
 | ||||
|     commandsDir = path.normalize(commandsDir); | ||||
|     if (!commandsDir.endsWith(path.sep)) commandsDir += path.sep; | ||||
| 
 | ||||
|     const headers = new Collection<string, SlashCommandBuilder>(); | ||||
|     const handlers = new Collection<string, () => Promise<any>>(); | ||||
|     const files = await globP(path.join(commandsDir, "**", "*.js")); // This stage filters out source maps (.js.map).
 | ||||
|     // Because glob will use / regardless of platform, the following regex pattern can rely on / being the case.
 | ||||
|     const filesClean = files.map((filename) => filename.substring(commandsDir.length)); | ||||
|     // Extract the usable parts from commands directory if the path is 1 to 2 subdirectories (a or a/b, not a/b/c).
 | ||||
|     // No further checks will be made to exclude template command files or test command files, keeping it structure-agnostic.
 | ||||
|     const pattern = /^([^/]+(?:\/[^/]+)?)\.js$/; | ||||
| 
 | ||||
|     for (let i = 0; i < files.length; i++) { | ||||
|         const match = pattern.exec(filesClean[i]); | ||||
|         if (!match) continue; | ||||
|         const commandID = match[1]; // e.g. "utilities/info"
 | ||||
|         const slashIndex = commandID.indexOf("/"); | ||||
|         const isMiscCommand = slashIndex !== -1; | ||||
|         const commandName = isMiscCommand ? commandID.substring(slashIndex + 1) : commandID; // e.g. "info"
 | ||||
| 
 | ||||
|         // This try-catch block MUST be here or Node.js' dynamic require() will silently fail.
 | ||||
|         try { | ||||
|             // If the dynamic import works, it must be an object at the very least. Then, just test to see if it's a proper instance.
 | ||||
|             const {header, handler} = (await import(files[i])) as {header: unknown; handler: unknown}; | ||||
| 
 | ||||
|             if (header instanceof SlashCommandBuilder && handler instanceof Function) { | ||||
|                 if (headers.has(commandName) || handlers.has(commandName)) { | ||||
|                     console.warn( | ||||
|                         `Command "${commandID}" already exists! Make sure to make each command uniquely identifiable across categories!` | ||||
|                     ); | ||||
|                 } else { | ||||
|                     // Set the slash command name to the filename only if there isn't already a name set
 | ||||
|                     if (header.name === undefined) { | ||||
|                         header.setName(commandName); | ||||
|                     } | ||||
| 
 | ||||
|                     headers.set(header.name, header); | ||||
|                     handlers.set(header.name, handler as any); // Just got to hope that the user puts in good data
 | ||||
|                     console.log(`Loaded Command: "${commandID}" as "${header.name}"`); // Use header.name to show what the slash command name is (should be the same)
 | ||||
|                 } | ||||
|             } else { | ||||
|                 console.warn( | ||||
|                     `Command "${commandID}" doesn't export a "header" property (SlashCommandBuilder instance) or a "handler" property (function)!` | ||||
|                 ); | ||||
|             } | ||||
|         } catch (error) { | ||||
|             console.error(error); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return [headers, handlers]; | ||||
| } | ||||
| 
 | ||||
| function globP(path: string) { | ||||
|     return new Promise<string[]>((resolve, reject) => { | ||||
|         glob(path, (error, files) => { | ||||
|             if (error) { | ||||
|                 reject(error); | ||||
|             } else { | ||||
|                 resolve(files); | ||||
|             } | ||||
|         }); | ||||
|     }); | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue