fix: component context typing

This commit is contained in:
Marcos Susaña 2024-05-07 13:00:05 -04:00
parent 6110337704
commit 85d2a20365
4 changed files with 42 additions and 14 deletions

View File

@ -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<keyof ComponentCommandInteractionMap> {
isComponent(): this is ComponentContext<keyof ContextComponentCommandInteractionMap> {
return false;
}
}

View File

@ -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<typeof this.componentType>): Promise<boolean> | boolean;
abstract run(interaction: ComponentContext<typeof this.componentType>): any;

View File

@ -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<Type extends keyof ComponentCommandInteractionMap>
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<Type extends keyof ComponentCommandInteractionMap> extends BaseContext {
export class ComponentContext<Type extends keyof ContextComponentCommandInteractionMap> extends BaseContext {
/**
* Creates a new instance of the ComponentContext class.
* @param client - The UsingClient instance.
@ -39,7 +40,7 @@ export class ComponentContext<Type extends keyof ComponentCommandInteractionMap>
*/
constructor(
readonly client: UsingClient,
public interaction: ComponentCommandInteractionMap[Type] | ComponentInteraction,
public interaction: ContextComponentCommandInteractionMap[Type],
) {
super(client);
}
@ -118,6 +119,10 @@ export class ComponentContext<Type extends keyof ComponentCommandInteractionMap>
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<Type extends keyof ComponentCommandInteractionMap>
return this.interaction.member;
}
isComponent(): this is ComponentContext<keyof ComponentCommandInteractionMap> {
isComponent(): this is ComponentContext<keyof ContextComponentCommandInteractionMap> {
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;

View File

@ -205,6 +205,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);