@seedcord/http 0.10.2 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -9
- package/dist/index.d.mts +42 -57
- package/dist/index.mjs +144 -239
- package/dist/index.mjs.map +1 -1
- package/dist/shared-vsj1uwIH.d.mts +977 -0
- package/dist/{edge.index-DCP1BD6f.mjs → username-B6enaS_x.mjs} +1634 -1519
- package/dist/username-B6enaS_x.mjs.map +1 -0
- package/dist/workerd.index.d.mts +65 -0
- package/dist/workerd.index.mjs +177 -0
- package/dist/workerd.index.mjs.map +1 -0
- package/package.json +22 -30
- package/dist/Manifest-D5MEsTmH.d.mts +0 -485
- package/dist/edge.index-DCP1BD6f.mjs.map +0 -1
- package/dist/edge.index-DFszgCJp.d.mts +0 -502
- package/dist/edge.index.d.mts +0 -10
- package/dist/edge.index.mjs +0 -15
- package/dist/manifest.index.d.mts +0 -10
- package/dist/manifest.index.mjs +0 -26
- package/dist/manifest.index.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"username-B6enaS_x.mjs","names":["Plugin","CorePlugin","RepliableHandler","CoreRepliableHandler","RepliableHandler","RepliableHandler","Subscriber","CoreSubscriber","WebhookLog","CoreWebhookLog","RepliableHandler"],"sources":["../src/Plugin.ts","../src/inputs/pick.ts","../src/inputs/ModalFields.ts","../src/emojis/EmojiInjector.ts","../src/reply/ReplySender.ts","../src/api.ts","../src/handlers/RepliableHandler.ts","../src/handlers/interaction/InteractionHandler.ts","../src/handlers/interaction/InteractionMiddleware.ts","../src/inputs/HttpSlashOptions.ts","../src/dispatch/slashRouteOf.ts","../src/handlers/interaction/SlashHandler.ts","../src/handlers/interaction/ContextMenuHandler.ts","../src/handlers/interaction/AutocompleteHandler.ts","../src/handlers/interaction/components/ComponentHandler.ts","../src/handlers/interaction/components/ButtonHandler.ts","../src/handlers/interaction/components/ModalHandler.ts","../src/handlers/interaction/components/SelectMenuHandler.ts","../src/subscribers/index.ts","../src/pagination/Paginator.ts","../src/pagination/sources.ts","../src/gates/Gated.ts","../src/version.ts","../src/publicKey.ts","../src/HttpStartupTasks.ts","../src/handlers/defaults/UnhandledAutocomplete.ts","../src/handlers/defaults/UnhandledRepliable.ts","../src/dispatch/resolve.ts","../src/dispatch/RouteRegistry.ts","../src/dispatch/InteractionDispatcher.ts","../src/gates/context.ts","../src/dispatch/reportFault.ts","../src/dispatch/dispatchInteraction.ts","../src/receiver/Ed25519Verifier.ts","../src/receiver/ReplayGuard.ts","../src/engine.ts","../src/InteractionsService.ts","../src/username.ts"],"sourcesContent":["import { FixedScope } from '@seedcord/core/internal';\nimport { Plugin as CorePlugin } from '@seedcord/core/plugin';\n\nimport type { Core } from '#interfaces/Core';\nimport type { PluginOptions } from '@seedcord/core/plugin';\nimport type { TypedOmit } from '@seedcord/types';\n\n/** The options an HTTP plugin declares, narrowed to the transports this base serves. */\nexport type HttpPluginOptions = TypedOmit<PluginOptions, 'transport'> & { transport?: 'http' };\n\nconst HTTP_SCOPE = { transport: 'http' } as const;\n\n/**\n * Base class for an HTTP plugin, binding `this.core` to the HTTP {@link Core}.\n *\n * A plugin that runs on either transport extends the base from `@seedcord/core/plugin`, whose\n * `this.core` is typed to the shared members only.\n *\n * @typeParam Opts - The transport and runtime the plugin declares.\n */\nexport abstract class Plugin<Opts extends HttpPluginOptions = { transport: 'http' }> extends CorePlugin<\n Opts,\n Core,\n keyof typeof HTTP_SCOPE\n> {\n /** @internal */\n protected static override readonly [FixedScope] = HTTP_SCOPE;\n}\n\nexport type { PluginLifecycleSpec, PluginOptions } from '@seedcord/core/plugin';\n","import { Collection } from '@discordjs/collection';\n\n// a Collection because the gateway handlers return discord.js Collections for the same picks\nexport function pick<Value>(\n ids: readonly string[] | undefined,\n bucket: Record<string, Value> | undefined\n): Collection<string, Value> {\n const found = new Collection<string, Value>();\n if (!ids || !bucket) return found;\n for (const id of ids) if (Object.hasOwn(bucket, id)) found.set(id, bucket[id] as Value);\n return found;\n}\n","import { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordTypeError } from '@seedcord/errors/internal';\nimport { ChannelType, ComponentType } from 'discord-api-types/v10';\n\nimport { pick } from '#inputs/pick';\n\nimport type { Collection } from '@discordjs/collection';\nimport type {\n APIAttachment,\n APIInteractionDataResolved,\n APIInteractionDataResolvedChannel,\n APIInteractionDataResolvedGuildMember,\n APIModalSubmission,\n APIRole,\n APIUser,\n ModalSubmitComponent\n} from 'discord-api-types/v10';\n\ntype FieldKind = ModalSubmitComponent['type'];\ntype KindWithValues = Extract<ModalSubmitComponent, { values: string[] }>['type'];\n\ninterface KindLabel {\n label: string;\n getter: string;\n}\n\nconst FIELD_KINDS: Record<FieldKind, KindLabel> = {\n [ComponentType.TextInput]: { label: 'a text input', getter: 'getTextInputValue' },\n [ComponentType.StringSelect]: { label: 'a string select', getter: 'getStringSelectValues' },\n [ComponentType.UserSelect]: { label: 'a user select', getter: 'getSelectedUsers' },\n [ComponentType.RoleSelect]: { label: 'a role select', getter: 'getSelectedRoles' },\n [ComponentType.MentionableSelect]: { label: 'a mentionable select', getter: 'getSelectedMentionables' },\n [ComponentType.ChannelSelect]: { label: 'a channel select', getter: 'getSelectedChannels' },\n [ComponentType.FileUpload]: { label: 'a file upload', getter: 'getUploadedFiles' },\n [ComponentType.RadioGroup]: { label: 'a radio group', getter: 'getRadioGroup' },\n [ComponentType.CheckboxGroup]: { label: 'a checkbox group', getter: 'getCheckboxGroup' },\n [ComponentType.Checkbox]: { label: 'a checkbox', getter: 'getCheckbox' }\n};\n\nfunction nameOfChannelType(type: ChannelType): string {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- ChannelType doesn't have a member for a type discord adds later\n return ChannelType[type] ?? String(type);\n}\n\nfunction listOf(values: string[]): string[] {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- discord.js guards this key on every select kind\n return values ?? [];\n}\n\nfunction isKind<Kind extends FieldKind>(\n entry: ModalSubmitComponent,\n kinds: readonly Kind[]\n): entry is Extract<ModalSubmitComponent, { type: Kind }> {\n return (kinds as readonly FieldKind[]).includes(entry.type);\n}\n\n/** The users, members, and roles a mentionable select picked. */\nexport interface SelectedMentionables {\n users: Collection<string, APIUser>;\n members: Collection<string, APIInteractionDataResolvedGuildMember>;\n roles: Collection<string, APIRole>;\n}\n\n/**\n * The fields a modal carries, read by custom id.\n *\n * A select getter resolves the ids its field picked against the interaction's `resolved` data and returns a\n * `Collection` keyed by id. A field that picked nothing returns null.\n *\n * @throws A **SeedcordTypeError** from every getter when no field in the modal has that custom id.\n * @throws A **SeedcordTypeError** from every getter when the field holds a kind that getter does not read. The message gives the getter that does.\n * @throws A **SeedcordTypeError** from a select getter called with `required` when its field picked nothing.\n */\nexport class ModalFields {\n private readonly entries = new Map<string, ModalSubmitComponent>();\n private readonly resolved: APIInteractionDataResolved | undefined;\n\n constructor(data: APIModalSubmission) {\n this.resolved = data.resolved;\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- the wire can omit components even though the typing requires it\n for (const component of data.components ?? []) {\n // discord nests each field under an action row or a label\n if ('components' in component) {\n for (const child of component.components) this.entries.set(child.custom_id, child);\n }\n if ('component' in component) this.entries.set(component.component.custom_id, component.component);\n }\n }\n\n private entry(customId: string): ModalSubmitComponent {\n const found = this.entries.get(customId);\n if (!found) throw new SeedcordTypeError(SeedcordErrorCode.ModalFieldNotFound, [customId]);\n return found;\n }\n\n private field<Kind extends FieldKind>(\n customId: string,\n kinds: readonly Kind[]\n ): Extract<ModalSubmitComponent, { type: Kind }> {\n const entry = this.entry(customId);\n if (!isKind(entry, kinds)) {\n // a modal can carry a component type newer than this enum\n const known = (FIELD_KINDS as Partial<Record<ComponentType, KindLabel>>)[entry.type];\n const args = known\n ? ([customId, known.label, known.getter] as const)\n : ([customId, `component type ${entry.type}`] as const);\n throw new SeedcordTypeError(SeedcordErrorCode.ModalFieldWrongKind, [...args]);\n }\n return entry;\n }\n\n private selected<Value>(\n customId: string,\n kinds: readonly KindWithValues[],\n bucket: Record<string, Value> | undefined,\n required: boolean\n ): Collection<string, Value> | null {\n const { values } = this.field(customId, kinds);\n const found = pick(values, bucket);\n if (found.size > 0) return found;\n if (required) throw new SeedcordTypeError(SeedcordErrorCode.ModalFieldEmpty, [customId]);\n return null;\n }\n\n /**\n * Returns the field with this custom id, as Discord sent it. Use it for a component type the typed\n * getters do not cover.\n *\n * Pass a component type to get that exact type back.\n *\n * @throws A **SeedcordTypeError** when no field has this custom id.\n * @throws A **SeedcordTypeError** when you pass a component type and the field holds a different one.\n */\n getField<Kind extends FieldKind>(customId: string, kind: Kind): Extract<ModalSubmitComponent, { type: Kind }>;\n getField(customId: string): ModalSubmitComponent;\n getField(customId: string, kind?: FieldKind): ModalSubmitComponent {\n return kind === undefined ? this.entry(customId) : this.field(customId, [kind]);\n }\n\n getTextInputValue(customId: string): string {\n return this.field(customId, [ComponentType.TextInput]).value;\n }\n\n getStringSelectValues(customId: string): string[] {\n return listOf(this.field(customId, [ComponentType.StringSelect]).values);\n }\n\n getSelectedUsers(customId: string, required: true): Collection<string, APIUser>;\n getSelectedUsers(customId: string, required?: boolean): Collection<string, APIUser> | null;\n getSelectedUsers(customId: string, required = false): Collection<string, APIUser> | null {\n const kinds = [ComponentType.UserSelect, ComponentType.MentionableSelect] as const;\n return this.selected(customId, kinds, this.resolved?.users, required);\n }\n\n /** The guild members behind the picked users. Discord resolves these only inside a guild. */\n getSelectedMembers(customId: string): Collection<string, APIInteractionDataResolvedGuildMember> | null {\n const kinds = [ComponentType.UserSelect, ComponentType.MentionableSelect] as const;\n return this.selected(customId, kinds, this.resolved?.members, false);\n }\n\n getSelectedRoles(customId: string, required: true): Collection<string, APIRole>;\n getSelectedRoles(customId: string, required?: boolean): Collection<string, APIRole> | null;\n getSelectedRoles(customId: string, required = false): Collection<string, APIRole> | null {\n const kinds = [ComponentType.RoleSelect, ComponentType.MentionableSelect] as const;\n return this.selected(customId, kinds, this.resolved?.roles, required);\n }\n\n /** Pass `channelTypes` to throw when a pick falls outside those types. */\n getSelectedChannels(\n customId: string,\n required: true,\n channelTypes?: readonly ChannelType[]\n ): Collection<string, APIInteractionDataResolvedChannel>;\n getSelectedChannels(\n customId: string,\n required?: boolean,\n channelTypes?: readonly ChannelType[]\n ): Collection<string, APIInteractionDataResolvedChannel> | null;\n getSelectedChannels(\n customId: string,\n required = false,\n channelTypes: readonly ChannelType[] = []\n ): Collection<string, APIInteractionDataResolvedChannel> | null {\n const kinds = [ComponentType.ChannelSelect] as const;\n const picked = this.selected(customId, kinds, this.resolved?.channels, required);\n if (!picked || channelTypes.length === 0) return picked;\n for (const found of picked.values()) {\n if (channelTypes.includes(found.type)) continue;\n throw new SeedcordTypeError(SeedcordErrorCode.ModalFieldChannelType, [\n customId,\n nameOfChannelType(found.type),\n channelTypes.map(nameOfChannelType)\n ]);\n }\n return picked;\n }\n\n getSelectedMentionables(customId: string, required: true): SelectedMentionables;\n getSelectedMentionables(customId: string, required?: boolean): SelectedMentionables | null;\n getSelectedMentionables(customId: string, required = false): SelectedMentionables | null {\n const { values } = this.field(customId, [ComponentType.MentionableSelect]);\n const resolved = this.resolved;\n const picked: SelectedMentionables = {\n users: pick(values, resolved?.users),\n members: pick(values, resolved?.members),\n roles: pick(values, resolved?.roles)\n };\n if (picked.users.size + picked.members.size + picked.roles.size > 0) return picked;\n if (required) throw new SeedcordTypeError(SeedcordErrorCode.ModalFieldEmpty, [customId]);\n return null;\n }\n\n getUploadedFiles(customId: string, required: true): Collection<string, APIAttachment>;\n getUploadedFiles(customId: string, required?: boolean): Collection<string, APIAttachment> | null;\n getUploadedFiles(customId: string, required = false): Collection<string, APIAttachment> | null {\n const kinds = [ComponentType.FileUpload] as const;\n return this.selected(customId, kinds, this.resolved?.attachments, required);\n }\n\n getRadioGroup(customId: string, required: true): string;\n getRadioGroup(customId: string, required?: boolean): string | null;\n getRadioGroup(customId: string, required = false): string | null {\n // discord.js guards this key against an absent value\n const value = this.field(customId, [ComponentType.RadioGroup]).value ?? null;\n if (value !== null) return value;\n if (required) throw new SeedcordTypeError(SeedcordErrorCode.ModalFieldEmpty, [customId]);\n return null;\n }\n\n getCheckboxGroup(customId: string): string[] {\n return listOf(this.field(customId, [ComponentType.CheckboxGroup]).values);\n }\n\n getCheckbox(customId: string): boolean {\n return this.field(customId, [ComponentType.Checkbox]).value;\n }\n}\n","import { ResolvedEmoji } from '@seedcord/core';\nimport { accessorStore, clearStore, guardedAccessor, resolveEmojis } from '@seedcord/core/internal';\nimport { Logger } from '@seedcord/logger';\n\nimport type { Core } from '#interfaces/Core';\nimport type { BakedIds } from '@seedcord/core/internal';\nimport type { EmojiMap } from '@seedcord/types';\n\nconst emojiStorage = accessorStore<ResolvedEmoji>();\n\n/** The global {@link Emojis} accessor type. */\nexport type InjectedEmojiMap = {\n [K in keyof EmojiMap]: ResolvedEmoji;\n};\n\n/**\n * The bot's resolved emojis, keyed by {@link EmojiMap}. A node bot fills these during startup. An edge\n * bot fills them on its first request, from the ids `seedcord build` wrote into the worker.\n *\n * @throws A **SeedcordError** when you read a key that was not filled.\n */\nexport const Emojis = guardedAccessor('Emojis', emojiStorage) as InjectedEmojiMap;\n\nexport function installEmojis(emojis: BakedIds['emojis']): void {\n clearStore(emojiStorage);\n for (const [key, { name, id, animated }] of Object.entries(emojis)) {\n emojiStorage[key] = new ResolvedEmoji(name, id, animated);\n }\n}\n\n// resolves the configured emojis over REST at startup\nexport class EmojiInjector {\n private readonly logger = new Logger('Emojis', { channel: 'bot' });\n\n constructor(private readonly core: Core) {}\n\n public async init(): Promise<void> {\n const configured = this.core.config.bot.emojis;\n if (!configured || Object.keys(configured).length === 0) {\n installEmojis({});\n this.logger.debug('No emojis configured, skipping emoji injection.');\n return;\n }\n\n installEmojis(await resolveEmojis(this.core.rest, this.core.applicationId, configured));\n this.logger.utils.summary('Loaded emojis', { emojis: Object.keys(emojiStorage).length });\n }\n}\n","import { BaseReplySender } from '@seedcord/core';\nimport { deferFlags, sendFlags } from '@seedcord/core/internal';\nimport { InteractionResponseType, MessageFlags, Routes } from 'discord-api-types/v10';\n\nimport type { REST, RawFile } from '@discordjs/rest';\nimport type { Bus, DispatchContext } from '@seedcord/core';\nimport type { SerializedReply } from '@seedcord/core/internal';\nimport type { DeferOpts, ReplyResponse, SendOpts, TypedOmit } from '@seedcord/types';\nimport type { APIMessage, APIModalInteractionResponseCallbackData } from 'discord-api-types/v10';\n\n/** The interaction payload fields the sender writes its wire from. */\nexport interface InteractionRef {\n readonly application_id: string;\n readonly id: string;\n readonly token: string;\n}\n\n/** The created message an http reply resolves to (the http `SentMessage` lens). */\nexport type SentMessage = APIMessage;\n\n// the framework's allowedMentions keys are camelCase, and the wire reads replied_user\ntype WireAllowedMentions = TypedOmit<NonNullable<ReplyResponse['allowedMentions']>, 'repliedUser'> & {\n replied_user?: boolean;\n};\n\ninterface WireAttachment {\n id: number;\n filename: string;\n description?: string;\n title?: string;\n}\n\ninterface MessageBody {\n flags: number;\n components: SerializedReply['components'];\n allowed_mentions?: WireAllowedMentions;\n attachments?: WireAttachment[];\n}\n\nfunction wireAllowedMentions(mentions: NonNullable<ReplyResponse['allowedMentions']>): WireAllowedMentions {\n const { repliedUser, ...wire } = mentions;\n return { ...wire, ...(repliedUser !== undefined && { replied_user: repliedUser }) };\n}\n\n// RawFile has no description field\nfunction wireAttachments(files: SerializedReply['files']): WireAttachment[] | null {\n if (!files?.some((file) => file.description ?? file.title)) return null;\n return files.map((file, index) => ({\n id: index,\n filename: file.name,\n ...(file.description && { description: file.description }),\n ...(file.title && { title: file.title })\n }));\n}\n\nfunction callbackData(reply: SerializedReply, flags: number): MessageBody {\n const attachments = wireAttachments(reply.files);\n return {\n flags,\n components: reply.components,\n ...(reply.allowedMentions && { allowed_mentions: wireAllowedMentions(reply.allowedMentions) }),\n ...(attachments && { attachments })\n };\n}\n\n/**\n * Writes interaction responses over the Discord REST callback and webhook endpoints. Construction is\n * internal to the repliable handler bases and the dispatcher.\n */\nexport class ReplySender extends BaseReplySender<SentMessage> {\n public constructor(\n private readonly ref: InteractionRef,\n private readonly rest: REST,\n dispatch: DispatchContext,\n bus: Bus\n ) {\n super({ bus, dispatch, interactionId: ref.id });\n }\n\n protected async writeReply(response: ReplyResponse | string, opts?: SendOpts): Promise<SentMessage | undefined> {\n const reply = this.serialize(response);\n const result = await this.callback(\n InteractionResponseType.ChannelMessageWithSource,\n callbackData(reply, sendFlags(opts)),\n reply.files\n );\n return this.createdMessage(result);\n }\n\n protected async writeDefer(opts?: DeferOpts): Promise<void> {\n await this.callback(InteractionResponseType.DeferredChannelMessageWithSource, { flags: deferFlags(opts) });\n }\n\n protected async writeDeferUpdate(): Promise<void> {\n await this.callback(InteractionResponseType.DeferredMessageUpdate);\n }\n\n protected async writeUpdate(response: ReplyResponse | string): Promise<SentMessage | undefined> {\n const reply = this.serialize(response);\n const result = await this.callback(\n InteractionResponseType.UpdateMessage,\n callbackData(reply, MessageFlags.IsComponentsV2),\n reply.files\n );\n return this.createdMessage(result);\n }\n\n protected async writeFollowUp(response: ReplyResponse | string, opts?: SendOpts): Promise<SentMessage> {\n const reply = this.serialize(response);\n // discord returns the created message for interaction-token followups either way. wait=true pins\n // that contract and matches the djs webhook client\n const result = await this.rest.post(Routes.webhook(this.ref.application_id, this.ref.token), {\n body: callbackData(reply, sendFlags(opts)),\n query: new URLSearchParams({ wait: 'true' }),\n ...(reply.files && { files: this.rawFiles(reply.files) })\n });\n // justified: a webhook POST returns the created message\n return result as SentMessage;\n }\n\n protected writeEditOriginal(response: ReplyResponse | string): Promise<SentMessage> {\n return this.editMessage(\n Routes.webhookMessage(this.ref.application_id, this.ref.token),\n this.serialize(response)\n );\n }\n\n protected writeEditTarget(targetId: string, response: ReplyResponse | string): Promise<SentMessage> {\n const route = Routes.webhookMessage(this.ref.application_id, this.ref.token, targetId);\n return this.editMessage(route, this.serialize(response));\n }\n\n protected async writeDeleteOriginal(): Promise<void> {\n await this.rest.delete(Routes.webhookMessage(this.ref.application_id, this.ref.token));\n }\n\n protected async writeDeleteTarget(targetId: string): Promise<void> {\n await this.rest.delete(Routes.webhookMessage(this.ref.application_id, this.ref.token, targetId));\n }\n\n protected async writeModal(data: APIModalInteractionResponseCallbackData): Promise<void> {\n await this.callback(InteractionResponseType.Modal, data);\n }\n\n private async callback(\n type: InteractionResponseType,\n data?: unknown,\n files?: SerializedReply['files']\n ): Promise<unknown> {\n const withResponse =\n type === InteractionResponseType.ChannelMessageWithSource || type === InteractionResponseType.UpdateMessage;\n return await this.rest.post(Routes.interactionCallback(this.ref.id, this.ref.token), {\n body: { type, ...(data !== undefined && { data }) },\n ...(withResponse && { query: new URLSearchParams({ with_response: 'true' }) }),\n ...(files && { files: this.rawFiles(files) })\n });\n }\n\n private async editMessage(route: `/${string}`, reply: SerializedReply): Promise<SentMessage> {\n const result = await this.rest.patch(route, {\n body: callbackData(reply, MessageFlags.IsComponentsV2),\n ...(reply.files && { files: this.rawFiles(reply.files) })\n });\n // justified: a webhook message PATCH returns the edited message\n return result as SentMessage;\n }\n\n private rawFiles(files: NonNullable<SerializedReply['files']>): RawFile[] {\n return files.map((file) => ({ name: file.name, data: file.data }));\n }\n\n private createdMessage(result: unknown): SentMessage | undefined {\n // justified: the with_response callback wire shape\n return (result as { resource?: { message?: SentMessage } }).resource?.message;\n }\n}\n","import { API } from '@discordjs/core/http-only';\n\nimport type { REST } from '@discordjs/rest';\n\nconst apis = new WeakMap<REST, API>();\n\nexport function apiFor(rest: REST): API {\n let api = apis.get(rest);\n if (!api) {\n api = new API(rest);\n apis.set(rest, api);\n }\n return api;\n}\n","import { RepliableHandler as CoreRepliableHandler } from '@seedcord/core';\n\nimport { ReplySender } from '#reply/ReplySender';\nimport { apiFor } from '#src/api';\n\nimport type { Core } from '#interfaces/Core';\nimport type { SentMessage } from '#reply/ReplySender';\nimport type { Repliables } from './interactionTypes';\nimport type { API } from '@discordjs/core/http-only';\nimport type { DispatchContext } from '@seedcord/core';\n\n/**\n * Shared base the repliable HTTP interaction handlers extend.\n *\n * Not a public entry point. Extend {@link SlashHandler}, {@link ButtonHandler}, {@link ModalHandler},\n * {@link ContextMenuHandler}, or one of the select menu bases instead. This class binds the core\n * reply base to the http sender.\n *\n * @typeParam Event - The repliable interaction type this handler processes\n */\nexport abstract class RepliableHandler<Event extends Repliables> extends CoreRepliableHandler<\n Event,\n Core,\n SentMessage,\n never,\n ReplySender\n> {\n // core's base keeps event protected, and Paginator.start reads it from outside the class\n /** @internal */\n public getEvent(): Event {\n return this.event;\n }\n\n protected buildSender(event: Event, core: Core, dispatch: DispatchContext): ReplySender {\n const ref = { application_id: event.application_id, id: event.id, token: event.token };\n return new ReplySender(ref, core.rest, dispatch, core.bus);\n }\n\n /**\n * Typed Discord REST API (`@discordjs/core/http-only`) over `core.rest`, one instance per core.\n * The interaction callbacks on `api.interactions` bypass the reply surface. The\n * `no-raw-interaction-acks` rule flags them in handler classes.\n */\n protected get api(): API {\n return apiFor(this.core.rest);\n }\n}\n","import { RepliableHandler } from '#handlers/RepliableHandler';\n\nimport type { Repliables } from '#handlers/interactionTypes';\nimport type { Core } from '#interfaces/Core';\nimport type { DispatchContext, ModalLike } from '@seedcord/core';\nimport type { APIModalSubmitInteraction } from 'discord-api-types/v10';\n\n/**\n * Shared base the repliable interaction handlers extend.\n *\n * Not a public entry point. Extend {@link SlashHandler}, {@link ContextMenuHandler}, {@link ButtonHandler},\n * {@link ModalHandler}, or one of the select menu bases instead. This class adds `showModal` on top\n * of the reply members.\n *\n * @typeParam Event - The repliable interaction type this handler processes\n */\nexport abstract class InteractionHandler<Event extends Repliables> extends RepliableHandler<Event> {\n // the dispatcher needs a public construct signature, but RepliableHandler's ctor is protected\n constructor(event: Event, core: Core, dispatch: DispatchContext) {\n super(event, core, dispatch);\n }\n\n /**\n * Open a modal. Must be the initial response to this interaction. The modal kind rejects this call at\n * compile time (Discord forbids a modal in response to a modal).\n */\n protected showModal(\n this: InteractionHandler<Exclude<Repliables, APIModalSubmitInteraction>>,\n modal: ModalLike\n ): Promise<void> {\n return this.sender.showModal(modal);\n }\n}\n","import { RepliableHandler } from '#src/handlers/RepliableHandler';\n\nimport type { Core } from '#interfaces/Core';\nimport type { ReplySender } from '#reply/ReplySender';\nimport type { InteractionOf } from './middlewareKinds';\nimport type { DispatchContext, DispatchResult, MiddlewareKind } from '@seedcord/core';\nimport type { MiddlewareKindsBrand } from '@seedcord/core/internal';\n\n/**\n * Base class for interaction middleware on the HTTP transport.\n *\n * Middleware runs after the dispatcher builds the handler and before the gates, over the handler's own\n * reply surface. Name the kinds in the generic and list the same ones in `{ kinds }`. Several kinds give\n * `this.event` a union. Narrow it on `type` and `data.component_type`. A catchall reads every repliable\n * kind.\n *\n * @typeParam Kind - One or more {@link InteractionKind} members. Defaults to every repliable kind.\n *\n * @example\n * ```ts\n * \\@RegisterInteractionMiddleware({ kinds: [InteractionKind.Button] })\n * class Audit extends InteractionMiddleware<InteractionKind.Button> {\n * async execute() {\n * this.logger.info(this.event.data.custom_id);\n * }\n * }\n * ```\n */\nexport abstract class InteractionMiddleware<\n in out Kind extends MiddlewareKind = MiddlewareKind\n> extends RepliableHandler<InteractionOf<Kind>> {\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [MiddlewareKindsBrand]?: Kind;\n\n public constructor(event: InteractionOf<Kind>, core: Core, dispatch: DispatchContext, sender: ReplySender) {\n super(event, core, dispatch, sender);\n }\n\n /**\n * Runs once the handler settles, newest middleware first. A refusal or a throw still reaches it,\n * since seedcord calls it on every middleware whose `execute()` started. Implement it to release\n * something this middleware took in `execute()`, such as a lock or an open span. A throw in here\n * is logged and goes no further.\n *\n * @param result - How the dispatch ended. Either failure state carries the thrown value on `caught`.\n *\n * @example\n * ```ts\n * // the base declares it. an implementation carries `override`.\n * override async after(result: DispatchResult) {\n * this.lock.release();\n * }\n * ```\n */\n public after?(result: DispatchResult): Promise<void>;\n}\n","import { ApplicationCommandOptionType } from 'discord-api-types/v10';\n\nimport type { SlashLikeData } from '#src/dispatch/slashRouteOf';\nimport type {\n APIApplicationCommandInteractionDataBasicOption,\n APIApplicationCommandInteractionDataOption,\n APIAttachment,\n APIInteractionDataResolved,\n APIInteractionDataResolvedChannel,\n APIInteractionDataResolvedGuildMember,\n APIRole,\n APIUser,\n InteractionType\n} from 'discord-api-types/v10';\n\ntype AnyOption = APIApplicationCommandInteractionDataOption<InteractionType>;\ntype Leaf = APIApplicationCommandInteractionDataBasicOption<InteractionType>;\n\ninterface FocusedOption {\n name: string;\n value: string;\n}\n\n// the raw-payload option reader for the typed SlashOptions/AutocompleteOptions views.\nexport class HttpSlashOptions {\n private readonly leaves = new Map<string, Leaf>();\n private readonly resolved: APIInteractionDataResolved | undefined;\n\n constructor(data: SlashLikeData) {\n this.resolved = data.resolved;\n let options: readonly AnyOption[] = data.options ?? [];\n const first = options[0];\n if (first?.type === ApplicationCommandOptionType.SubcommandGroup) options = first.options;\n const second = options[0];\n if (second?.type === ApplicationCommandOptionType.Subcommand) options = second.options ?? [];\n for (const option of options) {\n if (\n option.type !== ApplicationCommandOptionType.Subcommand &&\n option.type !== ApplicationCommandOptionType.SubcommandGroup\n ) {\n this.leaves.set(option.name, option);\n }\n }\n }\n\n getString(name: string): string | null {\n const leaf = this.leaves.get(name);\n return leaf?.type === ApplicationCommandOptionType.String ? leaf.value : null;\n }\n\n getInteger(name: string): number | null {\n const leaf = this.leaves.get(name);\n return leaf?.type === ApplicationCommandOptionType.Integer ? numeric(leaf.value) : null;\n }\n\n getNumber(name: string): number | null {\n const leaf = this.leaves.get(name);\n return leaf?.type === ApplicationCommandOptionType.Number ? numeric(leaf.value) : null;\n }\n\n getBoolean(name: string): boolean | null {\n const leaf = this.leaves.get(name);\n return leaf?.type === ApplicationCommandOptionType.Boolean ? leaf.value : null;\n }\n\n getUser(name: string): APIUser | null {\n const leaf = this.leaves.get(name);\n if (leaf?.type !== ApplicationCommandOptionType.User) return null;\n return this.resolved?.users?.[leaf.value] ?? null;\n }\n\n getMember(name: string): APIInteractionDataResolvedGuildMember | null {\n const leaf = this.leaves.get(name);\n if (leaf?.type !== ApplicationCommandOptionType.User) return null;\n return this.resolved?.members?.[leaf.value] ?? null;\n }\n\n getChannel(name: string): APIInteractionDataResolvedChannel | null {\n const leaf = this.leaves.get(name);\n if (leaf?.type !== ApplicationCommandOptionType.Channel) return null;\n return this.resolved?.channels?.[leaf.value] ?? null;\n }\n\n getRole(name: string): APIRole | null {\n const leaf = this.leaves.get(name);\n if (leaf?.type !== ApplicationCommandOptionType.Role) return null;\n return this.resolved?.roles?.[leaf.value] ?? null;\n }\n\n getAttachment(name: string): APIAttachment | null {\n const leaf = this.leaves.get(name);\n if (leaf?.type !== ApplicationCommandOptionType.Attachment) return null;\n return this.resolved?.attachments?.[leaf.value] ?? null;\n }\n\n getMentionable(name: string): APIUser | APIInteractionDataResolvedGuildMember | APIRole | null {\n const leaf = this.leaves.get(name);\n if (leaf?.type !== ApplicationCommandOptionType.Mentionable) return null;\n const resolved = this.resolved;\n return (\n resolved?.members?.[leaf.value] ?? resolved?.users?.[leaf.value] ?? resolved?.roles?.[leaf.value] ?? null\n );\n }\n\n getFocused(): FocusedOption | null {\n for (const leaf of this.leaves.values()) {\n if ('focused' in leaf && leaf.focused === true) return { name: leaf.name, value: String(leaf.value) };\n }\n return null;\n }\n}\n\n// the autocomplete wire carries integer/number values as strings\nfunction numeric(value: number | string): number | null {\n if (typeof value === 'number') return value;\n if (value.trim() === '') return null;\n const parsed = Number(value);\n return Number.isNaN(parsed) ? null : parsed;\n}\n","import { buildSlashRoute } from '@seedcord/utils/internal';\nimport { ApplicationCommandOptionType } from 'discord-api-types/v10';\n\nimport type {\n APIApplicationCommandAutocompleteInteraction,\n APIChatInputApplicationCommandInteraction\n} from 'discord-api-types/v10';\n\nexport type SlashLikeData = (\n APIChatInputApplicationCommandInteraction | APIApplicationCommandAutocompleteInteraction\n)['data'];\n\n// the raw-payload port of the gateway's slashRouteOf\n// both assemble the key through buildSlashRoute, so a dispatched interaction always matches its generated registry key\nexport function slashRouteOf(data: SlashLikeData): string {\n const first = data.options?.[0];\n if (first?.type === ApplicationCommandOptionType.SubcommandGroup) {\n return buildSlashRoute(data.name, first.options[0]?.name, first.name);\n }\n if (first?.type === ApplicationCommandOptionType.Subcommand) {\n return buildSlashRoute(data.name, first.name);\n }\n return data.name;\n}\n","import { SlashRouteBrand } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordTypeError } from '@seedcord/errors/internal';\n\nimport { InteractionHandler } from '#handlers/interaction/InteractionHandler';\nimport { HttpSlashOptions } from '#inputs/HttpSlashOptions';\nimport { slashRouteOf } from '#src/dispatch/slashRouteOf';\n\nimport type { SlashOptions } from '#inputs/SlashOptions';\nimport type { SlashRegistry } from '@seedcord/core';\nimport type { APIChatInputApplicationCommandInteraction } from 'discord-api-types/v10';\nimport type { Promisable } from 'type-fest';\n\ntype SlashMatchArms<Route extends keyof SlashRegistry, Ret> = {\n [Key in Route]: (options: SlashOptions<Key>) => Promisable<Ret>;\n};\n\n/**\n * Base class for a chat-input (slash) command handler on the HTTP transport.\n *\n * Pass the route from the generated registry as the generic, then read `this.options` for a single\n * command or `this.match` for several. Command authoring stays plain discord.js, `seedcord codegen`\n * reads its `toJSON()` to type these options.\n *\n * @typeParam Route - One or more route keys from {@link SlashRegistry}, e.g. `'ban'` or `'ban' | 'kick'`.\n */\nexport abstract class SlashHandler<\n Route extends keyof SlashRegistry\n> extends InteractionHandler<APIChatInputApplicationCommandInteraction> {\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [SlashRouteBrand]?: Route;\n\n private resolver?: HttpSlashOptions;\n\n /**\n * The typed options for this command's route. Only the getters for kinds this command declares appear.\n * Each getter's name argument is restricted to that command's options of its kind.\n *\n * - A required option drops the null.\n *\n * - Choices narrow to their literal union.\n *\n * - A channel option declared with `addChannelTypes` narrows to those types.\n *\n * Rich kinds resolve from the interaction's `resolved` data.\n */\n protected get options(): SlashOptions<Route> {\n this.resolver ??= new HttpSlashOptions(this.event.data);\n // SlashOptions is just the registry-typed view over the getters the reader already exposes\n return this.resolver as SlashOptions<Route>;\n }\n\n /**\n * Run the arm for whichever command fired. Use this only when the handler is registered for several\n * routes.\n *\n * Provide one arm per registered route, keyed by its route string, and each arm receives that route's\n * own narrowed options. The arms must cover every route in the generic, a missing route or an unknown\n * key is a compile error.\n *\n * @param arms - One handler per registered route, keyed by route string.\n * @returns The result of the arm that ran.\n */\n protected async match<Ret>(arms: SlashMatchArms<Route, Ret>): Promise<Ret> {\n const route = slashRouteOf(this.event.data);\n // justified: SlashMatchArms is keyed by Route literals, the Record cast indexes it with the runtime route string.\n const arm = Object.hasOwn(arms, route)\n ? (arms as Record<string, (options: SlashOptions<Route>) => Promisable<Ret>>)[route]\n : undefined;\n if (!arm)\n throw new SeedcordTypeError(SeedcordErrorCode.MatchArmMissing, [\n this.constructor.name,\n 'command route',\n route\n ]);\n return await arm(this.options);\n }\n}\n","import { ContextMenuKindBrand, ContextMenuNamesBrand } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordTypeError } from '@seedcord/errors/internal';\n\nimport { InteractionHandler } from '#handlers/interaction/InteractionHandler';\n\nimport type { NamesFor } from '@seedcord/core/internal';\nimport type {\n APIInteractionDataResolvedGuildMember,\n APIMessage,\n APIMessageApplicationCommandInteraction,\n APIUser,\n APIUserApplicationCommandInteraction,\n ApplicationCommandType\n} from 'discord-api-types/v10';\nimport type { Promisable } from 'type-fest';\n\ntype UserMenuArms<Names extends NamesFor<ApplicationCommandType.User>, Ret> = Record<\n Names,\n (target: APIUser, member: APIInteractionDataResolvedGuildMember | null) => Promisable<Ret>\n>;\n\ntype MessageMenuArms<Names extends NamesFor<ApplicationCommandType.Message>, Ret> = Record<\n Names,\n (target: APIMessage) => Promisable<Ret>\n>;\n\nfunction armFor<Ret>(handler: object, arms: object, name: string): (...args: never[]) => Promisable<Ret> {\n // hasOwn, since a plain lookup for a command named `constructor` returns Object.prototype's\n const arm = Object.hasOwn(arms, name) ? (arms as Record<string, unknown>)[name] : undefined;\n if (typeof arm !== 'function')\n throw new SeedcordTypeError(SeedcordErrorCode.MatchArmMissing, [\n handler.constructor.name,\n 'context menu command',\n name\n ]);\n return arm as (...args: never[]) => Promisable<Ret>;\n}\n\n/**\n * Base class for a user context-menu command handler on the HTTP transport (right-click a user).\n *\n * Pass the command name(s) as the generic, the same as `@UserContextMenuRoute`. Read the right-clicked user\n * from `this.target` and that same user's guild member from `this.targetMember`.\n *\n * @typeParam Names - One or more command names from the generated user registry.\n */\nexport abstract class UserContextMenuHandler<\n Names extends NamesFor<ApplicationCommandType.User>\n> extends InteractionHandler<APIUserApplicationCommandInteraction> {\n // phantom, nothing reads them. they keep the kind and the names on the instance type\n /** @internal */\n declare readonly [ContextMenuKindBrand]?: ApplicationCommandType.User;\n /** @internal */\n declare readonly [ContextMenuNamesBrand]?: Names;\n\n protected get target(): APIUser {\n const { target_id: targetId, resolved } = this.event.data;\n // justified: discord resolves the target it delivered target_id for\n return resolved.users[targetId] as APIUser;\n }\n\n /** The right-clicked user's guild member, null outside a guild. */\n protected get targetMember(): APIInteractionDataResolvedGuildMember | null {\n const { target_id: targetId, resolved } = this.event.data;\n return resolved.members?.[targetId] ?? null;\n }\n\n /** Which of the registered commands fired. */\n protected get commandName(): Names {\n return this.event.data.name as Names;\n }\n\n /**\n * Run the arm for whichever command fired. Use this only when the handler is registered for several\n * names.\n *\n * Provide one arm per registered name, keyed by the name Discord shows in the right-click menu. Each\n * arm receives the clicked user and that user's guild member. The arms must cover every name in the\n * generic. A missing name or an unknown key is a compile error.\n *\n * @param arms - One handler per registered command name.\n * @returns The result of the arm that ran.\n *\n * @example\n * ```ts\n * \\@UserContextMenuRoute('View Profile', 'Warn')\n * class Moderation extends UserContextMenuHandler<'View Profile' | 'Warn'> {\n * async execute() {\n * await this.match({\n * 'View Profile': (user) => this.reply(`Profile for ${user.username}.`),\n * Warn: (user, member) => this.reply(`Warned ${member?.nick ?? user.username}.`)\n * });\n * }\n * }\n * ```\n */\n protected async match<Ret>(arms: UserMenuArms<Names, Ret>): Promise<Ret> {\n const arm = armFor<Ret>(this, arms, this.event.data.name);\n return await (\n arm as (target: APIUser, member: APIInteractionDataResolvedGuildMember | null) => Promisable<Ret>\n )(this.target, this.targetMember);\n }\n}\n\n/**\n * Base class for a message context-menu command handler on the HTTP transport (right-click a message).\n *\n * Pass the command name(s) as the generic, the same as `@MessageContextMenuRoute`. Read the right-clicked\n * message from `this.target`.\n *\n * @typeParam Names - One or more command names from the generated message registry.\n */\nexport abstract class MessageContextMenuHandler<\n Names extends NamesFor<ApplicationCommandType.Message>\n> extends InteractionHandler<APIMessageApplicationCommandInteraction> {\n /** @internal */\n declare readonly [ContextMenuKindBrand]?: ApplicationCommandType.Message;\n /** @internal */\n declare readonly [ContextMenuNamesBrand]?: Names;\n\n protected get target(): APIMessage {\n const { target_id: targetId, resolved } = this.event.data;\n // justified: discord resolves the target it delivered target_id for\n return resolved.messages[targetId] as APIMessage;\n }\n\n /** Which of the registered commands fired. */\n protected get commandName(): Names {\n return this.event.data.name as Names;\n }\n\n /**\n * Run the arm for whichever command fired. Use this only when the handler is registered for several\n * names.\n *\n * Provide one arm per registered name, keyed by the name Discord shows in the right-click menu. Each\n * arm receives the clicked message. The arms must cover every name in the generic. A missing name or\n * an unknown key is a compile error.\n *\n * @param arms - One handler per registered command name.\n * @returns The result of the arm that ran.\n *\n * @example\n * ```ts\n * \\@MessageContextMenuRoute('Report Message', 'Quote Message')\n * class MessageTools extends MessageContextMenuHandler<'Report Message' | 'Quote Message'> {\n * async execute() {\n * await this.match({\n * 'Report Message': (message) => this.report(message),\n * 'Quote Message': (message) => this.reply(`> ${message.content}`)\n * });\n * }\n * }\n * ```\n */\n protected async match<Ret>(arms: MessageMenuArms<Names, Ret>): Promise<Ret> {\n const arm = armFor<Ret>(this, arms, this.event.data.name);\n return await (arm as (target: APIMessage) => Promisable<Ret>)(this.target);\n }\n}\n","import { BaseHandler } from '@seedcord/core';\nimport { AutocompleteRouteBrand, reportedWrite } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError, SeedcordTypeError } from '@seedcord/errors/internal';\nimport { InteractionResponseType, Routes } from 'discord-api-types/v10';\n\nimport { HttpSlashOptions } from '#inputs/HttpSlashOptions';\nimport { apiFor } from '#src/api';\nimport { slashRouteOf } from '#src/dispatch/slashRouteOf';\n\nimport type { Core } from '#interfaces/Core';\nimport type { API } from '@discordjs/core/http-only';\nimport type { AutocompleteOptions, DispatchContext, SlashRegistry } from '@seedcord/core';\nimport type { AutocompletableNames, ChoiceValueOf, EntryFor, FocusedField } from '@seedcord/core/internal';\nimport type {\n APIApplicationCommandOptionChoice,\n APIApplicationCommandAutocompleteInteraction\n} from 'discord-api-types/v10';\nimport type { Promisable } from 'type-fest';\n\ntype FocusedArms<Route extends keyof SlashRegistry, Ret> = {\n [Name in AutocompletableNames<Route>]: (\n value: string,\n respond: (\n choices: readonly APIApplicationCommandOptionChoice<ChoiceValueOf<EntryFor<Route, Name>>>[]\n ) => Promise<void>\n ) => Promisable<Ret>;\n};\n\n/**\n * Base class for an autocomplete handler on the HTTP transport.\n *\n * Pass the command route(s) from the generated registry as the generic. Branch on the focused field with\n * `this.match`, read already-entered sibling options with `this.options`, and find which command fired\n * with `this.route`.\n *\n * @typeParam Route - One or more route keys from {@link SlashRegistry}, e.g. `'search'`.\n */\nexport abstract class AutocompleteHandler<Route extends keyof SlashRegistry> extends BaseHandler<\n APIApplicationCommandAutocompleteInteraction,\n Core\n> {\n // keep this ctor. inheriting BaseHandler's protected one collapses the handler ctor type to never.\n constructor(event: APIApplicationCommandAutocompleteInteraction, core: Core, dispatch: DispatchContext) {\n super(event, core, dispatch, 'interactions');\n }\n\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [AutocompleteRouteBrand]?: Route;\n\n /**\n * Typed Discord REST API (`@discordjs/core/http-only`) over `core.rest`, one instance per core.\n */\n protected get api(): API {\n return apiFor(this.core.rest);\n }\n\n private resolver?: HttpSlashOptions;\n\n private get reader(): HttpSlashOptions {\n this.resolver ??= new HttpSlashOptions(this.event.data);\n return this.resolver;\n }\n\n /**\n * The focused option for this interaction. `value` is always the raw partial string the user is typing,\n * even for an integer or number option, so coerce it yourself when you need a number.\n */\n protected get focused(): FocusedField<Route> {\n const focused = this.reader.getFocused();\n if (!focused) throw new SeedcordError(SeedcordErrorCode.AutocompleteNoFocusedOption);\n // the registry constrains the names\n return focused as FocusedField<Route>;\n }\n\n /**\n * Run the arm for the focused field. An autocomplete always dispatches by which field is focused.\n * Match is how you read it.\n *\n * Provide one arm per autocompletable field across the registered commands, keyed by field name. Each\n * arm receives the focused partial value and a `respond` typed to that field's choice value. The\n * arms must cover every autocompletable field. A missing field or an unknown key is a compile error.\n *\n * @param arms - One handler per autocompletable field, keyed by field name.\n * @returns The result of the arm that ran.\n * @throws A **SeedcordTypeError** with `MatchArmMissing` when the focused field has no arm. Only a stale-deployed command can send one.\n */\n protected async match<Ret>(arms: FocusedArms<Route, Ret>): Promise<Ret> {\n const { name, value } = this.focused;\n const respond = (choices: readonly APIApplicationCommandOptionChoice[]): Promise<void> => this.respond(choices);\n // justified: FocusedArms is keyed by field literals, the Record cast indexes it with the runtime field name.\n type Arm = (\n value: string,\n respond: (choices: readonly APIApplicationCommandOptionChoice[]) => Promise<void>\n ) => Promisable<Ret>;\n const arm = Object.hasOwn(arms, name) ? (arms as Record<string, Arm>)[name] : undefined;\n if (!arm)\n throw new SeedcordTypeError(SeedcordErrorCode.MatchArmMissing, [\n this.constructor.name,\n 'focused field',\n name\n ]);\n return await arm(value, respond);\n }\n\n /** Send autocomplete suggestions, callback type 8. Prefer {@link match}, which restricts each field's choices to its declared type. */\n protected async respond(choices: readonly APIApplicationCommandOptionChoice[]): Promise<void> {\n await reportedWrite(\n { bus: this.core.bus, dispatch: this.dispatch, interactionId: this.event.id },\n 'respond',\n () =>\n this.core.rest.post(Routes.interactionCallback(this.event.id, this.event.token), {\n body: { type: InteractionResponseType.ApplicationCommandAutocompleteResult, data: { choices } }\n })\n );\n }\n\n /** The firing command route, for a field whose completion differs per registered command. */\n protected get route(): Route {\n return slashRouteOf(this.event.data) as Route;\n }\n\n /**\n * The already-entered options on this command, restricted to the kinds Discord resolves during autocomplete\n * (string, integer, number, boolean) with every read nullable, since a sibling is partial while the user\n * types the focused field. The focused field is on `this.focused`.\n */\n protected get options(): AutocompleteOptions<Route> {\n // AutocompleteOptions is the registry-typed view over the getters the reader exposes\n return this.reader as AutocompleteOptions<Route>;\n }\n}\n","import { ComponentDefsBrand, decodeComponentRoute } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordTypeError } from '@seedcord/errors/internal';\n\nimport { InteractionHandler } from '#handlers/interaction/InteractionHandler';\n\nimport type { SentMessage } from '#reply/ReplySender';\nimport type { DecodedComponentRoute, HasComponentDefs, MatchArms, SingleParams } from '@seedcord/core/internal';\nimport type { AnyCustomId } from '@seedcord/custom-id';\nimport type { ReplyResponse } from '@seedcord/types';\nimport type { APIMessageComponentInteraction, APIModalSubmitInteraction } from 'discord-api-types/v10';\nimport type { Promisable } from 'type-fest';\n\n/**\n * Shared base the customId-routed component handlers extend on the HTTP transport.\n *\n * Not a public entry point. Extend {@link ButtonHandler}, {@link ModalHandler}, or one of the select menu\n * bases instead. This class defines the customId decode, the route matching, and the source-message\n * verbs `update` and `deferUpdate`.\n *\n * @typeParam Event - The component or modal interaction type this handler processes\n * @typeParam Defs - The customId route definitions registered on the concrete handler\n */\nexport abstract class ComponentHandler<\n Event extends APIMessageComponentInteraction | APIModalSubmitInteraction,\n Defs extends readonly AnyCustomId[]\n>\n extends InteractionHandler<Event>\n implements HasComponentDefs<Defs>\n{\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [ComponentDefsBrand]?: Defs;\n\n /** Rewrite the source message this component interaction came from. */\n protected update(response: ReplyResponse | string): Promise<SentMessage> {\n return this.sender.update(response);\n }\n\n /** Acknowledge the component without changing the source message. */\n protected deferUpdate(): Promise<void> {\n return this.sender.deferUpdate();\n }\n\n private decoded?: DecodedComponentRoute;\n\n private get route(): DecodedComponentRoute {\n this.decoded ??= decodeComponentRoute(this.constructor, this.event.data.custom_id);\n return this.decoded;\n }\n\n /**\n * The decoded params of the single route this handler is registered for.\n *\n * Reading this decodes `this.event.data.custom_id` once and caches the result. On a handler\n * registered for several routes this is `never`. Use {@link match} instead.\n *\n * @throws A **StaleCustomId** when the wire was encoded under an older shape. The dispatcher boundary turns it into a reply.\n * @throws An **InvalidCustomId** when the wire is corrupt. The dispatcher boundary turns it into a reply.\n */\n protected get params(): SingleParams<Defs> {\n return this.route.params as SingleParams<Defs>;\n }\n\n /**\n * Run the arm for whichever route the component was minted from. Use this only when the handler is\n * registered for several routes. A single-route handler reads `this.params` directly. On a multi-route\n * handler `this.params` is `never`, so match is the only way to read the decoded params.\n *\n * Provide one arm per registered route, keyed by its prefix, and each arm receives that route's own\n * decoded params. The compiler checks that the arms cover every registered route prefix. `match`\n * decodes the wire before it runs an arm.\n *\n * @param arms - One callback per registered route, keyed by prefix.\n * @returns The result of the arm that ran.\n * @throws A **SeedcordTypeError** with `MatchArmMissing` when the wire's prefix has no arm.\n * @throws A **StaleCustomId** when the wire was encoded under an older shape.\n * @throws An **InvalidCustomId** when the wire is corrupt.\n *\n * @example\n * ```ts\n * \\@ButtonRoute(Approve, Reject)\n * class ReviewButtons extends ButtonHandler<[typeof Approve, typeof Reject]> {\n * async execute() {\n * await this.match({\n * approve: ({ userId }) => this.reply(`approved <@${userId}>`),\n * reject: ({ userId }) => this.reply(`rejected <@${userId}>`)\n * });\n * }\n * }\n * ```\n */\n protected async match<Ret>(arms: MatchArms<Defs, Ret>): Promise<Ret> {\n const { prefix, params } = this.route;\n // justified: MatchArms is keyed by prefix literals, the Record cast indexes it with the runtime prefix.\n const arm = Object.hasOwn(arms, prefix)\n ? (arms as Record<string, (params: Record<string, unknown>) => Promisable<Ret>>)[prefix]\n : undefined;\n if (!arm)\n throw new SeedcordTypeError(SeedcordErrorCode.MatchArmMissing, [\n this.constructor.name,\n 'component route',\n prefix\n ]);\n return await arm(params);\n }\n}\n","import { ComponentKindBrand } from '@seedcord/core/internal';\n\nimport { ComponentHandler } from './ComponentHandler';\n\nimport type { InteractionKind } from '@seedcord/core';\nimport type { AnyCustomId } from '@seedcord/custom-id';\nimport type { APIMessageComponentButtonInteraction } from 'discord-api-types/v10';\n\n/**\n * Base class for a button interaction handler on the HTTP transport.\n *\n * Register the customId definitions this handler decodes with `@ButtonRoute`, list the same ones in the\n * generic, then read `this.params` for a single route or `this.match` for several. Reply through the\n * handler members, or rewrite the source message with `this.update`. Passing different definitions to the\n * decorator and the generic is a compile error.\n *\n * @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof ApproveId]`.\n */\nexport abstract class ButtonHandler<Defs extends readonly AnyCustomId[]> extends ComponentHandler<\n APIMessageComponentButtonInteraction,\n Defs\n> {\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [ComponentKindBrand]?: InteractionKind.Button;\n}\n","import { ComponentKindBrand } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\n\nimport { ModalFields } from '#inputs/ModalFields';\n\nimport { ComponentHandler } from './ComponentHandler';\n\nimport type { SentMessage } from '#reply/ReplySender';\nimport type { InteractionKind } from '@seedcord/core';\nimport type { AnyCustomId } from '@seedcord/custom-id';\nimport type { ReplyResponse } from '@seedcord/types';\nimport type { APIModalSubmitInteraction } from 'discord-api-types/v10';\n\n/**\n * Base class for a modal submit handler on the HTTP transport.\n *\n * Register the customId definitions this handler decodes with `@ModalRoute` and list the same ones in the\n * generic. Read the submitted inputs from `this.fields`. Reply through the handler members. `showModal`\n * fails compilation on this kind, because Discord forbids opening a modal in response to a modal.\n *\n * @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof ConfigId]`.\n *\n * @example\n * ```ts\n * \\@ModalRoute(ConfigId)\n * class ConfigModal extends ModalHandler<[typeof ConfigId]> {\n * async execute() {\n * const { guildId } = this.params;\n * const name = this.fields.getTextInputValue('name');\n * await this.reply(`saved ${name} for ${guildId}`);\n * }\n * }\n * ```\n */\nexport abstract class ModalHandler<Defs extends readonly AnyCustomId[]> extends ComponentHandler<\n APIModalSubmitInteraction,\n Defs\n> {\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [ComponentKindBrand]?: InteractionKind.Modal;\n\n private reader?: ModalFields;\n\n /** The fields this modal submitted, read by custom id. */\n protected get fields(): ModalFields {\n this.reader ??= new ModalFields(this.event.data);\n return this.reader;\n }\n\n /** Rewrite the message this modal was opened from. Throws when a command opened the modal. */\n protected override update(response: ReplyResponse | string): Promise<SentMessage> {\n this.ensureSourceMessage('update');\n return super.update(response);\n }\n\n /** Acknowledge the submit without changing the source message. Throws when a command opened the modal. */\n protected override deferUpdate(): Promise<void> {\n this.ensureSourceMessage('deferUpdate');\n return super.deferUpdate();\n }\n\n // discord omits the message when a command opened the modal\n private ensureSourceMessage(method: string): void {\n if (this.event.message) return;\n throw new SeedcordError(SeedcordErrorCode.ReplyUpdateWithoutSource, [method, this.routeId]);\n }\n}\n","import { ComponentKindBrand } from '@seedcord/core/internal';\n\nimport { pick } from '#inputs/pick';\n\nimport { ComponentHandler } from './ComponentHandler';\n\nimport type { Collection } from '@discordjs/collection';\nimport type { InteractionKind } from '@seedcord/core';\nimport type { AnyCustomId } from '@seedcord/custom-id';\nimport type {\n APIInteractionDataResolvedChannel,\n APIInteractionDataResolvedGuildMember,\n APIMessageChannelSelectInteractionData,\n APIMessageComponentSelectMenuInteraction,\n APIMessageMentionableSelectInteractionData,\n APIMessageRoleSelectInteractionData,\n APIMessageStringSelectInteractionData,\n APIMessageUserSelectInteractionData,\n APIRole,\n APIUser\n} from 'discord-api-types/v10';\n\n/** @internal */\nexport type SelectInteraction<Data> = APIMessageComponentSelectMenuInteraction & { data: Data };\n\n// discord-api-types marks resolved required. a menu that resolved nothing arrives without the key.\nfunction resolvedOf<Data extends { resolved: object }>(data: Data): Partial<Data['resolved']> {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- the declared type overstates the wire\n return data.resolved ?? {};\n}\n\n/**\n * Shared base the select menu handlers extend on the HTTP transport.\n *\n * Not a public entry point. Extend {@link StringMenuHandler}, {@link UserMenuHandler},\n * {@link RoleMenuHandler}, {@link ChannelMenuHandler}, or {@link MentionableMenuHandler} instead. This\n * class defines the `values` getter those bases share.\n *\n * @typeParam Event - The select menu interaction type this handler processes\n * @typeParam Defs - The customId route definitions registered on the concrete handler\n */\nexport abstract class SelectMenuHandler<\n Event extends APIMessageComponentSelectMenuInteraction,\n Defs extends readonly AnyCustomId[]\n> extends ComponentHandler<Event, Defs> {\n /** The values this select picked. On every kind but the string menu they are snowflake ids. */\n protected get values(): string[] {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- a payload can arrive with no values key\n return this.event.data.values ?? [];\n }\n}\n\n/**\n * Base class for a string select menu handler on the HTTP transport.\n *\n * Register the customId definitions with `@StringMenuRoute`, list the same ones in the generic, then read\n * the chosen option values from `this.values`. Read `this.params` for a single route or `this.match` for\n * several. Reply through the handler members, or rewrite the source message with `this.update`.\n *\n * @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof TopicsId]`.\n *\n * @example\n * ```ts\n * \\@StringMenuRoute(TopicsId)\n * class Topics extends StringMenuHandler<[typeof TopicsId]> {\n * async execute() {\n * const { userId } = this.params;\n * await this.update(`<@${userId}> now follows ${this.values.join(', ')}`);\n * }\n * }\n * ```\n */\nexport abstract class StringMenuHandler<Defs extends readonly AnyCustomId[]> extends SelectMenuHandler<\n SelectInteraction<APIMessageStringSelectInteractionData>,\n Defs\n> {\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [ComponentKindBrand]?: InteractionKind.StringMenu;\n}\n\n/**\n * Base class for a user select menu handler on the HTTP transport.\n *\n * Beside `this.values` this handler declares `this.users` and `this.members`. Register the customId\n * definitions with `@UserMenuRoute` and list the same ones in the generic.\n *\n * @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof AssignId]`.\n *\n * @example\n * ```ts\n * \\@UserMenuRoute(AssignId)\n * class Assign extends UserMenuHandler<[typeof AssignId]> {\n * async execute() {\n * const { roleId } = this.params;\n * await this.reply(`assigning ${this.users.size} member(s) to <@&${roleId}>`);\n * }\n * }\n * ```\n */\nexport abstract class UserMenuHandler<Defs extends readonly AnyCustomId[]> extends SelectMenuHandler<\n SelectInteraction<APIMessageUserSelectInteractionData>,\n Defs\n> {\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [ComponentKindBrand]?: InteractionKind.UserMenu;\n\n /** The users this select picked. */\n protected get users(): Collection<string, APIUser> {\n return pick(this.values, resolvedOf(this.event.data).users);\n }\n\n /** The guild members behind the picked users. Discord resolves these only inside a guild. */\n protected get members(): Collection<string, APIInteractionDataResolvedGuildMember> {\n return pick(this.values, resolvedOf(this.event.data).members);\n }\n}\n\n/**\n * Base class for a role select menu handler on the HTTP transport.\n *\n * Beside `this.values` this handler declares `this.roles`. Register the customId definitions with\n * `@RoleMenuRoute` and list the same ones in the generic.\n *\n * @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof GrantId]`.\n *\n * @example\n * ```ts\n * \\@RoleMenuRoute(GrantId)\n * class Grant extends RoleMenuHandler<[typeof GrantId]> {\n * async execute() {\n * await this.update(`granting ${this.roles.size} role(s)`);\n * }\n * }\n * ```\n */\nexport abstract class RoleMenuHandler<Defs extends readonly AnyCustomId[]> extends SelectMenuHandler<\n SelectInteraction<APIMessageRoleSelectInteractionData>,\n Defs\n> {\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [ComponentKindBrand]?: InteractionKind.RoleMenu;\n\n /** The roles this select picked. */\n protected get roles(): Collection<string, APIRole> {\n return pick(this.values, resolvedOf(this.event.data).roles);\n }\n}\n\n/**\n * Base class for a channel select menu handler on the HTTP transport.\n *\n * Beside `this.values` this handler declares `this.channels`. Register the customId definitions with\n * `@ChannelMenuRoute` and list the same ones in the generic.\n *\n * @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof LogTargetId]`.\n *\n * @example\n * ```ts\n * \\@ChannelMenuRoute(LogTargetId)\n * class LogTarget extends ChannelMenuHandler<[typeof LogTargetId]> {\n * async execute() {\n * await this.update(`logging to ${this.channels.size} channel(s)`);\n * }\n * }\n * ```\n */\nexport abstract class ChannelMenuHandler<Defs extends readonly AnyCustomId[]> extends SelectMenuHandler<\n SelectInteraction<APIMessageChannelSelectInteractionData>,\n Defs\n> {\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [ComponentKindBrand]?: InteractionKind.ChannelMenu;\n\n /** The channels this select picked. */\n protected get channels(): Collection<string, APIInteractionDataResolvedChannel> {\n return pick(this.values, resolvedOf(this.event.data).channels);\n }\n}\n\n/**\n * Base class for a mentionable select menu handler on the HTTP transport.\n *\n * A mentionable menu accepts users and roles together. `this.users`, `this.members`, and `this.roles`\n * can each come back empty.\n *\n * @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof InviteId]`.\n *\n * @example\n * ```ts\n * \\@MentionableMenuRoute(InviteId)\n * class Invite extends MentionableMenuHandler<[typeof InviteId]> {\n * async execute() {\n * await this.update(`inviting ${this.users.size} user(s) and ${this.roles.size} role(s)`);\n * }\n * }\n * ```\n */\nexport abstract class MentionableMenuHandler<Defs extends readonly AnyCustomId[]> extends SelectMenuHandler<\n SelectInteraction<APIMessageMentionableSelectInteractionData>,\n Defs\n> {\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [ComponentKindBrand]?: InteractionKind.MentionableMenu;\n\n /** The users this select picked. */\n protected get users(): Collection<string, APIUser> {\n return pick(this.values, resolvedOf(this.event.data).users);\n }\n\n /** The guild members behind the picked users. Discord resolves these only inside a guild. */\n protected get members(): Collection<string, APIInteractionDataResolvedGuildMember> {\n return pick(this.values, resolvedOf(this.event.data).members);\n }\n\n /** The roles this select picked. */\n protected get roles(): Collection<string, APIRole> {\n return pick(this.values, resolvedOf(this.event.data).roles);\n }\n}\n","import { Subscriber as CoreSubscriber, WebhookLog as CoreWebhookLog } from '@seedcord/core';\n\nimport type { Core } from '#interfaces/Core';\nimport type { SubscriptionKey } from '@seedcord/core';\n\n/**\n * Base class for an HTTP subscriber, binding `this.core` to the HTTP {@link Core}.\n *\n * @typeParam KeyOfSubscribers - The subscription key this handler receives\n */\nexport abstract class Subscriber<KeyOfSubscribers extends SubscriptionKey> extends CoreSubscriber<\n KeyOfSubscribers,\n Core\n> {}\n\n/**\n * Base class for an HTTP subscriber that delivers its event to a Discord webhook, binding\n * `this.core` to the HTTP {@link Core}.\n *\n * @typeParam KeyOfSubscribers - The subscription key this reporter receives\n */\nexport abstract class WebhookLog<KeyOfSubscribers extends SubscriptionKey> extends CoreWebhookLog<\n KeyOfSubscribers,\n Core\n> {}\n","import { PaginatorBase } from '@seedcord/core';\n\nimport { ButtonHandler } from '#handlers/interaction/components';\n\nimport type { RepliableHandler } from '#handlers/RepliableHandler';\nimport type { Core } from '#interfaces/Core';\nimport type { SentMessage } from '#reply/ReplySender';\nimport type { Repliables } from '#src/handlers/interactionTypes';\nimport type { PageContext } from './PageContext';\nimport type { PaginatorConfig } from '@seedcord/core';\nimport type { PageCursor } from '@seedcord/core/internal';\nimport type { ReplyResponse } from '@seedcord/types';\nimport type { APIUser } from 'discord-api-types/v10';\n\n// `& { execute }` makes execute concrete. an empty `extends Bans.Handler {}` hits TS2515 without it.\ntype PaginatorHandlerCtor<Prefix extends string> = new (\n ...args: ConstructorParameters<typeof ButtonHandler>\n) => ButtonHandler<[PageCursor<Prefix>]> & { execute(): Promise<void> };\n\nfunction contextOf(interaction: Repliables, core: Core): PageContext {\n // discord sends member.user in a guild and the top-level user in a dm\n const resolved = interaction.member?.user ?? interaction.user;\n return {\n interaction,\n // justified: every repliable interaction Discord delivers carries a user, and the wrapper types don't say so\n user: resolved as APIUser,\n guildId: interaction.guild_id ?? null,\n core\n };\n}\n\n/**\n * A restart-proof paginator. Each nav button's customId encodes its full target page, so clicks are\n * idempotent and survive a restart. A persistent `@ButtonRoute` on `Handler` dispatches the clicks.\n *\n * @typeParam Item - The item type, inferred from the source.\n * @typeParam Prefix - The route prefix, inferred from `config.prefix`.\n *\n * @example\n * ```ts\n * export const Bans = new Paginator({\n * prefix: 'bans',\n * source: new ArraySource((ctx) => loadBans(ctx.guildId), { perPage: 10 }),\n * renderItem: (ban) => ban.user.username\n * });\n *\n * \\@ButtonRoute(Bans.cursor)\n * export class BansNav extends Bans.Handler {}\n * ```\n */\nexport class Paginator<Item, const Prefix extends string> extends PaginatorBase<Item, Prefix, PageContext> {\n /** The nav handler base. Extend it with an empty body and decorate it, `@ButtonRoute(p.cursor)`. */\n public readonly Handler: PaginatorHandlerCtor<Prefix>;\n\n constructor(config: PaginatorConfig<Item, Prefix, PageContext>) {\n super(config);\n\n // an arrow captures the paginator lexically so Nav.execute can reach it without aliasing `this`.\n const pageFor = (handler: RepliableHandler<Repliables>, n: number): Promise<ReplyResponse> =>\n this.page(handler, n);\n this.Handler = class Nav extends ButtonHandler<[PageCursor<Prefix>]> {\n async execute(): Promise<void> {\n await this.deferUpdate();\n const response = await pageFor(this, this.params.page);\n // deferUpdate seeds the sender deferred-update, so update PATCHes @original\n await this.update(response);\n }\n };\n }\n\n /**\n * Render a page as a {@link ReplyResponse} without sending anything.\n *\n * @param handler - The handler rendering the page, normally `this`.\n * @param n - The zero-based page.\n */\n async page(handler: RepliableHandler<Repliables>, n: number): Promise<ReplyResponse> {\n return this.buildPage(contextOf(handler.getEvent(), handler.core), n);\n }\n\n /**\n * Send a page through the handler's sender. The sender picks reply, edit, or followUp from its ack state.\n *\n * @param handler - The handler starting the paginator, normally `this`.\n * @param n - The zero-based page to open on.\n */\n async start(handler: RepliableHandler<Repliables>, n = 0): Promise<SentMessage> {\n const response = await this.page(handler, n);\n return handler.sender.send(response, { ephemeral: this.config.ephemeral ?? false });\n }\n}\n","import { ArraySourceBase, CursorSourceBase } from '@seedcord/core';\n\nimport type { PageContext } from './PageContext';\nimport type { PageSourceBase } from '@seedcord/core';\n\n/**\n * The one method a paginator calls on a source, once per click. Implement it for a source neither shipped\n * one covers.\n *\n * @typeParam Item - The item type the source pages over.\n */\nexport type PageSource<Item> = PageSourceBase<Item, PageContext>;\n\n/**\n * A source for a bounded list you can load whole. It loads the full list on every click, then slices the\n * page, so the real total is known (a real last button, \"Page X of Y\"). Cache inside your loader if the\n * load is expensive.\n *\n * @typeParam Item - The item type, inferred from the loader's return.\n */\nexport class ArraySource<Item> extends ArraySourceBase<Item, PageContext> {}\n\n/**\n * A source for a large or unknown-length set you fetch one page at a time (SQL LIMIT/OFFSET, a paged API).\n * The fetcher receives the page index and the page size and reports whether a next page exists. A cursor\n * source has no cheap total, so `totalPages` is undefined, the last button is omitted, and the indicator\n * reads \"Page X\".\n *\n * @typeParam Item - The item type, inferred from the fetcher's slice.\n */\nexport class CursorSource<Item> extends CursorSourceBase<Item, PageContext> {}\n","import { GatedMetadataKey } from '@seedcord/core/internal';\n\nimport type { AnyHandlerCtor, FitAll } from './matching';\nimport type { Gate, GateContextBase } from '@seedcord/core';\nimport type { NonEmptyTuple } from 'type-fest';\n\n/**\n * Attaches gates to an HTTP interaction handler. The gates run before `execute`, and a gate refusing stops\n * the handler with the reply or drop the gate threw. Multiple gates are ANDed. A gate\n * that requires a context the handler does not provide (a button gate on a slash handler, a gate on an\n * autocomplete handler, or a `RequirePermissions([...], { in: 'guild' })` gate the http transport cannot\n * satisfy) is a compile error at this line, and the error names the gate and the handler kind. Place it\n * above the route decorator.\n *\n * Combine gates with {@link and} or {@link or} to build a single gate from multiple arms.\n *\n * @example\n * ```ts\n * import { PermissionFlagsBits } from 'discord-api-types/v10';\n *\n * \\@Gated(GuildOnly(), RequirePermissions([PermissionFlagsBits.ManageMessages]))\n * \\@SlashRoute('purge')\n * class Purge extends SlashHandler<'purge'> {\n * async execute() {\n * // both gates passed, so this runs in a guild with a caller who can moderate this channel\n * }\n * }\n * ```\n *\n * @typeParam Gates - The non-empty tuple of gates to run, in order, against the handler's context.\n * @typeParam TCtor - The decorated handler's constructor, checked against every gate's required context.\n * @param gates - One or more gates to attach, each ANDed so the handler runs only when all pass.\n * @param ctor - The handler class being decorated, rejected at compile time when a gate requires a context it lacks.\n *\n * @see {@link defineGate}\n * @see {@link defineEffectGate}\n * @decorator\n */\nexport function Gated<const Gates extends NonEmptyTuple<Gate<GateContextBase>>>(...gates: Gates) {\n // the class fails to assign and TS names the gate\n return function <TCtor extends AnyHandlerCtor>(\n ctor: FitAll<TCtor, Gates> extends Gates ? TCtor : FitAll<TCtor, Gates>\n ): void {\n const existing = (Reflect.getMetadata(GatedMetadataKey, ctor) as readonly Gate[] | undefined) ?? [];\n Reflect.defineMetadata(GatedMetadataKey, [...existing, ...gates], ctor);\n };\n}\n","export const version = process.env.PACKAGE_VERSION ?? '0.0.0';\n","import { currentApplication } from '@seedcord/core/internal';\nimport { SeedcordErrorCode, paint } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { asError } from '@seedcord/utils/internal';\nimport { Envapter } from 'envapt';\n\nimport type { REST } from '@discordjs/rest';\n\nexport async function publicKeyOf(rest: Pick<REST, 'get'>): Promise<string> {\n const fromEnv = Envapter.get('DISCORD_PUBLIC_KEY');\n if (fromEnv !== undefined) return fromEnv;\n\n try {\n const application = await currentApplication(rest);\n return application.verify_key;\n } catch (error) {\n throw new SeedcordError(\n SeedcordErrorCode.CoreDiscordReadFailed,\n [\n 'the public key',\n asError(error).message,\n `The bot reads it there because ${paint.bold('DISCORD_PUBLIC_KEY')} is unset. Check ${paint.bold('DISCORD_BOT_TOKEN')}, or set ${paint.bold('DISCORD_PUBLIC_KEY')} to the key from your application's General Information page.`\n ],\n { cause: error }\n );\n }\n}\n","import { StartupPhase } from '@seedcord/core';\nimport { attachmentsOf, COMMAND_DEPLOY_TIMEOUT_MS, CommandRegistry } from '@seedcord/core/internal';\n\nimport { EmojiInjector } from '#src/emojis/EmojiInjector';\nimport { publicKeyOf } from '#src/publicKey';\n\nimport type { Core } from '#interfaces/Core';\nimport type { InteractionsService } from '#src/InteractionsService';\nimport type { HmrManager } from '@seedcord/core/internal';\n\ntype Host = Core & Parameters<typeof attachmentsOf>[0];\n\n// the startup tasks the node bot and the edge bot under seedcord dev share\nexport class HttpStartupTasks {\n private readonly commands: CommandRegistry | undefined;\n private readonly emojis: EmojiInjector;\n\n public constructor(\n private readonly host: Host,\n private readonly service: InteractionsService\n ) {\n this.commands = host.config.bot.commands.path ? new CommandRegistry(host) : undefined;\n this.emojis = new EmojiInjector(host);\n }\n\n // a Configuration task because plugins attach after the constructor runs\n public registerHmr(hmr: HmrManager): void {\n this.host.startup.addTask(StartupPhase.Configuration, 'hmr-registration', () => {\n if (this.service.interactions) hmr.register(this.service.interactions);\n if (this.commands) hmr.register(this.commands);\n hmr.register(this.service.subscribers);\n for (const { instance } of attachmentsOf(this.host)) hmr.register(instance);\n return Promise.resolve();\n });\n }\n\n // a deployed edge worker reads the key and ids seedcord build baked\n public addDiscordTasks(): void {\n const { startup } = this.host;\n startup.addTask(StartupPhase.Login, 'interactions-engine', async () => {\n this.service.prepareEngine(await publicKeyOf(this.service.rest));\n });\n\n const { commands } = this;\n if (!commands) {\n startup.addTask(StartupPhase.Login, 'emoji-injection', () => this.emojis.init());\n return;\n }\n startup.addTask(\n StartupPhase.Login,\n 'command-deploy',\n async (signal) => {\n await this.emojis.init();\n await commands.deploy(signal, { routes: this.service.interactions });\n },\n COMMAND_DEPLOY_TIMEOUT_MS\n );\n }\n}\n","import { AutocompleteHandler } from '#handlers/interaction/AutocompleteHandler';\n\n// dispatch falls back here when no manifest row matches\n// discord requires empty choices here, which clears the pending autocomplete state\nexport class UnhandledAutocomplete extends AutocompleteHandler<never> {\n async execute(): Promise<void> {\n await this.respond([]);\n }\n}\n","import { InteractionHandler } from '#handlers/interaction/InteractionHandler';\n\nimport type { Repliables } from '#handlers/interactionTypes';\n\n// dispatch falls back here when no manifest row matches\n// a reply failure here reaches the dispatch fault boundary directly\nexport class UnhandledRepliable extends InteractionHandler<Repliables> {\n async execute(): Promise<void> {\n await this.reply('Feature not implemented yet.');\n }\n}\n","import { InteractionKind } from '@seedcord/core';\nimport { prefixOf } from '@seedcord/custom-id';\nimport { ApplicationCommandType, ComponentType, InteractionType } from 'discord-api-types/v10';\n\nimport { UnhandledAutocomplete } from '#handlers/defaults/UnhandledAutocomplete';\nimport { UnhandledRepliable } from '#handlers/defaults/UnhandledRepliable';\n\nimport { slashRouteOf } from './slashRouteOf';\n\nimport type { HandlerConstructor } from '#handlers/constructors';\nimport type { APIInteraction } from 'discord-api-types/v10';\n\n/** A registered handler matched to an incoming interaction, under the keys the gateway dispatcher uses. */\nexport interface ResolvedRoute {\n readonly kind: InteractionKind;\n /** The stable dispatch id, `kind:key` (`slash:ban`). The unhandled default carries null. */\n readonly routeId: string | null;\n readonly attemptedKey?: string;\n readonly ctor: HandlerConstructor;\n}\n\n/** @internal */\nexport type RouteMap = Map<string, ResolvedRoute>;\n\ntype ComponentMapKey = Exclude<\n InteractionKind,\n | InteractionKind.Slash\n | InteractionKind.Autocomplete\n | InteractionKind.UserContextMenu\n | InteractionKind.MessageContextMenu\n>;\n\nexport type RouteMaps = Readonly<Record<InteractionKind, RouteMap>>;\n\nfunction commandKind(type: ApplicationCommandType): InteractionKind | null {\n switch (type) {\n case ApplicationCommandType.ChatInput: {\n return InteractionKind.Slash;\n }\n case ApplicationCommandType.User: {\n return InteractionKind.UserContextMenu;\n }\n case ApplicationCommandType.Message: {\n return InteractionKind.MessageContextMenu;\n }\n default: {\n return null;\n }\n }\n}\n\nfunction componentMapKey(type: ComponentType): Exclude<ComponentMapKey, InteractionKind.Modal> | null {\n switch (type) {\n case ComponentType.Button: {\n return InteractionKind.Button;\n }\n case ComponentType.StringSelect: {\n return InteractionKind.StringMenu;\n }\n case ComponentType.UserSelect: {\n return InteractionKind.UserMenu;\n }\n case ComponentType.RoleSelect: {\n return InteractionKind.RoleMenu;\n }\n case ComponentType.ChannelSelect: {\n return InteractionKind.ChannelMenu;\n }\n case ComponentType.MentionableSelect: {\n return InteractionKind.MentionableMenu;\n }\n default: {\n return null;\n }\n }\n}\n\nexport function emptyRouteMaps(): RouteMaps {\n return {\n [InteractionKind.Slash]: new Map(),\n [InteractionKind.UserContextMenu]: new Map(),\n [InteractionKind.MessageContextMenu]: new Map(),\n [InteractionKind.Autocomplete]: new Map(),\n [InteractionKind.Button]: new Map(),\n [InteractionKind.StringMenu]: new Map(),\n [InteractionKind.UserMenu]: new Map(),\n [InteractionKind.RoleMenu]: new Map(),\n [InteractionKind.ChannelMenu]: new Map(),\n [InteractionKind.MentionableMenu]: new Map(),\n [InteractionKind.Modal]: new Map()\n };\n}\n\nfunction unhandled(kind: InteractionKind, attemptedKey: string): ResolvedRoute {\n return {\n kind,\n routeId: null,\n attemptedKey,\n ctor: kind === InteractionKind.Autocomplete ? UnhandledAutocomplete : UnhandledRepliable\n };\n}\n\n/**\n * Matches a verified non-PING interaction to a registered handler. A known kind with no handler resolves\n * to the unhandled default. Null is an unrecognized payload shape, which the engine acks with a 202\n * without dispatching. Components and modals route by the stable customId prefix. A wire whose layout\n * hash drifted still reaches its handler, where decode refuses with `StaleCustomId`.\n */\nexport function resolve(maps: RouteMaps, interaction: APIInteraction): ResolvedRoute | null {\n switch (interaction.type) {\n case InteractionType.ApplicationCommand: {\n if (interaction.data.type === ApplicationCommandType.ChatInput) {\n const route = slashRouteOf(interaction.data);\n return maps[InteractionKind.Slash].get(route) ?? unhandled(InteractionKind.Slash, route);\n }\n const kind = commandKind(interaction.data.type);\n return kind ? (maps[kind].get(interaction.data.name) ?? unhandled(kind, interaction.data.name)) : null;\n }\n case InteractionType.ApplicationCommandAutocomplete: {\n const route = slashRouteOf(interaction.data);\n return maps[InteractionKind.Autocomplete].get(route) ?? unhandled(InteractionKind.Autocomplete, route);\n }\n case InteractionType.MessageComponent: {\n const key = componentMapKey(interaction.data.component_type);\n if (!key) return null;\n const prefix = prefixOf(interaction.data.custom_id);\n return maps[key].get(prefix) ?? unhandled(key, prefix);\n }\n case InteractionType.ModalSubmit: {\n const prefix = prefixOf(interaction.data.custom_id);\n return maps[InteractionKind.Modal].get(prefix) ?? unhandled(InteractionKind.Modal, prefix);\n }\n default: {\n return null;\n }\n }\n}\n","import { interactionRoutesOf } from '@seedcord/core/internal';\nimport { SeedcordErrorCode, paint } from '@seedcord/errors';\nimport { SeedcordTypeError } from '@seedcord/errors/internal';\n\nimport { emptyRouteMaps } from './resolve';\n\nimport type { HandlerConstructor } from '#handlers/constructors';\nimport type { RouteMaps } from './resolve';\nimport type { InteractionKind } from '@seedcord/core';\n\ninterface Owner {\n readonly ctor: HandlerConstructor;\n readonly kind: InteractionKind;\n readonly key: string;\n readonly from: string;\n}\n\nexport class RouteRegistry {\n public readonly maps: RouteMaps = emptyRouteMaps();\n\n private readonly owners = new Map<string, Owner>();\n\n public get size(): number {\n return this.owners.size;\n }\n\n /**\n * Writes every route the class declares. A class declaring none returns false.\n *\n * @throws A **SeedcordTypeError** when another class already holds one of them.\n */\n public register(ctor: HandlerConstructor, from: string): boolean {\n // nothing is written until every route clears the check below\n const writes: { kind: InteractionKind; key: string }[] = [];\n\n for (const [kind, keys] of interactionRoutesOf(ctor)) {\n for (const key of keys) {\n const existing = this.owners.get(`${kind}:${key}`);\n if (existing && existing.ctor !== ctor) {\n throw new SeedcordTypeError(SeedcordErrorCode.CoreDuplicateName, [\n 'route',\n `${kind}:${key}`,\n [\n `${paint.bold(existing.ctor.name)} (${paint.path(existing.from)})`,\n `${paint.bold(ctor.name)} (${paint.path(from)})`\n ]\n ]);\n }\n writes.push({ kind, key });\n }\n }\n\n if (writes.length === 0) return false;\n\n for (const { kind, key } of writes) {\n const routeId = `${kind}:${key}`;\n this.maps[kind].set(key, { kind, routeId, ctor });\n this.owners.set(routeId, { ctor, kind, key, from });\n }\n return true;\n }\n\n public unregister(ctor: HandlerConstructor, routeIds?: readonly string[]): void {\n for (const routeId of routeIds ?? this.routesOf(ctor)) {\n const owner = this.owners.get(routeId);\n if (owner?.ctor !== ctor) continue;\n this.owners.delete(routeId);\n this.maps[owner.kind].delete(owner.key);\n }\n }\n\n public routesOf(ctor: HandlerConstructor): string[] {\n const routeIds: string[] = [];\n for (const [routeId, owner] of this.owners) {\n if (owner.ctor === ctor) routeIds.push(routeId);\n }\n return routeIds;\n }\n}\n","import { InteractionKind } from '@seedcord/core';\nimport { HmrModuleHandler } from '@seedcord/core/hmr';\nimport {\n interactionMiddleware,\n InteractionMetadataKey,\n InteractionMiddlewareMetadataKey,\n MiddlewareRegistry\n} from '@seedcord/core/internal';\nimport { paint } from '@seedcord/errors';\nimport { Logger } from '@seedcord/logger';\nimport { formatFilePath, importFiles } from '@seedcord/utils';\nimport { Envapter } from 'envapt';\n\nimport { AutocompleteHandler } from '#handlers/interaction/AutocompleteHandler';\nimport { InteractionHandler } from '#handlers/interaction/InteractionHandler';\nimport { InteractionMiddleware } from '#handlers/interaction/InteractionMiddleware';\nimport { RouteRegistry } from '#src/dispatch/RouteRegistry';\n\nimport type { HandlerConstructor, InteractionMiddlewareConstructor } from '#handlers/constructors';\nimport type { RouteMap, RouteMaps } from '#src/dispatch/resolve';\nimport type { Initializeable, ContextMenuLeaves } from '@seedcord/core/internal';\nimport type { HmrAware, HmrUpdateEvent } from '@seedcord/types';\n\n// hmr swaps entries in these maps while resolve() reads them per request\nexport class InteractionDispatcher implements Initializeable, HmrAware {\n /** @internal */\n public readonly middlewares = new MiddlewareRegistry<InteractionMiddlewareConstructor>(interactionMiddleware);\n\n /** @internal */\n public readonly logger = new Logger('Interactions', { channel: 'interactions' });\n\n private readonly routes = new RouteRegistry();\n\n public get maps(): RouteMaps {\n return this.routes.maps;\n }\n\n private isInitialized = false;\n private readonly hmrHandler?: HmrModuleHandler<HandlerConstructor, InteractionMiddlewareConstructor, string[]>;\n\n private loading = false;\n private readonly loadedHandlers: { name: string; from: string }[] = [];\n private readonly loadedMiddlewares: { name: string; from: string }[] = [];\n\n constructor(\n private readonly handlersDir: string,\n private readonly middlewaresDir?: string\n ) {\n if (!Envapter.isDevelopment && !Envapter.isTest) return;\n\n this.hmrHandler = new HmrModuleHandler({\n handlersDir,\n ...(middlewaresDir && { middlewaresDir }),\n isHandler: this.isHandler.bind(this),\n isMiddleware: this.isMiddleware.bind(this),\n registerHandler: this.registerHandler.bind(this),\n registerMiddleware: this.registerMiddleware.bind(this),\n unregisterHandler: this.routes.unregister.bind(this.routes),\n unregisterMiddleware: this.unregisterMiddleware.bind(this),\n getArtifacts: this.routes.routesOf.bind(this.routes),\n logger: this.logger\n });\n }\n\n /** @internal */\n public async init(): Promise<void> {\n if (this.isInitialized) return;\n this.isInitialized = true;\n\n this.loading = true;\n this.loadedHandlers.length = 0;\n this.loadedMiddlewares.length = 0;\n try {\n if (this.middlewaresDir) await this.loadMiddlewares(this.middlewaresDir);\n await this.loadHandlers(this.handlersDir);\n } finally {\n this.loading = false;\n }\n\n this.reportLoad();\n }\n\n private async loadHandlers(dir: string): Promise<void> {\n for await (const { fullPath, relativePath, imported } of importFiles(dir)) {\n for (const value of Object.values(imported)) {\n if (!this.isHandler(value)) continue;\n this.registerHandler(value, relativePath);\n this.hmrHandler?.trackHandler(fullPath, value);\n }\n }\n }\n\n private async loadMiddlewares(dir: string): Promise<void> {\n for await (const { fullPath, relativePath, imported } of importFiles(dir)) {\n for (const value of Object.values(imported)) {\n if (!this.isMiddleware(value)) continue;\n this.registerMiddleware(value, relativePath);\n this.hmrHandler?.trackMiddleware(fullPath, value);\n }\n }\n }\n\n private reportLoad(): void {\n const { utils } = this.logger;\n\n if (this.loadedMiddlewares.length > 0) {\n utils.block('Loaded middlewares', utils.entries(this.loadedMiddlewares), 'debug');\n }\n\n utils.block(\n 'Loaded handlers',\n [...utils.entries(this.loadedHandlers), ...utils.counts({ routes: this.routes.size })],\n 'debug'\n );\n }\n\n /** @internal */\n public async onHmr(event: HmrUpdateEvent): Promise<void> {\n await this.hmrHandler?.handle(event);\n }\n\n public warnUnhandledRoutes(commandLeaves: Iterable<string>): void {\n this.warnMissing(commandLeaves, this.maps[InteractionKind.Slash], 'Slash route', '@SlashRoute');\n }\n\n public warnUnhandledContextMenuRoutes(leaves: ContextMenuLeaves): void {\n const user = this.maps[InteractionKind.UserContextMenu];\n const message = this.maps[InteractionKind.MessageContextMenu];\n this.warnMissing(leaves.user, user, 'User context menu', '@ContextMenuRoute');\n this.warnMissing(leaves.message, message, 'Message context menu', '@ContextMenuRoute');\n }\n\n private warnMissing(names: Iterable<string>, map: RouteMap, label: string, decorator: string): void {\n for (const name of names) {\n if (map.has(name)) continue;\n this.logger.warn(`${label} ${paint.sky.bold(name)} has no registered ${paint.bold(decorator)} handler.`);\n }\n }\n\n // a gateway class carries the same core metadata on a different base class\n private isHandler(value: unknown): value is HandlerConstructor {\n if (typeof value !== 'function' || !Reflect.hasMetadata(InteractionMetadataKey, value)) return false;\n return value.prototype instanceof InteractionHandler || value.prototype instanceof AutocompleteHandler;\n }\n\n private isMiddleware(value: unknown): value is InteractionMiddlewareConstructor {\n if (typeof value !== 'function') return false;\n return (\n value.prototype instanceof InteractionMiddleware &&\n Reflect.hasMetadata(InteractionMiddlewareMetadataKey, value)\n );\n }\n\n private registerMiddleware(ctor: InteractionMiddlewareConstructor, relativePath: string): void {\n const metadata = this.middlewares.register(ctor);\n if (!metadata || !this.loading) return;\n\n // the kinds are the only place a dev sees that a middleware is scoped\n const scope = metadata.keys ? `${metadata.priority}, ${metadata.keys.join(', ')}` : metadata.priority;\n this.loadedMiddlewares.push({\n name: `${ctor.name} (${String(scope)})`,\n from: formatFilePath(relativePath)\n });\n }\n\n private unregisterMiddleware(ctor: InteractionMiddlewareConstructor): void {\n this.middlewares.unregister(ctor);\n }\n\n private registerHandler(ctor: HandlerConstructor, relativePath: string): void {\n const from = formatFilePath(relativePath);\n if (!this.routes.register(ctor, from)) return;\n if (this.loading) this.loadedHandlers.push({ name: ctor.name, from });\n }\n}\n","import type { Core } from '#interfaces/Core';\nimport type { Repliables } from '#src/handlers/interactionTypes';\nimport type { InteractionGateContext } from './Gate';\nimport type { DispatchContext } from '@seedcord/core';\nimport type { APIUser } from 'discord-api-types/v10';\n\n// autocomplete is skipped before gates run, so the payload here always carries a reply target\nexport function interactionGateContext(\n payload: Repliables,\n core: Core,\n dispatch: DispatchContext\n): InteractionGateContext {\n const member = payload.member ?? null;\n // discord sends member.user in a guild and the top-level user in a dm\n const resolved = member?.user ?? payload.user;\n return {\n kind: 'interaction',\n core,\n dispatch,\n interaction: payload,\n // justified: every repliable interaction Discord delivers carries a user, the wrapper types don't say so\n user: resolved as APIUser,\n member,\n userId: resolved?.id ?? null,\n guildId: payload.guild_id ?? null,\n channelId: payload.channel?.id ?? null,\n memberRoleIds: member?.roles ?? [],\n memberPermissions: member ? BigInt(member.permissions) : null,\n // app_permissions is present on every interaction Discord delivers, including DMs\n appPermissions: BigInt(payload.app_permissions),\n declaredRoute: null // runHandlerGates overwrites this with the matched route\n };\n}\n","import { Notice } from '@seedcord/core';\nimport { PublishDefault } from '@seedcord/core/internal';\nimport { ApplicationCommandType, ComponentType, InteractionType } from 'discord-api-types/v10';\n\nimport { slashRouteOf } from './slashRouteOf';\n\nimport type { ValidInteractionTypes } from '#handlers/interactionTypes';\nimport type { Core } from '#interfaces/Core';\nimport type { DispatchContext, FaultSource, SubscriptionData } from '@seedcord/core';\nimport type { RenderContext } from '@seedcord/types';\n\ntype InteractionFaultSource = Extract<FaultSource, { kind: 'interaction' }>;\n\n// the raw-payload twin of gateway's extractErrorResponse\nexport function reportFault(\n error: Error,\n uuid: RenderContext['uuid'],\n dispatch: DispatchContext,\n payload: ValidInteractionTypes,\n core: Core\n): void {\n const source = interactionSource(payload);\n const from = { uuid, dispatchId: dispatch.id, origin: dispatch.routeId };\n if (error instanceof Notice && source)\n core.bus[PublishDefault]('handledException', { denial: error, ...from, source });\n else core.bus[PublishDefault]('unknownException', { ...from, error, ...actors(payload), metadata: payload });\n}\n\n// the raw payload has guild_id and no guild name\nfunction actors(payload: ValidInteractionTypes): Pick<SubscriptionData<'unknownException'>, 'guild' | 'user'> {\n const user = payload.member?.user ?? payload.user;\n return { guild: undefined, user: user ? { id: user.id, username: user.username } : undefined };\n}\n\nfunction interactionSource(payload: ValidInteractionTypes): InteractionFaultSource | null {\n // discord sends member.user in a guild and user in a dm\n const user = payload.member?.user ?? payload.user;\n if (!user) return null;\n\n const common = {\n kind: 'interaction',\n userId: user.id,\n guildId: payload.guild_id ?? null,\n channelId: payload.channel?.id ?? null,\n interactionId: payload.id,\n raw: payload\n } as const;\n\n if (payload.type === InteractionType.ApplicationCommand) {\n const { data } = payload;\n const isSlash = data.type === ApplicationCommandType.ChatInput;\n return {\n ...common,\n interactionKind: isSlash ? 'slash' : 'context-menu',\n command: isSlash ? slashRouteOf(data) : data.name,\n customId: null\n };\n }\n if (payload.type === InteractionType.ModalSubmit) {\n return { ...common, interactionKind: 'modal', command: null, customId: payload.data.custom_id };\n }\n if (payload.type === InteractionType.MessageComponent) {\n const isButton = payload.data.component_type === ComponentType.Button;\n return {\n ...common,\n interactionKind: isButton ? 'button' : 'select',\n command: null,\n customId: payload.data.custom_id\n };\n }\n return null;\n}\n","import { DiscordAPIError } from '@discordjs/rest';\nimport { DispatchContext, Fault, InteractionKind, Notice, Silence } from '@seedcord/core';\nimport {\n logUnknownFault,\n outcomeFor,\n queuedMsFor,\n reportDispatch,\n reportedWrite,\n resultFor,\n runAfter,\n runHandlerGates,\n slowGateMonitor\n} from '@seedcord/core/internal';\nimport { paint } from '@seedcord/errors';\nimport { Logger } from '@seedcord/logger';\nimport { asError } from '@seedcord/utils/internal';\nimport { InteractionResponseType, InteractionType, RESTJSONErrorCodes, Routes } from 'discord-api-types/v10';\n\nimport { RepliableHandler } from '#handlers/RepliableHandler';\nimport { ReplySender } from '#reply/ReplySender';\nimport { interactionGateContext } from '#src/gates/context';\n\nimport { reportFault } from './reportFault';\n\nimport type {\n ConstructableHandler,\n HandlerConstructor,\n InteractionMiddlewareConstructor\n} from '#handlers/constructors';\nimport type { InteractionMiddleware } from '#handlers/interaction/InteractionMiddleware';\nimport type { InteractionOf } from '#handlers/interaction/middlewareKinds';\nimport type { ValidInteractionTypes } from '#handlers/interactionTypes';\nimport type { Core } from '#interfaces/Core';\nimport type { ResolvedRoute } from './resolve';\nimport type { DispatchOutcome, DispatchResult, MiddlewareKind } from '@seedcord/core';\nimport type { MiddlewareRegistry } from '@seedcord/core/internal';\nimport type { RenderContext } from '@seedcord/types';\n\n// lazy, env binds after this module loads\nlet dispatchLogger: Logger | undefined;\nfunction logger(): Logger {\n dispatchLogger ??= new Logger('Dispatcher', { channel: 'interactions' });\n return dispatchLogger;\n}\n\ninterface FaultScope {\n readonly core: Core;\n readonly payload: ValidInteractionTypes;\n readonly routeId: string;\n readonly dispatch: DispatchContext;\n // null on autocomplete, whose only legal refusal is an empty type 8\n readonly sender: ReplySender | null;\n}\n\n// each one means the interaction is already gone\nconst HARMLESS_API_CODES: ReadonlySet<number | string> = new Set([\n RESTJSONErrorCodes.UnknownInteraction,\n RESTJSONErrorCodes.InteractionHasAlreadyBeenAcknowledged,\n RESTJSONErrorCodes.UnknownMessage\n]);\n\nasync function sendGuarded(routeId: string, send: () => Promise<unknown>): Promise<void> {\n try {\n await send();\n } catch (error) {\n if (error instanceof DiscordAPIError && HARMLESS_API_CODES.has(error.code)) {\n logger().debug(`boundary send hit harmless code ${paint.amber(String(error.code))}`);\n return;\n }\n logger().error(`boundary send failed for route ${paint.sky.bold(routeId)}`, error);\n }\n}\n\n// empty choices are the only legal way to clear a pending autocomplete\nasync function respondEmptyChoices(scope: FaultScope): Promise<void> {\n const telemetry = { bus: scope.core.bus, dispatch: scope.dispatch, interactionId: scope.payload.id };\n await reportedWrite(telemetry, 'respond', () =>\n scope.core.rest.post(Routes.interactionCallback(scope.payload.id, scope.payload.token), {\n body: { type: InteractionResponseType.ApplicationCommandAutocompleteResult, data: { choices: [] } }\n })\n );\n}\n\nfunction renderContext(scope: FaultScope, uuid: RenderContext['uuid']): RenderContext {\n const { dispatch } = scope;\n const developerUsername = scope.core.config.notifications?.developerUsername;\n return developerUsername === undefined ? { uuid, dispatch } : { uuid, developerUsername, dispatch };\n}\n\nasync function handleNotice(notice: Notice, uuid: RenderContext['uuid'], scope: FaultScope): Promise<void> {\n if (notice.report) {\n logger().error(`${notice.name}: ${paint.mute(uuid)}`, notice);\n reportFault(notice, uuid, scope.dispatch, scope.payload, scope.core);\n }\n const { sender } = scope;\n if (!sender) {\n await sendGuarded(scope.routeId, () => respondEmptyChoices(scope));\n return;\n }\n const response = notice.render(renderContext(scope, uuid));\n await sendGuarded(scope.routeId, () => sender.send(response, { ephemeral: notice.ephemeral }));\n}\n\nasync function handleRawFault(error: Error, uuid: RenderContext['uuid'], scope: FaultScope): Promise<void> {\n const { core, sender } = scope;\n\n logUnknownFault(logger(), paint.mute(uuid), error, core.config.errors);\n\n reportFault(error, uuid, scope.dispatch, scope.payload, core);\n\n if (!sender) {\n await sendGuarded(scope.routeId, () => respondEmptyChoices(scope));\n return;\n }\n\n const Override = core.config.errors?.defaultError;\n const card = Override ? new Override(uuid) : new Fault();\n const response = card.render(renderContext(scope, uuid));\n await sendGuarded(scope.routeId, () => sender.send(response, { ephemeral: true }));\n}\n\nasync function handleFault(caught: unknown, scope: FaultScope): Promise<void> {\n if (caught instanceof Silence) {\n if (caught.reason !== undefined && (scope.core.config.errors?.logSilences ?? true)) {\n logger().debug(`Silence: ${caught.reason}`);\n }\n return;\n }\n\n const uuid = crypto.randomUUID();\n if (caught instanceof Notice) {\n await handleNotice(caught, uuid, scope);\n return;\n }\n\n const error = asError(caught);\n\n const ignore = new Set<number | string>(scope.core.config.errors?.ignoreApiCodes ?? []);\n if (error instanceof DiscordAPIError && ignore.has(error.code)) {\n logger().debug(`swallowed api code ${paint.amber(String(error.code))}`);\n return;\n }\n\n await handleRawFault(error, uuid, scope);\n}\n\ninterface DispatchArgs {\n readonly match: ResolvedRoute;\n readonly payload: ValidInteractionTypes;\n readonly core: Core;\n readonly middlewares: MiddlewareRegistry<InteractionMiddlewareConstructor>;\n}\n\nfunction unhandledRouteId(match: ResolvedRoute): string {\n if (match.routeId) return match.routeId;\n // an empty key means a customId seedcord never minted\n const key = match.attemptedKey ?? '';\n return `${match.kind}:${key.length > 0 ? key : 'unrouted'}`;\n}\n\n// a fresh sender can still reply the card because nothing is acked yet here\nfunction freshScope(\n match: ResolvedRoute,\n payload: ValidInteractionTypes,\n core: Core,\n dispatch: DispatchContext\n): FaultScope {\n const ref = { application_id: payload.application_id, id: payload.id, token: payload.token };\n const routeId = unhandledRouteId(match);\n return {\n core,\n payload,\n routeId,\n dispatch,\n sender: match.kind === InteractionKind.Autocomplete ? null : new ReplySender(ref, core.rest, dispatch, core.bus)\n };\n}\n\nfunction dispatchReporter(\n match: ResolvedRoute,\n payload: ValidInteractionTypes,\n core: Core,\n dispatchId: string\n): (outcome: DispatchOutcome) => void {\n const startedAt = performance.now();\n const queuedMs = queuedMsFor(payload.id);\n return (outcome) => {\n reportDispatch(core.bus, {\n dispatchId,\n routeId: unhandledRouteId(match),\n interactionId: payload.id,\n kind: match.kind,\n outcome,\n fallback: match.routeId === null,\n // discord sends member.user in a guild and user in a dm\n userId: (payload.member?.user ?? payload.user)?.id ?? null,\n guildId: payload.guild_id ?? null,\n startedAt,\n queuedMs\n });\n };\n}\n\nasync function answer(\n caught: unknown,\n scope: FaultScope,\n report: (outcome: DispatchOutcome) => void,\n outcome: DispatchOutcome = outcomeFor(caught)\n): Promise<void> {\n try {\n await handleFault(caught, scope);\n } finally {\n report(outcome);\n }\n}\n\ninterface BeforeHandler {\n readonly args: DispatchArgs;\n readonly Handler: HandlerConstructor;\n readonly dispatch: DispatchContext;\n readonly scope: FaultScope;\n readonly ran: InteractionMiddleware[];\n}\n\nasync function runMiddlewares(step: BeforeHandler, kind: MiddlewareKind, sender: ReplySender): Promise<void> {\n const { args, dispatch, ran } = step;\n for (const Middleware of args.middlewares.chainFor(kind)) {\n // chainFor picked this kind. the payload is the one the class declares.\n const event = args.payload as InteractionOf<MiddlewareKind>;\n const instance = new Middleware(event, args.core, dispatch, sender);\n // pushed before the await because a middleware that throws still gets its after()\n ran.push(instance);\n await instance.execute();\n }\n}\n\n// a returned value is the throw that stops the dispatch before the handler runs\nasync function refusalBeforeHandler(step: BeforeHandler): Promise<{ caught: unknown } | null> {\n const { args, scope } = step;\n const { kind } = args.match;\n\n if (kind !== InteractionKind.Autocomplete && scope.sender) {\n try {\n await runMiddlewares(step, kind, scope.sender);\n } catch (caught) {\n return { caught };\n }\n }\n\n return gateRefusal(step);\n}\n\n// a null return means the refusal is already sent\nexport async function dispatchInteraction(args: DispatchArgs): Promise<(() => Promise<void>) | null> {\n const { match, payload, core } = args;\n const routeId = unhandledRouteId(match);\n // every fault path below renders against this one context\n const dispatch = new DispatchContext(routeId);\n const report = dispatchReporter(match, payload, core, dispatch.id);\n\n const Handler = match.ctor;\n logger().debug(`Processing ${paint.sky.bold(routeId)} with ${paint.mute(Handler.name)}`);\n\n let handler: InstanceType<ConstructableHandler>;\n try {\n // in a union of both handler bases, the event parameter is never. the route pairs each kind with its class.\n handler = new (Handler as ConstructableHandler)(payload as never, core, dispatch);\n } catch (caught) {\n await answer(caught, freshScope(match, payload, core, dispatch), report);\n return null;\n }\n const scope: FaultScope = {\n core,\n payload,\n routeId,\n dispatch,\n sender: handler instanceof RepliableHandler ? handler.sender : null\n };\n\n const ran: InteractionMiddleware[] = [];\n const refusal = await refusalBeforeHandler({ args, Handler, dispatch, scope, ran });\n if (refusal) {\n try {\n // a throwing render() inside answer() must not skip the after() calls\n await answer(refusal.caught, scope, report);\n } finally {\n await runAfter(ran, resultFor(refusal.caught), logger());\n }\n return null;\n }\n\n return async () => {\n let result: DispatchResult = { outcome: 'handled' };\n try {\n await handler.execute();\n report('handled');\n } catch (caught) {\n result = resultFor(caught);\n await answer(caught, scope, report);\n } finally {\n await runAfter(ran, result, logger());\n }\n };\n}\n\n// autocomplete has no reply target. @Gated already rejects a gate on one at compile time.\nasync function gateRefusal(step: BeforeHandler): Promise<{ caught: unknown } | null> {\n const { Handler, dispatch } = step;\n const { match, payload, core } = step.args;\n // match.kind comes from payload.type in the router. the second clause narrows the payload to Repliables.\n if (match.kind === InteractionKind.Autocomplete || payload.type === InteractionType.ApplicationCommandAutocomplete)\n return null;\n const monitor = slowGateMonitor();\n try {\n await runHandlerGates(\n Handler,\n interactionGateContext(payload, core, dispatch),\n match.routeId ?? undefined,\n monitor?.observe\n );\n return null;\n } catch (caught) {\n return { caught };\n } finally {\n // a refusing gate spent budget too\n monitor?.report(match.routeId);\n }\n}\n","import { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\n\nconst PUBLIC_KEY_BYTES = 32;\nconst SIGNATURE_BYTES = 64;\nconst HEX_RADIX = 16;\nconst HEX_PATTERN = /^[0-9a-f]+$/i;\n\nfunction hexToBytes(hex: string, byteLength: number): Uint8Array<ArrayBuffer> | null {\n if (hex.length !== byteLength * 2 || !HEX_PATTERN.test(hex)) return null;\n\n const bytes = new Uint8Array(byteLength);\n for (let index = 0; index < byteLength; index++) {\n bytes[index] = Number.parseInt(hex.slice(index * 2, index * 2 + 2), HEX_RADIX);\n }\n return bytes;\n}\n\nconst encoder = new TextEncoder();\n\nexport class Ed25519Verifier {\n private readonly key: Promise<CryptoKey>;\n\n constructor(publicKeyHex: string) {\n const publicKey = hexToBytes(publicKeyHex, PUBLIC_KEY_BYTES);\n if (!publicKey)\n throw new SeedcordError(SeedcordErrorCode.ConfigInvalidEnv, ['DISCORD_PUBLIC_KEY', '64 hex characters']);\n\n this.key = crypto.subtle.importKey('raw', publicKey, 'Ed25519', false, ['verify']);\n }\n\n async verify(signatureHex: string, timestamp: string, body: Uint8Array): Promise<boolean> {\n const signature = hexToBytes(signatureHex, SIGNATURE_BYTES);\n if (!signature) return false;\n\n const timestampBytes = encoder.encode(timestamp);\n const message = new Uint8Array(timestampBytes.length + body.length);\n message.set(timestampBytes, 0);\n message.set(body, timestampBytes.length);\n\n return crypto.subtle.verify('Ed25519', await this.key, signature, message);\n }\n}\n","const REPLAY_WINDOW_MS = 300_000; // compared in both directions, clock skew stays inside the window\nconst SWEEP_GAP_MS = 60_000;\nconst MS_PER_SECOND = 1000;\nconst TIMESTAMP_PATTERN = /^\\d+$/;\n\n// the seen map is per-isolate on edge, so a fresh isolate rejects a replay on freshness alone\nexport class ReplayGuard {\n private readonly seen = new Map<string, number>();\n private lastSweep = Date.now();\n\n // the parsed value feeds unseen(), which only ever sees timestamps this already accepted\n public fresh(timestampHeader: string): number | null {\n if (!TIMESTAMP_PATTERN.test(timestampHeader)) return null;\n const timestampMs = Number(timestampHeader) * MS_PER_SECOND;\n return Math.abs(Date.now() - timestampMs) <= REPLAY_WINDOW_MS ? timestampMs : null;\n }\n\n public unseen(signatureHex: string, timestampMs: number): boolean {\n const now = Date.now();\n this.maybeSweep(now);\n\n // >= because a timestamp at the exact stale edge is accepted and its entry expires at `now`\n const rejectUntil = this.seen.get(signatureHex);\n if (rejectUntil !== undefined && rejectUntil >= now) return false;\n\n // expires when the freshness check starts rejecting this timestamp\n this.seen.set(signatureHex, timestampMs + REPLAY_WINDOW_MS);\n return true;\n }\n\n // swept on access, a construction-time timer throws in workers global scope\n private maybeSweep(now: number): void {\n if (now - this.lastSweep < SWEEP_GAP_MS) return;\n this.lastSweep = now;\n // strict, the sweep runs before the dedup lookup and must keep an entry expiring exactly at `now`\n for (const [signature, rejectUntil] of this.seen) {\n if (rejectUntil < now) this.seen.delete(signature);\n }\n }\n}\n","import { PublishDefault } from '@seedcord/core/internal';\nimport { paint } from '@seedcord/errors';\nimport { Logger } from '@seedcord/logger';\nimport { asError } from '@seedcord/utils/internal';\nimport { InteractionResponseType, InteractionType } from 'discord-api-types/v10';\n\nimport { dispatchInteraction } from './dispatch/dispatchInteraction';\nimport { resolve } from './dispatch/resolve';\nimport { Ed25519Verifier } from './receiver/Ed25519Verifier';\nimport { ReplayGuard } from './receiver/ReplayGuard';\n\nimport type { InteractionMiddlewareConstructor } from '#handlers/constructors';\nimport type { ValidInteractionTypes } from '#handlers/interactionTypes';\nimport type { Core } from '#interfaces/Core';\nimport type { RouteMaps } from './dispatch/resolve';\nimport type { MiddlewareRegistry } from '@seedcord/core/internal';\nimport type { APIInteraction } from 'discord-api-types/v10';\n\nconst SIGNATURE_HEADER = 'x-signature-ed25519';\nconst TIMESTAMP_HEADER = 'x-signature-timestamp';\n\nconst ACCEPTED = 202;\nconst BAD_REQUEST = 400;\nconst UNAUTHORIZED = 401;\nconst METHOD_NOT_ALLOWED = 405;\n\n// widened so the raw payload's number field compares without an unsafe enum comparison\nconst PING: number = InteractionType.Ping;\n\nconst decoder = new TextDecoder();\n\ntype Outcome = 'not-post' | 'unsigned' | 'stale' | 'bad-signature' | 'bad-body' | 'ping' | 'replay' | 'dispatched';\ntype Answer = readonly [Response, Outcome];\n\n// discord only POSTs to the interactions endpoint\nexport function rejectNonPost(request: Request): Response | undefined {\n if (request.method === 'POST') return undefined;\n return new Response(null, { status: METHOD_NOT_ALLOWED, headers: { allow: 'POST' } });\n}\n\nfunction hasInteractionType(payload: unknown): payload is { type: number } {\n return typeof payload === 'object' && payload !== null && 'type' in payload && typeof payload.type === 'number';\n}\n\n/** Matches the shape of the Workers `ExecutionContext`. Work that continues after the 202 response runs under its `waitUntil`. */\nexport interface EngineContext {\n waitUntil(promise: Promise<unknown>): void;\n}\n\nexport type Engine = (request: Request, ctx?: EngineContext) => Promise<Response>;\n\nexport function buildEngine(\n core: Core,\n maps: RouteMaps,\n middlewares: MiddlewareRegistry<InteractionMiddlewareConstructor>,\n publicKey: string\n): Engine {\n const verifier = new Ed25519Verifier(publicKey);\n const replays = new ReplayGuard();\n // eager because env binds before this factory runs\n const logger = new Logger('Engine', { channel: 'bot' });\n\n async function dispatchMatched(\n match: NonNullable<ReturnType<typeof resolve>>,\n payload: ValidInteractionTypes,\n ctx: EngineContext | undefined\n ): Promise<void> {\n const start = await dispatchInteraction({ match, payload, core, middlewares });\n if (!start) return;\n\n // without this catch the rejection reaches the process unhandled\n const work = start().catch(rootFault);\n ctx?.waitUntil(work);\n }\n\n function rootFault(caught: unknown): void {\n const error = asError(caught);\n logger.error('dispatch failed past the boundary', error);\n core.bus[PublishDefault]('unhandledInteractionError', { error });\n }\n\n const handle = async (request: Request, ctx?: EngineContext): Promise<Response> => {\n const [response, outcome] = await respond(request, ctx);\n logger.debug(`${paint.sky.bold(request.method)} ${outcome} ${paint.amber(String(response.status))}`);\n return response;\n };\n\n const respond = async (request: Request, ctx?: EngineContext): Promise<Answer> => {\n const notPost = rejectNonPost(request);\n if (notPost) return [notPost, 'not-post'];\n\n const signature = request.headers.get(SIGNATURE_HEADER);\n const timestamp = request.headers.get(TIMESTAMP_HEADER);\n if (signature === null || timestamp === null) return [new Response(null, { status: UNAUTHORIZED }), 'unsigned'];\n\n const timestampMs = replays.fresh(timestamp);\n if (timestampMs === null) return [new Response(null, { status: UNAUTHORIZED }), 'stale'];\n\n const body = new Uint8Array(await request.arrayBuffer());\n if (!(await verifier.verify(signature, timestamp, body))) {\n return [new Response(null, { status: UNAUTHORIZED }), 'bad-signature'];\n }\n\n let payload: unknown;\n try {\n payload = JSON.parse(decoder.decode(body));\n } catch {\n return [new Response(null, { status: BAD_REQUEST }), 'bad-body'];\n }\n if (!hasInteractionType(payload)) return [new Response(null, { status: BAD_REQUEST }), 'bad-body'];\n\n // discord resends the same signed ping while verifying an endpoint, and a 401 there reads as a broken endpoint\n if (payload.type === PING) {\n return [Response.json({ type: InteractionResponseType.Pong }), 'ping'];\n }\n\n if (!replays.unseen(signature, timestampMs)) return [new Response(null, { status: UNAUTHORIZED }), 'replay'];\n\n try {\n // justified: the payload is signed by Discord, and the type field anchors the discriminated union\n core.bus[PublishDefault]('anyInteraction', { interaction: payload as APIInteraction });\n const match = resolve(maps, payload as APIInteraction);\n if (match) await dispatchMatched(match, payload as ValidInteractionTypes, ctx);\n } catch (caught) {\n // the 202 has to go out either way or discord drops the interaction\n rootFault(caught);\n }\n\n return [new Response(null, { status: ACCEPTED }), 'dispatched'];\n };\n\n return handle;\n}\n","import { REST } from '@discordjs/rest';\nimport { Bus } from '@seedcord/core';\nimport { interactionMiddleware, MiddlewareRegistry, readBotToken, SubscriberLoader } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { MemoryRateLimiter } from '@seedcord/rate-limiter';\n\nimport { InteractionDispatcher } from '#src/dispatch/InteractionDispatcher';\nimport { emptyRouteMaps } from '#src/dispatch/resolve';\nimport { buildEngine } from '#src/engine';\n\nimport type { InteractionMiddlewareConstructor } from '#handlers/constructors';\nimport type { HttpConfig } from '#interfaces/Config';\nimport type { Core } from '#interfaces/Core';\nimport type { Engine } from '#src/engine';\nimport type { RESTOptions } from '@discordjs/rest';\nimport type { BotToken } from '@seedcord/errors/internal';\nimport type { IRateLimiter } from '@seedcord/types';\n\nexport class InteractionsService {\n public readonly rest: REST;\n public readonly rateLimiter: IRateLimiter;\n public readonly bus: Bus;\n public readonly subscribers: SubscriberLoader;\n public readonly interactions: InteractionDispatcher | undefined;\n\n private token?: BotToken;\n private builtEngine?: Engine;\n\n constructor(\n private readonly host: Core,\n config: HttpConfig,\n restOptions: Partial<RESTOptions> | undefined\n ) {\n this.rest = new REST(restOptions);\n this.rateLimiter = config.store ?? new MemoryRateLimiter();\n this.bus = new Bus(host);\n this.subscribers = new SubscriberLoader(this.bus, config.subscribers.path);\n\n const interactions = config.bot.interactions;\n this.interactions = interactions.path\n ? new InteractionDispatcher(interactions.path, interactions.middlewares)\n : undefined;\n }\n\n public get applicationId(): string {\n if (!this.token) throw new SeedcordError(SeedcordErrorCode.CoreApplicationUnavailable);\n return this.token.applicationId;\n }\n\n public authenticate(): void {\n this.token = readBotToken();\n this.rest.setToken(this.token.value);\n }\n\n public get engine(): Engine {\n if (!this.builtEngine) throw new SeedcordError(SeedcordErrorCode.CoreFetchBeforeStart);\n return this.builtEngine;\n }\n\n public prepareEngine(publicKey: string): Engine {\n this.builtEngine ??= this.createEngine(publicKey);\n return this.builtEngine;\n }\n\n private createEngine(publicKey: string): Engine {\n const maps = this.interactions?.maps ?? emptyRouteMaps();\n const middlewares =\n this.interactions?.middlewares ??\n new MiddlewareRegistry<InteractionMiddlewareConstructor>(interactionMiddleware);\n return buildEngine(this.host, maps, middlewares, publicKey);\n }\n}\n","import { paint } from '@seedcord/errors';\nimport { Routes } from 'discord-api-types/v10';\n\nimport type { REST } from '@discordjs/rest';\nimport type { Logger } from '@seedcord/logger';\n\nexport async function usernameOf(rest: Pick<REST, 'get'>, logger: Logger): Promise<string | undefined> {\n try {\n // justified: the @me payload carries username per the discord api contract\n const me = (await rest.get(Routes.user('@me'))) as { username?: string };\n if (me.username) logger.info(`Running as ${paint.sky.bold(me.username)}`);\n return me.username;\n } catch (caught) {\n // a bad token errors on the first real send anyway\n logger.warn('could not fetch the bot identity', caught);\n return undefined;\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { A as RoleMenuHandler, B as AutocompleteHandler, C as Plugin, D as InteractionMiddleware, E as EngineContext, F as InteractionHandler, H as HttpConfig, I as RepliableHandler, L as InteractionRef, M as StringMenuHandler, N as UserMenuHandler, O as ChannelMenuHandler, P as ComponentHandler, R as ReplySender, S as HttpPluginOptions, T as PluginOptions, U as HttpEdgeConfig, V as Core, W as HttpServerConfig, _ as Emojis, a as ArraySource, b as SelectedMentionables, c as Paginator, d as WebhookLog, f as ModalHandler, g as SlashHandler, h as UserContextMenuHandler, i as InteractionGateContext, j as SelectMenuHandler, k as MentionableMenuHandler, l as PageContext, m as MessageContextMenuHandler, n as version, o as CursorSource, p as ButtonHandler, r as Gated, s as PageSource, t as HmrModuleHandler, u as Subscriber, v as InjectedEmojiMap, w as PluginLifecycleSpec, x as SlashOptions, y as ModalFields, z as SentMessage } from "./shared-vsj1uwIH.mjs";
|
|
2
|
+
import { CoordinatedStartup } from "@seedcord/core/internal";
|
|
3
|
+
import { PluginHost } from "@seedcord/core/plugin";
|
|
4
|
+
import { Bus } from "@seedcord/core";
|
|
5
|
+
import { HostAugmentTarget, HostVersion, SeedcordBrand } from "@seedcord/types/internal";
|
|
6
|
+
import { REST } from "@discordjs/rest";
|
|
7
|
+
import { IRateLimiter } from "@seedcord/types";
|
|
8
|
+
export * from "@seedcord/errors";
|
|
9
|
+
export * from "@seedcord/core";
|
|
10
|
+
export * from "@seedcord/logger";
|
|
11
|
+
export * from "@seedcord/event-emitter";
|
|
12
|
+
export * from "@seedcord/rate-limiter";
|
|
13
|
+
export * from "@seedcord/utils";
|
|
14
|
+
export * from "@seedcord/types";
|
|
15
|
+
//#region src/edge/Seedcord.d.ts
|
|
16
|
+
/**
|
|
17
|
+
* The HTTP-interactions bot on Cloudflare Workers. Default-export it from `bot.ts`. Cloudflare
|
|
18
|
+
* calls `fetch` for every request.
|
|
19
|
+
*
|
|
20
|
+
* The constructor stores the config. The first POST in each isolate reads `DISCORD_BOT_TOKEN`
|
|
21
|
+
* and the public key, command ids, and emoji ids that `seedcord build` wrote into the worker. It
|
|
22
|
+
* loads the handler and subscriber folders, then runs the startup tasks and every plugin's `init()`
|
|
23
|
+
* and `ready()`. Requests that arrive meanwhile wait for it.
|
|
24
|
+
*
|
|
25
|
+
* Under `seedcord dev` the bot starts when the CLI starts it. It reads the public key and emoji
|
|
26
|
+
* ids from Discord and deploys your commands, the way a node bot does.
|
|
27
|
+
*/
|
|
28
|
+
export declare class Seedcord extends PluginHost<'http', 'edge'> {
|
|
29
|
+
#private;
|
|
30
|
+
/** @internal */
|
|
31
|
+
readonly [SeedcordBrand] = true;
|
|
32
|
+
/** @internal */
|
|
33
|
+
readonly [HostAugmentTarget] = "@seedcord/http";
|
|
34
|
+
/** @internal */
|
|
35
|
+
readonly [HostVersion]: string;
|
|
36
|
+
/** Discord REST client built from `bot.restOptions`, with both sweepers off. */
|
|
37
|
+
readonly rest: REST;
|
|
38
|
+
/** @see {@link IRateLimiter} */
|
|
39
|
+
readonly rateLimiter: IRateLimiter;
|
|
40
|
+
/** @see {@link Bus} */
|
|
41
|
+
readonly bus: Bus;
|
|
42
|
+
/**
|
|
43
|
+
* @deprecated Cloudflare Workers don't provide a shutdown hook.
|
|
44
|
+
* @throws A **SeedcordError** with `CoreLifecycleUnavailable` every time you call `addTask`.
|
|
45
|
+
*/
|
|
46
|
+
readonly shutdown: Pick<import("@seedcord/core/node").CoordinatedShutdown, "addTask">;
|
|
47
|
+
/** Add a task that runs during startup, on the first POST. */
|
|
48
|
+
readonly startup: Pick<CoordinatedStartup, 'addTask'>;
|
|
49
|
+
readonly config: HttpEdgeConfig;
|
|
50
|
+
constructor(config: HttpEdgeConfig);
|
|
51
|
+
/** The bot's Discord application id. Throws if you read it before the bot starts. */
|
|
52
|
+
get applicationId(): string;
|
|
53
|
+
/**
|
|
54
|
+
* Answers one request to the interactions endpoint. Cloudflare passes `env` and `ctx`, but this
|
|
55
|
+
* method reads only `ctx`. Import your bindings as `env` from `cloudflare:workers`.
|
|
56
|
+
* `cf workers types` writes their types. Work that continues after the 202 response runs under `ctx.waitUntil`. Any request
|
|
57
|
+
* besides a POST gets a 405 before the bot starts.
|
|
58
|
+
*/
|
|
59
|
+
fetch(request: Request, _env?: unknown, ctx?: EngineContext): Promise<Response>;
|
|
60
|
+
/** @internal */
|
|
61
|
+
protected static reset(): void;
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { ArraySource, AutocompleteHandler, ButtonHandler, ChannelMenuHandler, ComponentHandler, type Core, CursorSource, Emojis, type EngineContext, Gated, HmrModuleHandler, type HttpConfig, type HttpEdgeConfig, type HttpPluginOptions, type HttpServerConfig, type InjectedEmojiMap, type InteractionGateContext, InteractionHandler, InteractionMiddleware, type InteractionRef, MentionableMenuHandler, MessageContextMenuHandler, ModalFields, ModalHandler, type PageContext, type PageSource, Paginator, Plugin, type PluginLifecycleSpec, type PluginOptions, RepliableHandler, ReplySender, RoleMenuHandler, SelectMenuHandler, type SelectedMentionables, type SentMessage, SlashHandler, type SlashOptions, StringMenuHandler, Subscriber, UserContextMenuHandler, UserMenuHandler, WebhookLog, version };
|
|
65
|
+
//# sourceMappingURL=workerd.index.d.mts.map
|