import type { ContextMenuCommand, InteractionGuildMemberStructure, ReturnCache } from '../..'; import { type GuildMemberStructure, type GuildStructure, type MessageStructure, Transformers, type UserStructure, type WebhookMessageStructure, } from '../../client/transformers'; import { type InteractionCreateBodyRequest, type InteractionMessageUpdateBodyRequest, type MakeRequired, type MessageWebhookCreateBodyRequest, type ModalCreateBodyRequest, type UnionToTuple, type When, toSnakeCase, } from '../../common'; import type { AllChannels, MessageCommandInteraction, UserCommandInteraction } from '../../structures'; import { type APIMessage, ApplicationCommandType, MessageFlags, type RESTGetAPIGuildQuery } from '../../types'; import { BaseContext } from '../basecontext'; import type { RegisteredMiddlewares } from '../decorators'; import type { CommandMetadata, ExtendContext, GlobalMetadata, UsingClient } from './shared'; export type InteractionTarget = T extends MessageCommandInteraction ? MessageStructure : UserStructure; export interface MenuCommandContext< T extends MessageCommandInteraction | UserCommandInteraction, M extends keyof RegisteredMiddlewares = never, > extends BaseContext, ExtendContext {} export class MenuCommandContext< T extends MessageCommandInteraction | UserCommandInteraction, M extends keyof RegisteredMiddlewares = never, > extends BaseContext { constructor( readonly client: UsingClient, readonly interaction: T, readonly shardId: number, readonly command: ContextMenuCommand, ) { super(client); } metadata: CommandMetadata> = {} as never; globalMetadata: GlobalMetadata = {}; // biome-ignore lint/suspicious/useGetterReturn: default don't exist. get target(): InteractionTarget { switch (this.interaction.data.type) { case ApplicationCommandType.Message: { const data = this.interaction.data.resolved.messages[this.interaction.data.targetId as Lowercase]; return Transformers.Message(this.client, toSnakeCase(data) as APIMessage) as never; } case ApplicationCommandType.User: { const data = this.interaction.data.resolved.users[this.interaction.data.targetId as Lowercase]; return Transformers.User(this.client, toSnakeCase(data)) as never; } } } get t() { return this.client.t(this.interaction.locale ?? this.client.langs.defaultLang ?? 'en-US'); } get fullCommandName() { return this.command.name; } write( body: InteractionCreateBodyRequest, withResponse?: WR, ): Promise> { return this.interaction.write(body, withResponse); } modal(body: ModalCreateBodyRequest) { return this.interaction.modal(body); } deferReply( ephemeral = false, withResponse?: WR, ): Promise> { return this.interaction.deferReply(ephemeral ? MessageFlags.Ephemeral : undefined, withResponse); } editResponse(body: InteractionMessageUpdateBodyRequest): Promise { return this.interaction.editResponse(body); } deleteResponse() { return this.interaction.deleteResponse(); } editOrReply( body: InteractionCreateBodyRequest | InteractionMessageUpdateBodyRequest, withResponse?: WR, ): Promise> { return this.interaction.editOrReply(body as InteractionCreateBodyRequest, withResponse); } followup(body: MessageWebhookCreateBodyRequest): Promise { return this.interaction.followup(body); } fetchResponse(): Promise { return this.interaction.fetchResponse(); } channel(mode?: 'rest' | 'flow'): Promise; channel(mode: 'cache'): ReturnCache; channel(mode: 'cache' | 'rest' | 'flow' = 'flow') { if (mode === 'cache') return this.client.cache.adapter.isAsync ? Promise.resolve(this.interaction.channel) : this.interaction.channel; return this.client.channels.fetch(this.channelId, mode === 'rest'); } me(mode?: 'rest' | 'flow'): Promise; me(mode: 'cache'): ReturnCache; me(mode: 'cache' | 'rest' | 'flow' = 'flow'): any { if (!this.guildId) return mode === 'cache' ? (this.client.cache.adapter.isAsync ? Promise.resolve() : undefined) : Promise.resolve(); switch (mode) { case 'cache': return this.client.cache.members?.get(this.client.botId, this.guildId); default: return this.client.members.fetch(this.guildId, this.client.botId, mode === 'rest'); } } guild(mode?: 'rest' | 'flow', query?: RESTGetAPIGuildQuery): Promise | undefined>; guild(mode: 'cache', query?: RESTGetAPIGuildQuery): ReturnCache | undefined>; guild(mode: 'cache' | 'rest' | 'flow' = 'flow', query?: RESTGetAPIGuildQuery) { if (!this.guildId) return mode === 'cache' ? (this.client.cache.adapter.isAsync ? Promise.resolve() : undefined) : Promise.resolve(); switch (mode) { case 'cache': return ( this.client.cache.guilds?.get(this.guildId) || (this.client.cache.adapter.isAsync ? (Promise.resolve() as any) : undefined) ); default: return this.client.guilds.fetch(this.guildId, { force: mode === 'rest', query }); } } get guildId() { return this.interaction.guildId; } get channelId() { return this.interaction.channel.id; } get author(): UserStructure { return this.interaction.user; } get member(): InteractionGuildMemberStructure | undefined { return this.interaction.member; } isMenu(): this is MenuCommandContext { return true; } isMenuUser(): this is MenuCommandContext { return this.interaction.data.type === ApplicationCommandType.User; } isMenuMessage(): this is MenuCommandContext { return this.interaction.data.type === ApplicationCommandType.Message; } inGuild(): this is GuildMenuCommandContext { return !!this.guildId; } } export interface GuildMenuCommandContext< T extends MessageCommandInteraction | UserCommandInteraction, M extends keyof RegisteredMiddlewares = never, > extends Omit, 'guildId' | 'member'>, 'guild'> { guild(mode?: 'rest' | 'flow'): Promise>; guild(mode: 'cache'): ReturnCache | undefined>; }