commandHandler.ts
1 import { Client, CommandInteraction, InteractionType, SlashCommandBuilder } from 'discord.js'; 2 import fs from 'fs'; 3 import path from 'path'; 4 import { getLang } from './db'; 5 import { log, __ } from './messages'; 6 7 export interface Command { 8 data: SlashCommandBuilder; 9 execute(interaction: CommandInteraction): Promise<void>; 10 } 11 12 const defaultOptions = { 13 commandsDir: './commands/', 14 commandFileExtension: ['.js', '.ts'] as string[] 15 }; 16 17 export default class CommandHandler { 18 private client: Client; 19 private options: typeof defaultOptions; 20 public commands: Map<Command['data']['name'], Command>; 21 22 constructor(client: Client, options = defaultOptions) { 23 this.client = client; 24 this.options = options; 25 26 this.commands = this.getCommandFiles( 27 this.options.commandsDir, 28 this.options.commandFileExtension 29 ); 30 31 client.on('interactionCreate', async interaction => { 32 if (interaction.type !== InteractionType.ApplicationCommand) return; 33 const command = this.commands.get(interaction.commandName); 34 if (!command) return; 35 try { 36 command.execute(interaction); 37 } catch (error) { 38 log.error(error, 'Error while executing command' + command.data.name); 39 await interaction.reply({ 40 content: __({ 41 phrase: 'There was an error while executing this command!', 42 locale: getLang(interaction) 43 }), 44 ephemeral: true 45 }); 46 } 47 }); 48 } 49 50 getCommandFiles(commandsDir: string, commandFileExtension: string | string[]) { 51 const commands = new Map(); 52 const commandFiles = fs.readdirSync(path.join(__dirname, commandsDir)).filter(file => { 53 for (const extension of commandFileExtension) { 54 if (file.endsWith(extension)) return true; 55 } 56 return false; 57 }); 58 for (const file of commandFiles) { 59 const command: Command = require(commandsDir + file).default as Command; 60 commands.set(command.data.name, command); 61 } 62 return commands as typeof this.commands; 63 } 64 }