diff --git a/src/commands/basecontext.ts b/src/commands/basecontext.ts index 3558f87..cac0eef 100644 --- a/src/commands/basecontext.ts +++ b/src/commands/basecontext.ts @@ -1,4 +1,4 @@ -import type { ComponentCommandInteractionMap, ComponentContext } from '../components/componentcontext'; +import type { ContextComponentCommandInteractionMap, ComponentContext } from '../components/componentcontext'; import type { MessageCommandInteraction, UserCommandInteraction } from '../structures'; import type { CommandContext } from './applications/chatcontext'; import type { MenuCommandContext } from './applications/menucontext'; @@ -27,7 +27,7 @@ export class BaseContext { return false; } - isComponent(): this is ComponentContext { + isComponent(): this is ComponentContext { return false; } } diff --git a/src/components/command.ts b/src/components/command.ts index 3cdfdab..87d5751 100644 --- a/src/components/command.ts +++ b/src/components/command.ts @@ -1,6 +1,6 @@ import { ComponentType } from 'discord-api-types/v10'; import type { ModalSubmitInteraction } from '../structures'; -import type { ComponentCommandInteractionMap, ComponentContext } from './componentcontext'; +import type { ContextComponentCommandInteractionMap, ComponentContext } from './componentcontext'; export const InteractionCommandType = { COMPONENT: 0, @@ -13,7 +13,7 @@ export interface ComponentCommand { export abstract class ComponentCommand { type = InteractionCommandType.COMPONENT; - abstract componentType: keyof ComponentCommandInteractionMap; + abstract componentType: keyof ContextComponentCommandInteractionMap; abstract filter(interaction: ComponentContext): Promise | boolean; abstract run(interaction: ComponentContext): any; diff --git a/src/components/componentcontext.ts b/src/components/componentcontext.ts index 656d3b5..8cdb314 100644 --- a/src/components/componentcontext.ts +++ b/src/components/componentcontext.ts @@ -1,9 +1,8 @@ -import { MessageFlags } from 'discord-api-types/v10'; +import { ComponentType, MessageFlags } from 'discord-api-types/v10'; import type { AllChannels, ButtonInteraction, ChannelSelectMenuInteraction, - ComponentInteraction, Guild, GuildMember, MentionableSelectMenuInteraction, @@ -20,18 +19,20 @@ import type { ComponentInteractionMessageUpdate, InteractionCreateBodyRequest, InteractionMessageUpdateBodyRequest, + ModalCreateBodyRequest, When, } from '../common'; -export interface ComponentContext - extends BaseContext, +export interface ComponentContext< + Type extends keyof ContextComponentCommandInteractionMap = keyof ContextComponentCommandInteractionMap, +> extends BaseContext, ExtendContext {} /** * Represents a context for interacting with components in a Discord bot. * @template Type - The type of component interaction. */ -export class ComponentContext extends BaseContext { +export class ComponentContext extends BaseContext { /** * Creates a new instance of the ComponentContext class. * @param client - The UsingClient instance. @@ -39,7 +40,7 @@ export class ComponentContext */ constructor( readonly client: UsingClient, - public interaction: ComponentCommandInteractionMap[Type] | ComponentInteraction, + public interaction: ContextComponentCommandInteractionMap[Type], ) { super(client); } @@ -118,6 +119,10 @@ export class ComponentContext return this.interaction.deleteResponse(); } + modal(body: ModalCreateBodyRequest) { + return this.interaction.modal(body); + } + /** * Gets the channel of the interaction. * @param mode - The mode to fetch the channel. @@ -197,16 +202,38 @@ export class ComponentContext return this.interaction.member; } - isComponent(): this is ComponentContext { + isComponent(): this is ComponentContext { return true; } + + isButton(): this is ComponentContext<'Button'> { + return this.interaction.data.componentType === ComponentType.Button; + } + + isChannelSelectMenu(): this is ComponentContext<'ChannelSelect'> { + return this.interaction.componentType === ComponentType.ChannelSelect; + } + + isRoleSelectMenu(): this is ComponentContext<'RoleSelect'> { + return this.interaction.componentType === ComponentType.RoleSelect; + } + + isMentionableSelectMenu(): this is ComponentContext<'MentionableSelect'> { + return this.interaction.componentType === ComponentType.MentionableSelect; + } + + isUserSelectMenu(): this is ComponentContext<'UserSelect'> { + return this.interaction.componentType === ComponentType.UserSelect; + } + + isStringSelectMenu(): this is ComponentContext<'StringSelect'> { + return this.interaction.componentType === ComponentType.StringSelect; + } } -export interface ComponentCommandInteractionMap { - ActionRow: never; +export interface ContextComponentCommandInteractionMap { Button: ButtonInteraction; StringSelect: StringSelectMenuInteraction; - TextInput: never; UserSelect: UserSelectMenuInteraction; RoleSelect: RoleSelectMenuInteraction; MentionableSelect: MentionableSelectMenuInteraction; diff --git a/src/components/handler.ts b/src/components/handler.ts index 6b83d91..15d6a7a 100644 --- a/src/components/handler.ts +++ b/src/components/handler.ts @@ -207,6 +207,7 @@ export class ComponentHandler extends BaseHandler { for (const i of this.commands) { try { if (i.type === InteractionCommandType.COMPONENT && i.cType === interaction.componentType) { + // @ts-expect-error ComponentInteraction is a generic class const context = new ComponentContext(this.client, interaction); const extended = this.client.options?.context?.(interaction) ?? {}; Object.assign(context, extended);