From c1670b8abdbb238554bb161381f9a12fc9c0d464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linnea=20Gr=C3=A4f?= Date: Wed, 9 Apr 2025 18:55:03 +0200 Subject: [PATCH] feat: Thoroughly type ContextCommand --- src/command.ts | 10 +++++++--- src/commands/botsex.ts | 9 +++++---- src/index.ts | 9 ++++++++- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/command.ts b/src/command.ts index 91560cf..dae6617 100644 --- a/src/command.ts +++ b/src/command.ts @@ -1,11 +1,15 @@ -import { AutocompleteFocusedOption, AutocompleteInteraction, ChatInputCommandInteraction, ContextMenuCommandBuilder, ContextMenuCommandInteraction, SharedSlashCommand, Snowflake, User } from "discord.js"; +import { ApplicationCommandType, AutocompleteFocusedOption, AutocompleteInteraction, ChatInputCommandInteraction, ContextMenuCommandBuilder, ContextMenuCommandInteraction, Message, SharedSlashCommand, Snowflake, User } from "discord.js"; import { Config } from "./config"; export abstract class ICommand { } -export abstract class ContextCommand extends ICommand { +export abstract class ContextCommand extends ICommand { + abstract targetType: + T extends User ? ApplicationCommandType.User : + T extends Message ? ApplicationCommandType.Message : + never; abstract contextDefinition: ContextMenuCommandBuilder - abstract run(interaction: ContextMenuCommandInteraction, target: Snowflake): Promise + abstract run(interaction: ContextMenuCommandInteraction, target: T extends User ? User : T extends Message ? Message : never): Promise } export abstract class Command extends ICommand { diff --git a/src/commands/botsex.ts b/src/commands/botsex.ts index f04fcd3..93d63cc 100644 --- a/src/commands/botsex.ts +++ b/src/commands/botsex.ts @@ -1,13 +1,14 @@ -import { ApplicationCommandType, ContextMenuCommandBuilder, ContextMenuCommandInteraction, InteractionContextType, Snowflake } from "discord.js"; +import { ApplicationCommandType, ContextMenuCommandBuilder, ContextMenuCommandInteraction, InteractionContextType, Snowflake, User } from "discord.js"; import { ContextCommand } from "../command.ts"; -export default class RailUser extends ContextCommand { +export default class RailUser extends ContextCommand { + targetType: ApplicationCommandType.User = ApplicationCommandType.User; contextDefinition: ContextMenuCommandBuilder = new ContextMenuCommandBuilder() .setName('rail') .setType(ApplicationCommandType.User) - async run(interaction: ContextMenuCommandInteraction, target: Snowflake): Promise { - await interaction.reply(`Raililng <@${target}>.`) + async run(interaction: ContextMenuCommandInteraction, target: User): Promise { + await interaction.reply(`Raililng <@${target.id}>.`) await new Promise(resolve => setTimeout(resolve, 1000)) await interaction.editReply(`UHGhghgghghgh. Railing successfull.`) } diff --git a/src/index.ts b/src/index.ts index 24591ce..255f8b8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,6 @@ import { + ApplicationCommand, + ApplicationCommandType, Client, Events, GatewayIntentBits, @@ -43,6 +45,8 @@ const contextCommands = allCommands.filter(it => it instanceof ContextCommand); const contextCommandLUT = Object.fromEntries(contextCommands.map(it => [it.contextDefinition.name, it])) const commandLookup = Object.fromEntries(commands.map(it => [it.slashCommand.name, it])) +contextCommands.forEach(it => it.contextDefinition.type === it.targetType) + function makeDefaultAvailableEverywhere): any, readonly contexts?: InteractionContextType[] }>(t: T): T { if (!t.contexts) t.setContexts(InteractionContextType.BotDM, InteractionContextType.Guild, InteractionContextType.PrivateChannel) @@ -69,8 +73,11 @@ client.on(Events.InteractionCreate, async (interaction) => { console.error("unknown context command: " + commandName) return } + // The cast here is valid, since the type of the interaction is set in accordance to the definition + if (command.targetType != (interaction.isUserContextMenuCommand() ? ApplicationCommandType.User : ApplicationCommandType.Message)) + console.error("Out of date discord definition of this context command") try { - await command.run(interaction, interaction.targetId) + await command.run(interaction, interaction.isUserContextMenuCommand() ? interaction.targetUser : interaction.targetMessage) } catch (e) { console.error("error during context command execution: " + commandName, e) interaction.reply("something sharted itself")