pnp-scheduler/source/Discord/InteractionRouter.ts
2025-06-18 22:53:54 +02:00

109 lines
No EOL
3 KiB
TypeScript

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(<ChatInputCommandInteraction>interaction);
break;
case InteractionRoutingType.AutoComplete:
await this.handleAutocomplete(<AutocompleteInteraction>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>("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);
}
}
}