import { MenuCommandContext, User, type AllChannels, type Guild, type InferWithPrefix, type MessageCommandInteraction, type ReturnCache, type UserCommandInteraction, type WebhookMessage, } from '../..'; import type { Client, WorkerClient } from '../../client'; import { MessageFlags, type If, type UnionToTuple, type When } from '../../common'; import type { InteractionCreateBodyRequest, InteractionMessageUpdateBodyRequest } from '../../common/types/write'; import { Message, type ChatInputCommandInteraction, type GuildMember, type InteractionGuildMember, } from '../../structures'; import type { RegisteredMiddlewares } from '../decorators'; import type { OptionResolver } from '../optionresolver'; import type { Command, ContextOptions, OptionsRecord, SubCommand } from './chat'; import type { CommandMetadata, ExtendContext, GlobalMetadata, UsingClient } from './shared'; export interface CommandContext extends ExtendContext {} export class CommandContext { message!: If; interaction!: If; messageResponse?: If; constructor( readonly client: UsingClient, data: ChatInputCommandInteraction | Message, readonly resolver: OptionResolver, readonly shardId: number, readonly command: Command | SubCommand, ) { if (data instanceof Message) { this.message = data as never; } else { this.interaction = data; } } options: ContextOptions = {} as never; metadata: CommandMetadata> = {} as never; globalMetadata: GlobalMetadata = {}; get proxy() { return this.client.proxy; } get t() { return this.client.langs!.get(this.interaction?.locale ?? this.client.langs!.defaultLang ?? 'en-US'); } get fullCommandName() { return this.resolver.fullCommandName; } async write( body: InteractionCreateBodyRequest, fetchReply?: FR, ): Promise> { if (this.interaction) return this.interaction.write(body, fetchReply); const options = (this.client as Client | WorkerClient).options?.commands; return (this.messageResponse = await (this.message! as Message)[ !this.messageResponse && options?.reply?.(this) ? 'reply' : 'write' ](body)); } async deferReply(ephemeral = false) { if (this.interaction) return this.interaction.deferReply(ephemeral ? MessageFlags.Ephemeral : undefined); const options = (this.client as Client | WorkerClient).options?.commands; return (this.messageResponse = await (this.message! as Message)[options?.reply?.(this) ? 'reply' : 'write']( options?.deferReplyResponse?.(this) ?? { content: 'Thinking...' }, )); } async editResponse(body: InteractionMessageUpdateBodyRequest) { if (this.interaction) return this.interaction.editResponse(body); return (this.messageResponse = await this.messageResponse!.edit(body)); } deleteResponse() { if (this.interaction) return this.interaction.deleteResponse(); return this.messageResponse!.delete(); } editOrReply( body: InteractionCreateBodyRequest | InteractionMessageUpdateBodyRequest, fetchReply?: FR, ): Promise> { if (this.interaction) return this.interaction.editOrReply(body as InteractionCreateBodyRequest, fetchReply); if (this.messageResponse) { return this.editResponse(body); } return this.write(body as InteractionCreateBodyRequest, fetchReply); } async fetchResponse(): Promise< If > { if (this.interaction) return this.interaction.fetchResponse(); this.messageResponse = await this.messageResponse?.fetch(); return this.messageResponse as undefined; } channel(mode?: 'rest' | 'flow'): Promise>; channel(mode?: 'cache'): ReturnCache>; channel(mode: 'cache' | 'rest' | 'flow' = 'cache') { if (this.interaction?.channel && mode === 'cache') return this.client.cache.adapter.isAsync ? Promise.resolve(this.interaction.channel) : this.interaction.channel; switch (mode) { case 'cache': return ( this.client.cache.channels?.get(this.channelId) || (this.client.cache.adapter.isAsync ? (Promise.resolve() as any) : undefined) ); default: return this.client.channels.fetch(this.channelId, mode === 'rest'); } } me(mode?: 'rest' | 'flow'): Promise; me(mode?: 'cache'): ReturnCache; me(mode: 'cache' | 'rest' | 'flow' = 'cache') { 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) || (this.client.cache.adapter.isAsync ? (Promise.resolve() as any) : undefined) ); default: return this.client.members.fetch(this.guildId, this.client.botId, mode === 'rest'); } } guild(mode?: 'rest' | 'flow'): Promise | undefined>; guild(mode?: 'cache'): ReturnCache | undefined>; guild(mode: 'cache' | 'rest' | 'flow' = 'cache') { if (!this.guildId) return (mode === 'cache' ? this.client.cache.adapter.isAsync ? Promise.resolve() : undefined : Promise.resolve()) as unknown as undefined; 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, mode === 'rest'); } } get guildId() { return this.interaction?.guildId || (this.message! as Message | undefined)?.guildId; } get channelId() { return this.interaction?.channelId || (this.message! as Message).channelId; } get author() { return this.interaction?.user || (this.message! as Message).author; } get member(): If< InferWithPrefix, GuildMember | InteractionGuildMember | undefined, InteractionGuildMember | undefined > { return this.interaction?.member || ((this.message! as Message)?.member as any); } isChat(): this is CommandContext { return this instanceof CommandContext; } isMenu(): this is MenuCommandContext { return this instanceof MenuCommandContext; } isMenuUser(): this is MenuCommandContext { return this instanceof MenuCommandContext && this.target instanceof User; } isMenuMessage(): this is MenuCommandContext { return this instanceof MenuCommandContext && this.target instanceof Message; } }