import { AutocompleteInteraction, ChatInputCommandInteraction, inlineCode, Interaction, MessageFlags, } from "discord.js"; import Commands from "./Commands/Commands"; import {Logger} from "log4js"; import {UserError} from "./UserError"; import {Container} from "../Container/Container"; enum InteractionRoutingType { Unrouted, Command, AutoComplete, } export class InteractionRouter { constructor( public readonly commands: Commands, public readonly logger: Logger ) { } async route(interaction: Interaction) { const interactionType = this.findInteractionType(interaction); switch (interactionType) { case InteractionRoutingType.Unrouted: this.logger.debug("Unroutable interaction found...") break; case InteractionRoutingType.Command: await this.handleCommand(interaction); break; case InteractionRoutingType.AutoComplete: await this.handleAutocomplete(interaction) break; } } private findInteractionType(interaction: Interaction): InteractionRoutingType { if (interaction.isChatInputCommand()) { return InteractionRoutingType.Command; } if (interaction.isAutocomplete()) { return InteractionRoutingType.AutoComplete; } return InteractionRoutingType.Unrouted; } private async handleCommand(interaction: ChatInputCommandInteraction) { try { const command = this.commands.getCommand(interaction.commandName); if (!command) { throw new UserError(`Requested command not found.`); } if (!('execute' in command)) { throw new UserError(`Requested command is not setup for a chat command.`); } this.logger.debug(`Found chat command ${interaction.commandName}: running...`); await command.execute?.call(command, interaction); } catch (e: any) { this.logger.error(e) let userMessage = ":x: There was an error while executing this command!"; if (e.constructor.name === UserError.name) { userMessage = `:x: \`${e.message}\` - Please validate your request!` if (e.tryInstead) { userMessage += ` You can try the following: ${inlineCode(e.tryInstead)}` } } if (interaction.replied || interaction.deferred) { await interaction.followUp({ content: userMessage, flags: MessageFlags.Ephemeral }); } else { await interaction.reply({ content: userMessage, flags: MessageFlags.Ephemeral }); } } } private async handleAutocomplete(interaction: AutocompleteInteraction) { const command = this.commands.getCommand(interaction.commandName); if (!command) { return null; } if (!('handleAutocomplete' in command)) { return null; } Container.get("logger").debug(`Found command ${interaction.commandName} for autocomplete: handling...`); try { await command.handleAutocomplete?.call(command, interaction); } catch (e: unknown) { Container.get('logger').error(e); } } }