/ src / modules / commandHandler.ts
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  }