143 lines
No EOL
4.1 KiB
TypeScript
143 lines
No EOL
4.1 KiB
TypeScript
import {
|
|
AnySelectMenuInteraction,
|
|
AutocompleteInteraction, ButtonInteraction,
|
|
ChatInputCommandInteraction,
|
|
inlineCode,
|
|
Interaction, InteractionReplyOptions,
|
|
MessageFlags, ModalSubmitInteraction,
|
|
} from "discord.js";
|
|
import Commands from "./Commands/Commands";
|
|
import {Logger} from "log4js";
|
|
import {UserError} from "./UserError";
|
|
import {Container} from "../Container/Container";
|
|
import {EventHandler} from "../Events/EventHandler";
|
|
import {ModalInteractionEvent} from "../Events/EventClasses/ModalInteractionEvent";
|
|
import {ComponentInteractionEvent} from "../Events/EventClasses/ComponentInteractionEvent";
|
|
import {log} from "node:util";
|
|
import {PermissionError} from "./PermissionError";
|
|
import {EmbedLibrary} from "./EmbedLibrary";
|
|
|
|
enum InteractionRoutingType {
|
|
Unrouted,
|
|
Command,
|
|
AutoComplete,
|
|
ModalSubmit,
|
|
ButtonSubmit,
|
|
MenuSubmit,
|
|
}
|
|
|
|
export class InteractionRouter {
|
|
constructor(
|
|
public readonly commands: Commands,
|
|
public readonly logger: Logger,
|
|
private readonly events: EventHandler
|
|
) {
|
|
}
|
|
|
|
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(<ChatInputCommandInteraction>interaction);
|
|
break;
|
|
case InteractionRoutingType.AutoComplete:
|
|
await this.handleAutocomplete(<AutocompleteInteraction>interaction)
|
|
break;
|
|
case InteractionRoutingType.ModalSubmit:
|
|
this.events.dispatch(new ModalInteractionEvent(<ModalSubmitInteraction>interaction));
|
|
break;
|
|
case InteractionRoutingType.ButtonSubmit:
|
|
case InteractionRoutingType.MenuSubmit:
|
|
this.events.dispatch(new ComponentInteractionEvent(<ButtonInteraction|AnySelectMenuInteraction>interaction))
|
|
}
|
|
}
|
|
|
|
private findInteractionType(interaction: Interaction): InteractionRoutingType {
|
|
if (interaction.isChatInputCommand()) {
|
|
return InteractionRoutingType.Command;
|
|
}
|
|
|
|
if (interaction.isAutocomplete()) {
|
|
return InteractionRoutingType.AutoComplete;
|
|
}
|
|
|
|
if (interaction.isModalSubmit()) {
|
|
return InteractionRoutingType.ModalSubmit;
|
|
}
|
|
|
|
if (interaction.isButton()) {
|
|
return InteractionRoutingType.ButtonSubmit;
|
|
}
|
|
if (interaction.isAnySelectMenu()) {
|
|
return InteractionRoutingType.MenuSubmit;
|
|
}
|
|
|
|
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) {
|
|
|
|
|
|
let logErrorMessage = true;
|
|
if ("shouldLog" in e) {
|
|
logErrorMessage = e.shouldLog;
|
|
}
|
|
|
|
if (logErrorMessage) {
|
|
this.logger.error(e)
|
|
}
|
|
|
|
const responseOptions: InteractionReplyOptions = {
|
|
embeds: [
|
|
EmbedLibrary.error(e)
|
|
],
|
|
flags: MessageFlags.Ephemeral
|
|
}
|
|
|
|
if (interaction.replied || interaction.deferred) {
|
|
await interaction.followUp(responseOptions);
|
|
} else {
|
|
await interaction.reply(responseOptions);
|
|
}
|
|
}
|
|
}
|
|
|
|
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>("logger").debug(`Found command ${interaction.commandName} for autocomplete: handling...`);
|
|
|
|
try {
|
|
await command.handleAutocomplete?.call(command, interaction);
|
|
} catch (e: unknown) {
|
|
Container.get<Logger>('logger').error(e);
|
|
}
|
|
|
|
}
|
|
} |