@seedcord/gateway 0.7.2 → 0.7.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["#source","CoreRepliableHandler","CoreBaseHandler","CoreSubscriber","CoreWebhookLog","CorePlugin","logger","logger","event","#logger","#intents","#client","#emojiInjector","#interactions","#events","#commandRegistry","#registerShutdownTasks","#stopAccepting","#drain","#stop","#isInitialized","#login","#logout","packageVersion"],"sources":["../src/logger-bootstrap.ts","../src/bot/decorators/Events.ts","../src/bot/decorators/Gated.ts","../src/bot/decorators/Middlewares.ts","../src/bot/gates/catalog/IgnoreBots.ts","../src/bot/notices/index.ts","../src/bot/gates/catalog/Nsfw.ts","../src/bot/injectors/EmojiInjector.ts","../src/bot/notices/utils.ts","../src/bot/utilities/permissions/checkPermissions.ts","../src/bot/utilities/permissions/checkBotPermissions.ts","../src/bot/utilities/permissions/hasPermsToAssign.ts","../src/bot/confirm/reserved.ts","../src/bot/confirm/getConfirmation.ts","../src/bot/ReplySender.ts","../src/handlers/RepliableHandler.ts","../src/handlers/interaction/InteractionMiddleware.ts","../src/handlers/interaction/InteractionHandler.ts","../src/bot/utilities/miscellaneous/slashRouteOf.ts","../src/handlers/interaction/SlashHandler.ts","../src/handlers/interaction/ContextMenuHandler.ts","../src/handlers/BaseHandler.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/handlers/event/EventHandler.ts","../src/handlers/event/EventMiddleware.ts","../src/pagination/Paginator.ts","../src/pagination/sources.ts","../src/subscribers/index.ts","../src/plugin.ts","../src/miscellaneous/deriveEventActor.ts","../src/bot/gates/runGates.ts","../src/miscellaneous/extractErrorResponse.ts","../src/bot/handleEventFault.ts","../src/bot/reportEventDispatch.ts","../src/bot/controllers/EventDispatcher.ts","../src/bot/defaults/UnhandledRepliable.ts","../src/bot/defaults/UnhandledAutocomplete.ts","../src/bot/harmlessApiCodes.ts","../src/bot/handleInteractionFault.ts","../src/bot/controllers/InteractionDispatcher.ts","../src/miscellaneous/assertGuildsIntent.ts","../src/bot/Bot.ts","../src/version.ts","../src/Seedcord.ts"],"sourcesContent":["import { installNodeDefaults } from '@seedcord/logger/node';\n\n// the gateway runs on node so install the winston sinks before any logging\ninstallNodeDefaults();\n","import { EventMetadataKey } from '@seedcord/core/internal';\n\nimport type { EventHandler } from '#handlers/event';\nimport type { ValidNonInteractionKeys } from '#src/handlers/interactionTypes';\nimport type { EventFrequency } from '@seedcord/types';\nimport type { ClientEvents } from 'discord.js';\nimport type { Constructor } from 'type-fest';\n\n/** Options accepted by the event registration decorator. */\nexport interface RegisterEventOptions {\n /**\n * Frequency: 'once' or 'on'.\n *\n * @defaultValue `'on'`\n */\n readonly frequency?: EventFrequency | undefined;\n}\n\n/** @internal */\nexport interface RegisterEventMetadataEntry<EventKey extends keyof ClientEvents> {\n readonly event: EventKey;\n readonly frequency: EventFrequency;\n}\n\n/** Tuple describing a single event and optional options. */\nexport type EventSpec<EventKey extends ValidNonInteractionKeys> = readonly [\n event: EventKey,\n options?: RegisterEventOptions\n];\n\n/**\n * Registers an event handler class with one or more Discord.js events.\n *\n * Associates the decorated class with the provided Discord client events for automatic registration and execution when those events are emitted.\n *\n * Supply any number of event tuples. Each tuple can include per event options.\n *\n * @typeParam EventKey - Union of Discord.js ClientEvents keys to register for\n * @param defs - One or more tuples of [event, options]\n * @decorator\n * @example\n * ```ts\n * \\@RegisterEvent([Events.MessageCreate])\n * class MessageHandler extends EventHandler<Events.MessageCreate> {\n * async execute() {\n * // Handle message creation\n * }\n * }\n * ```\n *\n * @example\n * ```ts\n * \\@RegisterEvent([Events.MessageCreate], [Events.MessageUpdate])\n * class MessageHandler extends EventHandler<Events.MessageCreate | Events.MessageUpdate> {\n * async execute() {\n * // Handle message creation or update\n * }\n * }\n * ```\n *\n * @example\n * ```ts\n * \\@RegisterEvent([Events.MessageCreate, { frequency: 'once' }], [Events.MessageUpdate])\n * class OneTimeMessageHandler extends EventHandler<Events.MessageCreate | Events.MessageUpdate> {\n * async execute() {\n * // Handle only the first message creation, and message update normally\n * }\n * }\n * ```\n */\nexport function RegisterEvent<const Defs extends readonly EventSpec<ValidNonInteractionKeys>[]>(...defs: Defs) {\n type EventKey = Defs[number][0];\n\n // EventHandler is invariant in its Names generic (match puts Names in the arms, a contravariant position), so\n // this single constraint rejects a handler whose generic and decorator list different events, both directions.\n return function <HandlerCtor extends Constructor<EventHandler<EventKey>>>(constructor: HandlerCtor): void {\n const saved = Reflect.getMetadata(EventMetadataKey, constructor) as\n RegisterEventMetadataEntry<EventKey>[] | undefined;\n const existing = saved ?? [];\n\n const entries = defs.map<RegisterEventMetadataEntry<EventKey>>(([event, options]) => ({\n event,\n frequency: options?.frequency ?? 'on'\n }));\n\n Reflect.defineMetadata(EventMetadataKey, [...existing, ...entries], constructor);\n };\n}\n","import { GatedMetadataKey } from '@seedcord/core/internal';\n\nimport type { AnyHandlerCtor, FitAll } from '#bot/gates/matching';\nimport type { Gate, GateContextBase } from '@seedcord/core';\nimport type { NonEmptyTuple } from 'type-fest';\n\n/**\n * Attaches gates to a handler. The gates run before `execute`, and a gate refusing stops the handler with\n * the reply or drop the gate threw. Multiple gates are ANDed, so each must pass. A gate that requires a\n * context the handler does not provide (a button gate on a slash handler, an interaction gate on an event\n * handler) 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.js';\n *\n * \\@Gated(GuildOnly(), RequirePermissions([PermissionFlagsBits.Administrator]))\n * \\@SlashRoute('maintenance')\n * class Maintenance extends SlashHandler<'maintenance'> {\n * async execute() {\n * // both gates passed, so this runs in a guild with an admin caller\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 needs 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 // mismatch resolves to the error tuple, so 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","import { EventMiddlewareMetadataKey } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordTypeError } from '@seedcord/errors/internal';\n\nimport type { EventMiddleware } from '#handlers/event';\nimport type { ValidNonInteractionKeys } from '#src/handlers/interactionTypes';\nimport type { Constructor, NonEmptyTuple } from 'type-fest';\n\n/** Registration options for an event middleware. */\nexport interface EventMiddlewareOptions<Events extends NonEmptyTuple<ValidNonInteractionKeys>> {\n /**\n * Restrict this middleware to certain Discord client events. The middleware's `EventMiddleware`\n * generic must list the same events, or applying the decorator is a compile error. Omit it to run on\n * every event.\n */\n readonly events?: Events;\n /** Lower runs earlier. Two middleware sharing a priority run in registration order.\n *\n * @defaultValue 0\n */\n readonly priority?: number;\n}\n\n/** @internal */\nexport interface EventMiddlewareMetadata {\n readonly priority: number;\n readonly events?: readonly ValidNonInteractionKeys[];\n}\n\n/**\n * Registers an event middleware. It runs before the handlers for every event it lists.\n *\n * @param options - The events this middleware runs on and its ordering.\n * @decorator\n *\n * @example\n * ```ts\n * \\@RegisterEventMiddleware({ events: [Events.MessageCreate], priority: 10 })\n * class Audit extends EventMiddleware<Events.MessageCreate> {\n * async execute() {\n * this.logger.info(this.event[0].id);\n * }\n * }\n * ```\n *\n * @throws A **SeedcordTypeError** If `priority` is not a finite number.\n */\nexport function RegisterEventMiddleware<\n const Events extends NonEmptyTuple<ValidNonInteractionKeys> = NonEmptyTuple<ValidNonInteractionKeys>\n>(options: EventMiddlewareOptions<Events> = {}) {\n return function (ctor: Constructor<EventMiddleware<Events[number]>>): void {\n const priority = Number(options.priority ?? 0);\n if (!Number.isFinite(priority)) {\n throw new SeedcordTypeError(SeedcordErrorCode.DecoratorInvalidMiddlewarePriority);\n }\n if (options.events?.length === 0) {\n throw new SeedcordTypeError(SeedcordErrorCode.DecoratorEmptyMiddlewareFilter, ['events']);\n }\n\n const metadata: EventMiddlewareMetadata = {\n priority,\n ...(options.events && { events: options.events })\n };\n\n Reflect.defineMetadata(EventMiddlewareMetadataKey, metadata, ctor);\n };\n}\n\n/** @internal */\nexport function eventMiddlewareMetaOf(constructor: object): EventMiddlewareMetadata | undefined {\n const saved: unknown = Reflect.getMetadata(EventMiddlewareMetadataKey, constructor);\n return saved as EventMiddlewareMetadata | undefined;\n}\n","import { defineGate, Silence } from '@seedcord/core';\n\nimport type { EventGateContext } from '../Gate';\n\n/**\n * Drops a client event whose actor is a bot, with a {@link Silence} so nothing is replied. Event-only, because a\n * Silence on an interaction would leave Discord's failed-interaction state. It rejects an interaction handler at\n * the decorator line. Takes no options, so attach it directly without calling it.\n *\n * @see {@link Gated}\n *\n * @example\n * ```ts\n * import { Events } from 'discord.js';\n *\n * \\@Gated(IgnoreBots)\n * class OnMessage extends EventHandler<Events.MessageCreate> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n */\nexport const IgnoreBots = defineGate('IgnoreBots', (ctx: EventGateContext) => {\n if (ctx.user?.bot) throw new Silence('actor is a bot');\n});\n","import { Notice } from '@seedcord/core';\nimport { GateNotice, NoticeCard } from '@seedcord/core/internal';\n\nimport type { ReplyResponse } from '@seedcord/types';\nimport type { Role } from 'discord.js';\n\nexport class NotNsfw extends GateNotice {\n public constructor(message = 'This can only be used in an age-restricted channel.') {\n super(message);\n this.summary = 'be in an age-restricted channel';\n }\n}\n\nexport class RoleHigherThanMe extends Notice {\n public constructor(\n message: string,\n public role: Role,\n public botRole: Role\n ) {\n super(message);\n }\n\n public render(): ReplyResponse {\n const card = new NoticeCard(\n `I cannot assign a role that is higher than me.\\n\\n` +\n `The role <@&${this.role.id}> is higher than my role <@&${this.botRole.id}> in the hierarchy.`\n );\n return { components: [card.component] };\n }\n}\n\nexport class CannotAssignBotRole extends Notice {\n public constructor(message = 'I cannot assign a managed role.') {\n super(message);\n }\n\n public render(): ReplyResponse {\n return { components: [new NoticeCard('I cannot assign a managed role.').component] };\n }\n}\n","import { defineGate } from '@seedcord/core';\nimport { pickNotice } from '@seedcord/core/internal';\n\nimport { NotNsfw } from '#bot/notices';\n\nimport type { NonModalInteraction } from '#src/handlers/interactionTypes';\nimport type { InteractionGateContext } from '../Gate';\nimport type { Gate, GateNoticeOptions } from '@seedcord/core';\n\n// a thread carries no nsfw flag of its own\nfunction channelIsNsfw(channel: InteractionGateContext['interaction']['channel']): boolean {\n if (!channel) return false;\n if (channel.isThread()) return channel.parent?.nsfw ?? false;\n return 'nsfw' in channel ? channel.nsfw : false;\n}\n\n/**\n * Requires an age-restricted channel, else refuses. Pass {@link GateNoticeOptions} to reword or replace the refusal.\n *\n * A thread inherits its parent channel's nsfw flag. ModalSubmit has no reliable channel, so it is excluded.\n *\n * @param options - Reword the default refusal with `message`, or replace it with `notice`.\n *\n * @see {@link Gated}\n *\n * @example\n * ```ts\n * \\@Gated(Nsfw())\n * \\@SlashRoute('nsfwcmd')\n * class NsfwHandler extends SlashHandler<'nsfwcmd'> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n */\nexport function Nsfw(options?: GateNoticeOptions): Gate<InteractionGateContext<NonModalInteraction>, 'Nsfw'> {\n return defineGate('Nsfw', (ctx: InteractionGateContext<NonModalInteraction>) => {\n if (channelIsNsfw(ctx.interaction.channel)) return;\n throw pickNotice(options, (message) => new NotNsfw(message));\n });\n}\n","import { ResolvedEmoji } from '@seedcord/core';\nimport { accessorStore, clearStore, guardedAccessor, isEmojiTuple } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { Logger } from '@seedcord/logger';\n\nimport type { Core } from '#interfaces/Core';\nimport type { EmojiMap } from '@seedcord/types';\nimport type { ApplicationEmoji, GuildEmoji } from 'discord.js';\n\ntype SavedEmojiType = GuildEmoji | ApplicationEmoji;\n\n/** A resolved emoji, plus the discord.js emoji it came from on {@link GatewayEmoji.source}. */\nexport class GatewayEmoji<Source extends SavedEmojiType = SavedEmojiType> extends ResolvedEmoji {\n // Object.entries skips a private field\n readonly #source: Source;\n\n constructor(source: Source) {\n super(source.name, source.id, source.animated);\n this.#source = source;\n }\n\n /** What discord.js resolved, for `.url` and the management calls. */\n public get source(): Source {\n return this.#source;\n }\n}\n\nconst emojiStorage = accessorStore<GatewayEmoji>();\n\n/**\n * The global {@link Emojis} accessor type. Each key's `source` resolves to its precise class, `GuildEmoji`\n * for a `'guild'` tag and `ApplicationEmoji` for an `'application'` tag, the tags `seedcord codegen`\n * writes into {@link EmojiMap}.\n */\nexport type InjectedEmojiMap = {\n [K in keyof EmojiMap]: EmojiMap[K] extends 'guild' ? GatewayEmoji<GuildEmoji> : GatewayEmoji<ApplicationEmoji>;\n};\n\n/**\n * The bot's resolved emojis, keyed by {@link EmojiMap}. Filled by {@link EmojiInjector} during startup.\n * Throws if you read a key the injector did not fill.\n */\nexport const Emojis = guardedAccessor('Emojis', emojiStorage) as InjectedEmojiMap;\n\n// a guild emoji requires the Guilds intent in the client options\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 this.clearEmojis();\n\n if (!this.core.config.bot.emojis || Object.keys(this.core.config.bot.emojis).length === 0) {\n this.logger.debug('No emojis configured, skipping emoji injection.');\n return;\n }\n\n const configEmojis = this.core.config.bot.emojis;\n await this.core.bot.client.application?.emojis.fetch();\n\n const failures: string[] = [];\n const fetchedGuilds = new Set<string>();\n for (const [key, value] of Object.entries(configEmojis)) {\n if (isEmojiTuple(value)) {\n await this.resolveTuple(key, value, failures, fetchedGuilds);\n } else if (typeof value === 'string') {\n this.resolveString(key, value, failures);\n } else {\n failures.push(` - \"${key}\" has an invalid value (expected a name or [name, guildId])`);\n }\n }\n\n if (failures.length > 0) {\n throw new SeedcordError(SeedcordErrorCode.ConfigEmojiUnresolved, [failures.length, failures.join('\\n')]);\n }\n\n this.logger.utils.summary('Loaded emojis', { emojis: Object.keys(emojiStorage).length });\n }\n\n private async resolveTuple(\n key: string,\n value: readonly [string, string],\n failures: string[],\n fetchedGuilds: Set<string>\n ): Promise<void> {\n const [emojiName, guildId] = value;\n\n const guild = this.core.bot.client.guilds.cache.get(guildId);\n if (!guild) {\n failures.push(\n ` - \"${emojiName}\" for \"${key}\" targets guild ${guildId}, which is not available (check the Guilds intent)`\n );\n return;\n }\n\n if (!fetchedGuilds.has(guildId)) {\n await guild.emojis.fetch();\n fetchedGuilds.add(guildId);\n }\n const guildEmoji = guild.emojis.cache.find((e) => e.name === emojiName);\n if (!guildEmoji) {\n failures.push(` - \"${emojiName}\" for \"${key}\" was not found in guild ${guildId}`);\n return;\n }\n\n emojiStorage[key] = new GatewayEmoji(guildEmoji);\n }\n\n private resolveString(key: string, emojiName: string, failures: string[]): void {\n const appEmoji = this.core.bot.client.application?.emojis.cache.find((e) => e.name === emojiName);\n if (!appEmoji) {\n failures.push(` - \"${emojiName}\" for \"${key}\" was not found among the application emojis`);\n return;\n }\n\n emojiStorage[key] = new GatewayEmoji(appEmoji);\n }\n\n private clearEmojis(): void {\n clearStore(emojiStorage);\n }\n}\n","import { Role } from 'discord.js';\n\nimport type { GuildMember } from 'discord.js';\n\n// whose permissions a check ran against, mentioned as the refusal subject\ntype PermSubject = Role | GuildMember;\n\nexport function mentionFor(subject: PermSubject): string {\n if (subject instanceof Role) return `<@&${subject.id}>`;\n return `<@${subject.id}>`;\n}\n","import { assertPermissions } from '@seedcord/core';\nimport { Guild, GuildMember, Role } from 'discord.js';\n\nimport { mentionFor } from '#bot/notices/utils';\n\nimport type { PermissionNoticeOverrides, PermissionScope } from '@seedcord/core';\nimport type { TextChannel } from 'discord.js';\n\n/** Options for {@link checkPermissions}. */\nexport interface CheckPermissionOptions extends PermissionNoticeOverrides {\n /** The role or member to check. */\n for: Role | GuildMember;\n /** A guild reads the base bits from roles, a text channel reads the overwrite-resolved set. */\n in: Guild | TextChannel;\n /** The permission flag bits to check. */\n scope: PermissionScope;\n /** Refuse when the target holds a scope bit. */\n inverse?: boolean;\n}\n\n/**\n * Checks a {@link Role} or a {@link GuildMember} against the base permission bits in a {@link Guild},\n * before channel overwrites. Refuses when a permission in `scope` is missing, or with `inverse` when one\n * is present.\n *\n * @example\n * ```ts\n * import { PermissionFlagsBits } from 'discord.js';\n * import { checkPermissions } from '@seedcord/gateway';\n *\n * checkPermissions(role, guild, [PermissionFlagsBits.ManageMessages, PermissionFlagsBits.KickMembers]);\n * ```\n *\n * @example\n * ```ts\n * // refuse when the member holds Administrator, and replace the refusal\n * checkPermissions(member, guild, [PermissionFlagsBits.Administrator], true, {\n * dangerousNotice: CustomDangerousNotice\n * });\n * ```\n */\nexport function checkPermissions(\n target: Role | GuildMember,\n ctx: Guild,\n scope: PermissionScope,\n inverse?: boolean,\n errors?: PermissionNoticeOverrides\n): void;\n\n/**\n * Checks a {@link Role} or a {@link GuildMember} against the overwrite-resolved set in a\n * {@link TextChannel}. Refuses when a permission in `scope` is missing, or with `inverse` when one is\n * present.\n *\n * @example\n * ```ts\n * import { PermissionFlagsBits } from 'discord.js';\n * import { checkPermissions } from '@seedcord/gateway';\n *\n * checkPermissions(role, textChannel, [PermissionFlagsBits.SendMessages, PermissionFlagsBits.ViewChannel]);\n * ```\n */\nexport function checkPermissions(\n target: Role | GuildMember,\n // eslint-disable-next-line @typescript-eslint/unified-signatures -- the guild and channel forms resolve different bits, documented separately\n ctx: TextChannel,\n scope: PermissionScope,\n inverse?: boolean,\n errors?: PermissionNoticeOverrides\n): void;\n\n/**\n * Checks permissions with an options object. Refuses when a permission in\n * {@link CheckPermissionOptions.scope} is missing, or with `options.inverse` when one is present.\n *\n * @example\n * ```ts\n * import { PermissionFlagsBits } from 'discord.js';\n * import { checkPermissions } from '@seedcord/gateway';\n *\n * checkPermissions({\n * for: member,\n * in: textChannel,\n * scope: [PermissionFlagsBits.SendMessages, PermissionFlagsBits.ViewChannel]\n * });\n * ```\n */\nexport function checkPermissions(options: CheckPermissionOptions): void;\n\nexport function checkPermissions(\n a: Role | GuildMember | CheckPermissionOptions,\n b?: Guild | TextChannel,\n c?: PermissionScope,\n d?: boolean,\n e?: PermissionNoticeOverrides\n): void {\n const opts: CheckPermissionOptions =\n a instanceof Role || a instanceof GuildMember\n ? // justified: the positional overloads always supply b and c, the implementation signature widens them to | undefined\n {\n for: a,\n in: b as Guild | TextChannel,\n scope: c as PermissionScope,\n inverse: d ?? false,\n ...e\n }\n : a;\n\n const { for: pFor, in: pIn, scope, inverse = false, missingNotice, dangerousNotice } = opts;\n\n const perms = pIn instanceof Guild ? pFor.permissions : pIn.permissionsFor(pFor, true);\n\n assertPermissions({\n subject: mentionFor(pFor),\n permissions: perms.bitfield,\n scope,\n inverse,\n ...(missingNotice && { missingNotice }),\n ...(dangerousNotice && { dangerousNotice })\n });\n}\n","import { MissingPermissions, PermissionNames } from '@seedcord/core/internal';\nimport { Logger } from '@seedcord/logger';\nimport { Guild } from 'discord.js';\n\nimport { checkPermissions } from './checkPermissions';\n\nimport type { PermissionNoticeOverrides, PermissionScope } from '@seedcord/core';\nimport type { TextChannel } from 'discord.js';\n\n/**\n * Checks the bot's own permissions in a {@link Guild} or {@link TextChannel}. Refuses when a permission in\n * `scope` is missing, or with `inverse` when one is present. When the bot member is uncached, the refusal\n * reports every permission in `scope` as missing.\n *\n * @example\n * ```ts\n * import { PermissionFlagsBits } from 'discord.js';\n * import { checkBotPermissions } from '@seedcord/gateway';\n *\n * checkBotPermissions(textChannel, [PermissionFlagsBits.SendMessages, PermissionFlagsBits.ViewChannel]);\n * ```\n */\nexport function checkBotPermissions(\n target: Guild | TextChannel,\n scope: PermissionScope,\n inverse = false,\n errors?: PermissionNoticeOverrides\n): void {\n if (target instanceof Guild) {\n const me = target.members.me;\n if (!me) {\n const names = scope.map((bit) => PermissionNames.get(bit) ?? String(bit));\n const Missing = errors?.missingNotice ?? MissingPermissions;\n throw new Missing(undefined, 'The bot', names);\n }\n checkPermissions(me, target, scope, inverse, errors);\n return;\n }\n\n const me = target.guild.members.me;\n\n if (!me) {\n const logger = new Logger('checkBotPermissions', { channel: 'errors' });\n logger.warn(\n `Bot member is unavailable in guild ${target.guild.id} while checking permissions in channel ${target.id}`\n );\n const names = scope.map((bit) => PermissionNames.get(bit) ?? String(bit));\n const Missing = errors?.missingNotice ?? MissingPermissions;\n throw new Missing(undefined, 'The bot', names);\n }\n\n checkPermissions(me, target, scope, inverse, errors);\n}\n","import { MissingPermissions } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { PermissionFlagsBits, Role } from 'discord.js';\n\nimport { CannotAssignBotRole, RoleHigherThanMe } from '#bot/notices';\n\nimport { checkBotPermissions } from './checkBotPermissions';\n\nimport type { Notice } from '@seedcord/core';\nimport type { Guild } from 'discord.js';\n\n/**\n * Optional custom error constructors for {@link HasPermsToAssignOptions}.\n */\nexport interface AssignRoleNoticeOverrides {\n higherNotice?: new (message: string, role: Role, botRole: Role) => Notice;\n managedNotice?: new (message: string) => Notice;\n missingNotice?: new (message: string | undefined, subject: string, missingPerms: readonly string[]) => Notice;\n}\n\n/**\n * Options for {@link hasPermsToAssign}.\n */\nexport interface HasPermsToAssignOptions {\n targetRole: Role;\n noticeOverrides?: AssignRoleNoticeOverrides;\n}\n\n// botRoleFor searches the guild's role cache, so a cold cache returns null\nfunction botRoleOf(guild: Guild): Role {\n const botRole = guild.roles.botRoleFor(guild.client.user);\n if (!botRole) throw new SeedcordError(SeedcordErrorCode.CoreBotRoleMissing, [guild.id]);\n return botRole;\n}\n\n/**\n * Validates that the bot can assign a target role. Refuses when the target role is above the bot's, is managed, or the bot lacks Manage Roles.\n *\n * @param roleOrOptions - Target role or complete options for the check\n * @throws A `Notice` on refusal, or a `SeedcordError` when the bot has no role in the guild's role cache.\n *\n * @example\n * ```ts\n * import { hasPermsToAssign } from '@seedcord/gateway';\n *\n * // Check if the bot can assign a specific role\n * hasPermsToAssign(role);\n *\n * // Check with custom error handling\n * hasPermsToAssign({\n * targetRole: role,\n * noticeOverrides: {\n * higherNotice: CustomHigherNotice,\n * managedNotice: CustomManagedNotice,\n * missingNotice: CustomMissingPermissionsNotice\n * }\n * });\n * ```\n */\nexport function hasPermsToAssign(roleOrOptions: Role | HasPermsToAssignOptions): void {\n const { targetRole, noticeOverrides: errors } =\n roleOrOptions instanceof Role\n ? {\n targetRole: roleOrOptions,\n noticeOverrides: undefined\n }\n : roleOrOptions;\n\n const HigherNotice = errors?.higherNotice ?? RoleHigherThanMe;\n const ManagedNotice = errors?.managedNotice ?? CannotAssignBotRole;\n const MissingNotice = errors?.missingNotice ?? MissingPermissions;\n\n const botRole = botRoleOf(targetRole.guild);\n\n if (targetRole.comparePositionTo(botRole) >= 0) {\n throw new HigherNotice('Role is higher than me', targetRole, botRole);\n }\n\n if (targetRole.managed) {\n throw new ManagedNotice(`Cannot assign managed role ${targetRole.name}`);\n }\n\n checkBotPermissions(targetRole.guild, [PermissionFlagsBits.ManageRoles], false, { missingNotice: MissingNotice });\n}\n","import { CustomId } from '@seedcord/core';\n\nconst RESERVED_CONFIRM_PREFIX = '__seedcord_confirm';\n\n// no route, so the dispatcher skips these clicks and the in-process collector reads them instead. never mint a real component from this id.\nexport const CONFIRM_DEF = new CustomId(RESERVED_CONFIRM_PREFIX).oneOf('choice', ['confirm', 'cancel']);\n","import { ButtonBuilder, TextDisplayBuilder } from '@discordjs/builders';\nimport { BuilderComponent, RowComponent } from '@seedcord/core';\nimport { ButtonStyle, ComponentType } from 'discord.js';\n\nimport { CONFIRM_DEF } from './reserved';\n\nimport type { ReplySender } from '#bot/ReplySender';\nimport type { NonModalInteraction } from '#src/handlers/interactionTypes';\nimport type { RepliableHandler } from '#src/handlers/RepliableHandler';\nimport type { ReplyResponse } from '@seedcord/types';\nimport type { ButtonInteraction, Message } from 'discord.js';\nimport type { Promisable } from 'type-fest';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n// encode the ids once because the reserved def's shape and choices never change\nconst CONFIRM_IDS = {\n confirm: CONFIRM_DEF.encode({ choice: 'confirm' }),\n cancel: CONFIRM_DEF.encode({ choice: 'cancel' })\n};\n\ntype Outcome = ReplyResponse | (() => Promisable<ReplyResponse>);\n\ntype ConfirmPrompt = string | ((ids: { confirm: string; cancel: string }) => Promisable<ReplyResponse>);\n\n/** Options shared by both confirmation forms. */\nexport interface ConfirmOptions {\n /**\n * Whether the prompt is ephemeral. Only the invoking user can act on it either way, a non-invoker's\n * click is ignored.\n *\n * @defaultValue `true`\n */\n ephemeral?: boolean;\n /**\n * Milliseconds to wait for a click before the prompt is settled and the result resolves to `false`.\n *\n * @defaultValue `30_000`\n */\n timeoutMs?: number;\n /** Shown in place of the prompt when the user confirms. Absent removes the prompt. */\n onConfirm?: Outcome;\n /** Shown in place of the prompt when the user cancels. Absent removes the prompt. */\n onCancel?: Outcome;\n /** Shown in place of the prompt when the prompt times out. Absent removes the prompt. */\n onTimeout?: Outcome;\n}\n\n/** Options for the string-prompt form, adding the built-in Confirm/Cancel buttons' labels and style. */\nexport interface DefaultConfirmOptions extends ConfirmOptions {\n /**\n * Confirm-button label.\n *\n * @defaultValue `'Confirm'`\n */\n confirmLabel?: string;\n /**\n * Cancel-button label.\n *\n * @defaultValue `'Cancel'`\n */\n cancelLabel?: string;\n /**\n * Confirm-button style.\n *\n * @defaultValue {@link ButtonStyle.Danger}\n */\n confirmStyle?: ButtonStyle;\n}\n\nclass ConfirmButtons extends RowComponent<'button'> {\n constructor(options: DefaultConfirmOptions | undefined) {\n super('button');\n this.instance.addComponents(\n new ButtonBuilder()\n .setCustomId(CONFIRM_IDS.confirm)\n .setLabel(options?.confirmLabel ?? 'Confirm')\n .setStyle(options?.confirmStyle ?? ButtonStyle.Danger),\n new ButtonBuilder()\n .setCustomId(CONFIRM_IDS.cancel)\n .setLabel(options?.cancelLabel ?? 'Cancel')\n .setStyle(ButtonStyle.Secondary)\n );\n }\n}\n\nclass ConfirmPromptCard extends BuilderComponent<'container'> {\n constructor(text: string, options: DefaultConfirmOptions | undefined) {\n super('container');\n this.instance\n .addTextDisplayComponents(new TextDisplayBuilder().setContent(text))\n .addActionRowComponents(new ConfirmButtons(options).component);\n }\n}\n\nfunction defaultPrompt(text: string, options: DefaultConfirmOptions | undefined): ReplyResponse {\n return { components: [new ConfirmPromptCard(text, options).component] };\n}\n\nasync function collectChoice(message: Message, userId: string, timeoutMs: number): Promise<ButtonInteraction | null> {\n try {\n return await message.awaitMessageComponent({\n componentType: ComponentType.Button,\n time: timeoutMs,\n filter: (click) => click.user.id === userId && CONFIRM_DEF.owns(click.customId)\n });\n } catch {\n // awaitMessageComponent rejects on timeout, which resolves to no decision here\n return null;\n }\n}\n\nasync function settle(sender: ReplySender, message: Message, outcome: Outcome | undefined): Promise<void> {\n if (outcome === undefined) {\n // a plain message.delete() cannot remove an ephemeral message\n await sender.delete(message).catch(() => undefined);\n return;\n }\n await sender.edit(message, typeof outcome === 'function' ? await outcome() : outcome);\n}\n\n/**\n * Shows a confirm/cancel prompt with built-in Confirm and Cancel buttons and resolves to `true` only if the\n * invoking user clicks confirm. A cancel click or a timeout resolves to `false`. Gate the action behind it\n * with an early return. A failed prompt send throws into the fault boundary. A {@link ModalHandler} is\n * excluded at compile time.\n *\n * @param handler - The handler to prompt from, `this` inside a non-modal handler.\n * @param prompt - The message shown above the Confirm and Cancel buttons.\n * @param options - Ephemeral flag, timeout, the built-in buttons' labels and style, and the optional\n * `onConfirm`/`onCancel`/`onTimeout` outcome replies that edit the prompt in place.\n * @returns `true` if confirmed, `false` on cancel or timeout.\n *\n * @example\n * ```ts\n * import { getConfirmation } from '@seedcord/gateway';\n *\n * \\@SlashRoute('ban')\n * class BanHandler extends SlashHandler<'ban'> {\n * async execute() {\n * const target = this.options.getUser('target');\n * if (!(await getConfirmation(this, `Ban ${target.tag}? This cannot be undone.`))) return;\n * await this.event.guild?.members.ban(target.id);\n * }\n * }\n * ```\n */\nexport function getConfirmation(\n handler: RepliableHandler<NonModalInteraction>,\n prompt: string,\n options?: DefaultConfirmOptions\n): Promise<boolean>;\n/**\n * Shows a confirm/cancel prompt you build yourself and resolves to `true` only if the invoking user clicks\n * confirm. The factory receives the two minted button ids. Set them on your own buttons. A cancel click or a\n * timeout resolves to `false`. A failed prompt send throws into the fault boundary. A {@link ModalHandler} is\n * excluded at compile time.\n *\n * @param handler - The handler to prompt from, `this` inside a non-modal handler.\n * @param prompt - A factory given the minted `{ confirm, cancel }` ids that returns the reply to show. Build\n * it with the `BuilderComponent` and `RowComponent` wrappers.\n * @param options - Ephemeral flag, timeout, and the optional `onConfirm`/`onCancel`/`onTimeout` outcome\n * replies that edit the prompt in place.\n * @returns `true` if confirmed, `false` on cancel or timeout.\n *\n * @remarks\n * The prompt is collected in-process, so it does not survive a bot restart. Without an outcome hook the\n * prompt is gone once the user confirms, so deliver the result with a fresh `this.followUp(...)`.\n *\n * @example\n * ```ts\n * import { ButtonBuilder, TextDisplayBuilder } from '@discordjs/builders';\n * import { ButtonStyle } from 'discord.js';\n * import { BuilderComponent, RowComponent, getConfirmation } from '@seedcord/gateway';\n *\n * class BanPrompt extends BuilderComponent<'container'> {\n * constructor(text: string) {\n * super('container');\n * this.instance.addTextDisplayComponents(new TextDisplayBuilder().setContent(text));\n * }\n * }\n *\n * class ConfirmRow extends RowComponent<'button'> {\n * constructor(ids: { confirm: string; cancel: string }) {\n * super('button');\n * const buttons = [\n * [ids.confirm, 'Ban', ButtonStyle.Danger],\n * [ids.cancel, 'Cancel', ButtonStyle.Secondary]\n * ] as const;\n * this.instance.addComponents(\n * ...buttons.map(([id, label, style]) => new ButtonBuilder().setCustomId(id).setLabel(label).setStyle(style))\n * );\n * }\n * }\n *\n * const target = this.options.getUser('target');\n * const confirmed = await getConfirmation(\n * this,\n * (ids) => ({ components: [new BanPrompt(`Ban ${target.tag}?`).component, new ConfirmRow(ids).component] }),\n * { onConfirm: { components: [new BanPrompt(`Banned ${target.tag}.`).component] } }\n * );\n * if (!confirmed) return;\n * ```\n */\nexport function getConfirmation(\n handler: RepliableHandler<NonModalInteraction>,\n prompt: (ids: { confirm: string; cancel: string }) => Promisable<ReplyResponse>,\n options?: ConfirmOptions\n): Promise<boolean>;\nexport async function getConfirmation(\n handler: RepliableHandler<NonModalInteraction>,\n prompt: ConfirmPrompt,\n options?: DefaultConfirmOptions\n): Promise<boolean> {\n const { ephemeral = true, timeoutMs = DEFAULT_TIMEOUT_MS } = options ?? {};\n\n const response = typeof prompt === 'string' ? defaultPrompt(prompt, options) : await prompt(CONFIRM_IDS);\n const interaction = handler.getEvent();\n const { sender } = handler;\n const message = await sender.send(response, { ephemeral });\n\n const winner = await collectChoice(message, interaction.user.id, timeoutMs);\n if (!winner) {\n await settle(sender, message, options?.onTimeout);\n return false;\n }\n\n // discord can expire the 3s ack window between the filter firing and this ack\n await winner.deferUpdate().catch(() => undefined);\n const confirmed = winner.customId === CONFIRM_IDS.confirm;\n await settle(sender, message, confirmed ? options?.onConfirm : options?.onCancel);\n return confirmed;\n}\n","import { BaseReplySender } from '@seedcord/core';\nimport { deferFlags, sendFlags } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { MessageFlags } from 'discord.js';\n\nimport type { GatewayFile, GatewayReplyResponse } from '#interfaces/ReplyResponse';\nimport type { Repliables } from '#src/handlers/interactionTypes';\nimport type { Bus, DispatchContext } from '@seedcord/core';\nimport type { AckState } from '@seedcord/core/internal';\nimport type { DeferOpts, ReplyFile, SendOpts } from '@seedcord/types';\nimport type {\n APIModalInteractionResponseCallbackData,\n InteractionCallbackResponse,\n InteractionReplyOptions,\n InteractionUpdateOptions,\n MessageComponentInteraction,\n ModalMessageModalSubmitInteraction,\n Message,\n WebhookMessageEditOptions\n} from 'discord.js';\n\n// djs kinds that carry a source message\ntype SourceInteraction = MessageComponentInteraction | ModalMessageModalSubmitInteraction;\n\nexport type SentMessage = Message;\n\nfunction isReplyFile(file: ReplyFile | GatewayFile): file is ReplyFile {\n return typeof file === 'object' && 'data' in file && ArrayBuffer.isView(file.data);\n}\n\n// discord.js rejects a plain Uint8Array\nfunction toDjsFile(file: ReplyFile | GatewayFile): GatewayFile {\n if (!isReplyFile(file)) return file;\n return {\n attachment: Buffer.from(file.data),\n name: file.name,\n ...(file.description !== undefined && { description: file.description }),\n ...(file.title !== undefined && { title: file.title })\n };\n}\n\n// djs flips `replied` on editReply, so per-call derivation would break repeated update() and post-edit\n// send() parity\nfunction seedState(interaction: Repliables): AckState {\n if (interaction.deferred && interaction.ephemeral === null) return 'deferred-update';\n if (interaction.replied) return 'replied';\n if (interaction.deferred) return 'deferred-reply';\n return 'unacked';\n}\n\n/** Writes interaction responses through discord.js. The repliable handler bases and the dispatcher construct it. */\nexport class ReplySender extends BaseReplySender<SentMessage, GatewayFile> {\n public constructor(\n private readonly interaction: Repliables,\n dispatch: DispatchContext,\n bus: Bus\n ) {\n super({ bus, dispatch, interactionId: interaction.id }, seedState(interaction));\n }\n\n protected async writeReply(\n response: GatewayReplyResponse | string,\n opts?: SendOpts\n ): Promise<SentMessage | undefined> {\n const result = await this.interaction.reply({\n ...this.replyOptions(response, sendFlags(opts)),\n withResponse: true\n });\n return this.createdMessage(result);\n }\n\n protected async writeDefer(opts?: DeferOpts): Promise<void> {\n await this.interaction.deferReply({ flags: deferFlags(opts) });\n }\n\n protected async writeDeferUpdate(): Promise<void> {\n await this.sourceInteraction('deferUpdate').deferUpdate();\n }\n\n protected async writeUpdate(response: GatewayReplyResponse | string): Promise<SentMessage | undefined> {\n const source = this.sourceInteraction('update');\n const result = await source.update({ ...this.updateOptions(response), withResponse: true });\n return this.createdMessage(result);\n }\n\n protected async writeFollowUp(response: GatewayReplyResponse | string, opts?: SendOpts): Promise<SentMessage> {\n return await this.interaction.followUp(this.replyOptions(response, sendFlags(opts)));\n }\n\n protected async writeEditOriginal(response: GatewayReplyResponse | string): Promise<SentMessage> {\n return await this.interaction.editReply(this.editOptions(response));\n }\n\n protected async writeEditTarget(targetId: string, response: GatewayReplyResponse | string): Promise<SentMessage> {\n return await this.interaction.webhook.editMessage(targetId, this.editOptions(response));\n }\n\n protected async writeDeleteOriginal(): Promise<void> {\n await this.interaction.deleteReply();\n }\n\n protected async writeDeleteTarget(targetId: string): Promise<void> {\n await this.interaction.deleteReply(targetId);\n }\n\n protected async writeModal(data: APIModalInteractionResponseCallbackData): Promise<void> {\n const { interaction } = this;\n // unreachable after guardModalSource, the throw re-narrows the union for showModal\n if (interaction.isModalSubmit()) this.rejectModalSubmit();\n await interaction.showModal(data);\n }\n\n protected override guardModalSource(): void {\n // the bases gate this at compile time. a direct sender caller skips that\n if (this.interaction.isModalSubmit()) this.rejectModalSubmit();\n }\n\n private rejectModalSubmit(): never {\n throw new SeedcordError(SeedcordErrorCode.ReplyIllegalAckState, [\n 'showModal',\n 'this interaction is a modal submit',\n 'A modal cannot open another modal.',\n this.routeId\n ]);\n }\n\n private sourceInteraction(method: 'update' | 'deferUpdate'): SourceInteraction {\n const { interaction } = this;\n if (interaction.isMessageComponent()) return interaction;\n if (interaction.isModalSubmit() && interaction.isFromMessage()) return interaction;\n throw new SeedcordError(SeedcordErrorCode.ReplyUpdateWithoutSource, [method, this.routeId]);\n }\n\n private replyOptions(response: GatewayReplyResponse | string, flags: number): InteractionReplyOptions {\n const reply = this.serialize(response);\n return {\n components: reply.components,\n flags,\n ...(reply.allowedMentions && { allowedMentions: reply.allowedMentions }),\n ...(reply.files && { files: reply.files.map(toDjsFile) })\n };\n }\n\n private editOptions(response: GatewayReplyResponse | string): WebhookMessageEditOptions {\n const reply = this.serialize(response);\n return {\n components: reply.components,\n flags: MessageFlags.IsComponentsV2,\n ...(reply.allowedMentions && { allowedMentions: reply.allowedMentions }),\n ...(reply.files && { files: reply.files.map(toDjsFile) })\n };\n }\n\n private updateOptions(response: GatewayReplyResponse | string): InteractionUpdateOptions {\n const reply = this.serialize(response);\n return {\n components: reply.components,\n flags: MessageFlags.IsComponentsV2,\n ...(reply.allowedMentions && { allowedMentions: reply.allowedMentions }),\n ...(reply.files && { files: reply.files.map(toDjsFile) })\n };\n }\n\n private createdMessage(result: InteractionCallbackResponse): SentMessage | undefined {\n return result.resource?.message ?? undefined;\n }\n}\n","import { RepliableHandler as CoreRepliableHandler } from '@seedcord/core';\n\nimport { ReplySender } from '#bot/ReplySender';\n\nimport type { SentMessage } from '#bot/ReplySender';\nimport type { Core } from '#interfaces/Core';\nimport type { GatewayFile } from '#interfaces/ReplyResponse';\nimport type { Repliables } from './interactionTypes';\nimport type { DispatchContext } from '@seedcord/core';\n\n/**\n * Shared base the repliable 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 gateway 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 GatewayFile,\n ReplySender\n> {\n // this chain skips gateway BaseHandler, the only class that defines getEvent\n /** @internal */\n public getEvent(): Event {\n return this.event;\n }\n\n protected buildSender(event: Event, core: Core, dispatch: DispatchContext): ReplySender {\n return new ReplySender(event, dispatch, core.bus);\n }\n}\n","import { RepliableHandler } from '#src/handlers/RepliableHandler';\n\nimport type { ReplySender } from '#bot/ReplySender';\nimport type { Core } from '#interfaces/Core';\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.\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. The discord.js guards narrow it. A catchall reads every repliable 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.customId);\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 { RepliableHandler } from '#handlers/RepliableHandler';\n\nimport type { Core } from '#interfaces/Core';\nimport type { NonModalInteraction, Repliables } from '#src/handlers/interactionTypes';\nimport type { DispatchContext, ModalLike } from '@seedcord/core';\n\n/**\n * Shared base the typed interaction handlers extend.\n *\n * Not a public entry point. Extend {@link SlashHandler}, {@link ButtonHandler}, {@link ModalHandler},\n * or one of the select menu bases instead. This class adds `showModal` on top of the reply members\n * those bases share.\n *\n * @typeParam Repliable - The interaction type this handler processes\n */\nexport abstract class InteractionHandler<Repliable extends Repliables> extends RepliableHandler<Repliable> {\n // keep this ctor. inheriting RepliableHandler's protected one collapses HandlerConstructor to never.\n constructor(event: Repliable, 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(this: InteractionHandler<NonModalInteraction>, modal: ModalLike): Promise<void> {\n return this.sender.showModal(modal);\n }\n}\n","import { buildSlashRoute } from '@seedcord/utils/internal';\n\nimport type { AutocompleteInteraction, ChatInputCommandInteraction } from 'discord.js';\n\n// the controller and seedcord codegen both build routes through buildSlashRoute, so a dispatched\n// interaction always matches its generated registry key\nexport function slashRouteOf(interaction: ChatInputCommandInteraction | AutocompleteInteraction): string {\n const group = interaction.options.getSubcommandGroup(false) ?? undefined;\n const subcommand = interaction.options.getSubcommand(false) ?? undefined;\n return buildSlashRoute(interaction.commandName, subcommand, group);\n}\n","import { SlashRouteBrand } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordTypeError } from '@seedcord/errors/internal';\n\nimport { slashRouteOf } from '#bUtilities/miscellaneous/slashRouteOf';\nimport { InteractionHandler } from '#handlers/interaction/InteractionHandler';\n\nimport type { SlashOptions } from '#inputs/SlashOptions';\nimport type { SlashRegistry } from '@seedcord/core';\nimport type { CacheFor } from '@seedcord/core/internal';\nimport type { CacheType, ChatInputCommandInteraction } from 'discord.js';\nimport type { Promisable } from 'type-fest';\n\ntype SlashMatchArms<Route extends keyof SlashRegistry, Cache extends CacheType, Ret> = {\n [Key in Route]: (options: SlashOptions<Key, Cache>) => Promisable<Ret>;\n};\n\n/**\n * Base class for a chat-input (slash) command handler.\n *\n * Pass the route from the generated registry as the generic, the same string as `@SlashRoute`, then read\n * `this.options` for a single command or `this.match` for several. Command authoring stays plain\n * discord.js, `seedcord codegen` 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 * @typeParam Cache - The interaction cache state. The command's contexts set it.\n *\n * @example\n * ```ts\n * \\@SlashRoute('ban')\n * class BanHandler extends SlashHandler<'ban'> {\n * async execute() {\n * const target = this.options.getUser('target'); // User\n * const reason = this.options.getString('reason'); // string | null\n * }\n * }\n * ```\n */\nexport abstract class SlashHandler<\n Route extends keyof SlashRegistry,\n Cache extends CacheType = CacheFor<Route>\n> extends InteractionHandler<ChatInputCommandInteraction<Cache>> {\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [SlashRouteBrand]?: Route;\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 * Use `this.event.options` directly for anything outside this view, such as `getSubcommand()`.\n * However, for the common case, the methods in this would suffice.\n */\n protected get options(): SlashOptions<Route, Cache> {\n // the djs resolver already carries every getter. SlashOptions is its stricter registry-typed view.\n return this.event.options as SlashOptions<Route, Cache>;\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 * @example\n * ```ts\n * \\@SlashRoute('ban', 'kick')\n * class ModHandler extends SlashHandler<'ban' | 'kick'> {\n * async execute() {\n * await this.match({\n * ban: (options) => this.event.guild?.members.ban(options.getUser('target').id),\n * kick: (options) => this.event.guild?.members.kick(options.getUser('member').id)\n * });\n * }\n * }\n * ```\n */\n protected async match<Ret>(arms: SlashMatchArms<Route, Cache, Ret>): Promise<Ret> {\n const route = slashRouteOf(this.event);\n // justified: SlashMatchArms is keyed by Route literals, so 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, Cache>) => Promisable<Ret>>)[route]\n : undefined;\n if (!arm) throw new SeedcordTypeError(SeedcordErrorCode.SlashMatchArmMissing, [route]);\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 { MenuCacheFor, NamesFor } from '@seedcord/core/internal';\nimport type {\n APIInteractionGuildMember,\n ApplicationCommandType,\n BooleanCache,\n CacheType,\n CacheTypeReducer,\n GuildMember,\n Message,\n MessageContextMenuCommandInteraction,\n User,\n UserContextMenuCommandInteraction\n} from 'discord.js';\nimport type { Promisable } from 'type-fest';\n\ntype UserMenuArms<Names extends NamesFor<ApplicationCommandType.User>, Ret> = {\n [Name in Names]: (\n target: User,\n member: CacheTypeReducer<\n MenuCacheFor<ApplicationCommandType.User, Name>,\n GuildMember,\n APIInteractionGuildMember\n > | null\n ) => Promisable<Ret>;\n};\n\ntype MessageMenuArms<Names extends NamesFor<ApplicationCommandType.Message>, Ret> = {\n [Name in Names]: (\n target: Message<BooleanCache<MenuCacheFor<ApplicationCommandType.Message, Name>>>\n ) => Promisable<Ret>;\n};\n\nfunction armFor<Ret>(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') throw new SeedcordTypeError(SeedcordErrorCode.ContextMenuMatchArmMissing, [name]);\n return arm as (...args: never[]) => Promisable<Ret>;\n}\n\n/**\n * Base class for a user context-menu command handler (right-click a user).\n *\n * Pass the command name(s) as the generic, the same as `@UserContextMenuRoute`. Read the right-clicked\n * user 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 * @typeParam Cache - The interaction cache state. The command's contexts set it.\n *\n * @example\n * ```ts\n * \\@UserContextMenuRoute('View Profile')\n * class ViewProfile extends UserContextMenuHandler<'View Profile'> {\n * async execute() {\n * const user = this.target;\n * }\n * }\n * ```\n */\nexport abstract class UserContextMenuHandler<\n Names extends NamesFor<ApplicationCommandType.User>,\n Cache extends CacheType = MenuCacheFor<ApplicationCommandType.User, Names>\n> extends InteractionHandler<UserContextMenuCommandInteraction<Cache>> {\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(): User {\n return this.event.targetUser;\n }\n\n /** The right-clicked user's guild member, null outside a guild. */\n protected get targetMember(): CacheTypeReducer<Cache, GuildMember, APIInteractionGuildMember> | null {\n return this.event.targetMember;\n }\n\n /** Which of the registered commands fired. */\n protected get commandName(): Names {\n return this.event.commandName 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, both narrowed to the cache state of that\n * one command. The arms must cover every name in the generic. A missing name or an unknown key is a\n * 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.tag}.`),\n * Warn: (user, member) => this.reply(`Warned ${member?.displayName ?? user.tag}.`)\n * });\n * }\n * }\n * ```\n */\n protected async match<Ret>(arms: UserMenuArms<Names, Ret>): Promise<Ret> {\n const arm = armFor<Ret>(arms, this.event.commandName);\n return await (arm as (target: User, member: unknown) => Promisable<Ret>)(this.target, this.targetMember);\n }\n}\n\n/**\n * Base class for a message context-menu command handler (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 * @typeParam Cache - The interaction cache state. The command's contexts set it.\n *\n * @example\n * ```ts\n * \\@MessageContextMenuRoute('Report Message')\n * class ReportMessage extends MessageContextMenuHandler<'Report Message'> {\n * async execute() {\n * const message = this.target;\n * }\n * }\n * ```\n */\nexport abstract class MessageContextMenuHandler<\n Names extends NamesFor<ApplicationCommandType.Message>,\n Cache extends CacheType = MenuCacheFor<ApplicationCommandType.Message, Names>\n> extends InteractionHandler<MessageContextMenuCommandInteraction<Cache>> {\n /** @internal */\n declare readonly [ContextMenuKindBrand]?: ApplicationCommandType.Message;\n /** @internal */\n declare readonly [ContextMenuNamesBrand]?: Names;\n\n protected get target(): Message<BooleanCache<Cache>> {\n return this.event.targetMessage;\n }\n\n /** Which of the registered commands fired. */\n protected get commandName(): Names {\n return this.event.commandName 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, narrowed to the cache state of that one command. The arms must\n * cover every name in the 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 * \\@MessageContextMenuRoute('Report Message', 'Pin Message')\n * class MessageTools extends MessageContextMenuHandler<'Report Message' | 'Pin Message'> {\n * async execute() {\n * await this.match({\n * 'Report Message': (message) => this.report(message),\n * 'Pin Message': (message) => message.pin()\n * });\n * }\n * }\n * ```\n */\n protected async match<Ret>(arms: MessageMenuArms<Names, Ret>): Promise<Ret> {\n const arm = armFor<Ret>(arms, this.event.commandName);\n return await (arm as (target: Message<BooleanCache<Cache>>) => Promisable<Ret>)(this.target);\n }\n}\n","import { BaseHandler as CoreBaseHandler } from '@seedcord/core';\n\nimport type { Core } from '../interfaces';\nimport type { ValidEventTypes } from './interactionTypes';\n\n/**\n * The gateway base, fixes the core base's `TCore` to the gateway {@link Core} and adds the `getEvent`\n * gate hook.\n */\nexport abstract class BaseHandler<ValidEvent extends ValidEventTypes> extends CoreBaseHandler<ValidEvent, Core> {\n // gates infer which event a handler is for from this return type\n public getEvent(): ValidEvent {\n return this.event;\n }\n}\n","import { AutocompleteRouteBrand, reportedWrite } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordTypeError } from '@seedcord/errors/internal';\n\nimport { slashRouteOf } from '#bUtilities/miscellaneous/slashRouteOf';\nimport { BaseHandler } from '#src/handlers/BaseHandler';\n\nimport type { Core } from '#interfaces/Core';\nimport type { AutocompleteOptions, DispatchContext, SlashRegistry } from '@seedcord/core';\nimport type { AutocompletableNames, CacheFor, ChoiceValueOf, EntryFor, FocusedField } from '@seedcord/core/internal';\nimport type { ApplicationCommandOptionChoiceData, AutocompleteInteraction, CacheType } from 'discord.js';\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 ApplicationCommandOptionChoiceData<ChoiceValueOf<EntryFor<Route, Name>>>[]\n ) => Promise<void>\n ) => Promisable<Ret>;\n};\n\n/**\n * Base class for a Discord autocomplete handler.\n *\n * Pass the command route(s) from the generated registry as the generic, the same string(s) as\n * `@AutocompleteRoute`. Branch on the focused field with `this.match`, read already-entered sibling options\n * with `this.options`, and find which command fired with `this.route`.\n *\n * @typeParam Route - One or more route keys from {@link SlashRegistry}, e.g. `'search'` or `'search' | 'find'`.\n * @typeParam Cache - The interaction cache state. The command's contexts set it.\n *\n * @example\n * ```ts\n * \\@AutocompleteRoute('search')\n * class SearchAutocomplete extends AutocompleteHandler<'search'> {\n * async execute() {\n * await this.match({\n * query: (value, respond) => respond([{ name: value, value }])\n * });\n * }\n * }\n * ```\n */\nexport abstract class AutocompleteHandler<\n Route extends keyof SlashRegistry,\n Cache extends CacheType = CacheFor<Route>\n> extends BaseHandler<AutocompleteInteraction<Cache>> {\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [AutocompleteRouteBrand]?: Route;\n\n // keep this ctor. inheriting BaseHandler's protected one collapses HandlerConstructor to never.\n constructor(event: AutocompleteInteraction<Cache>, core: Core, dispatch: DispatchContext) {\n super(event, core, dispatch, 'interactions');\n }\n\n private decodedFocused?: { name: string; value: string };\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 if (this.decodedFocused) return this.decodedFocused as FocusedField<Route>;\n const raw = this.event.options.getFocused(true);\n const focused = { name: raw.name, value: raw.value };\n this.decodedFocused = focused;\n // the registry constrains the names\n return focused as FocusedField<Route>;\n }\n\n /**\n * Run the arm for the focused field. Because an autocomplete always dispatches by which field is\n * focused, match is how you read it. There is no single-field shortcut the way slash/component handlers have one.\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. A\n * focused field with no arm, only reachable from a stale-deployed command, throws at runtime.\n *\n * @param arms - One handler per autocompletable field, keyed by field name.\n * @returns The result of the arm that ran.\n *\n * @example\n * ```ts\n * \\@AutocompleteRoute('search')\n * class SearchAutocomplete extends AutocompleteHandler<'search'> {\n * async execute() {\n * await this.match({\n * query: (value, respond) => respond(titles(value).map((s) => ({ name: s, value: s }))),\n * tag: (value, respond) => respond(tags(value).map((s) => ({ name: s, value: s })))\n * });\n * }\n * }\n * ```\n */\n protected async match<Ret>(arms: FocusedArms<Route, Ret>): Promise<Ret> {\n const { name, value } = this.focused;\n const respond = (choices: readonly ApplicationCommandOptionChoiceData[]): Promise<void> =>\n this.respond(choices);\n // justified: FocusedArms is keyed by field literals, so the Record cast indexes it with the runtime field name.\n type Arm = (\n value: string,\n respond: (choices: readonly ApplicationCommandOptionChoiceData[]) => Promise<void>\n ) => Promisable<Ret>;\n const arm = Object.hasOwn(arms, name) ? (arms as Record<string, Arm>)[name] : undefined;\n if (!arm) throw new SeedcordTypeError(SeedcordErrorCode.AutocompleteMatchArmMissing, [name]);\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 ApplicationCommandOptionChoiceData[]): Promise<void> {\n await reportedWrite(\n { bus: this.core.bus, dispatch: this.dispatch, interactionId: this.event.id },\n 'respond',\n () =>\n // eslint-disable-next-line @seedcord/no-raw-interaction-acks -- this is the base respond and calls djs directly\n this.event.respond(choices)\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) 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 // the djs resolver exposes these getters. AutocompleteOptions is the registry-typed view over it.\n return this.event.options 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 '#bot/ReplySender';\nimport type { GatewayReplyResponse } from '#interfaces/ReplyResponse';\nimport type { DecodedComponentRoute, HasComponentDefs, MatchArms, SingleParams } from '@seedcord/core/internal';\nimport type { AnyCustomId } from '@seedcord/custom-id';\nimport type { AnySelectMenuInteraction, ButtonInteraction, ModalSubmitInteraction } from 'discord.js';\nimport type { Promisable } from 'type-fest';\n\ntype ComponentInteraction = ButtonInteraction | ModalSubmitInteraction | AnySelectMenuInteraction;\n\n/**\n * Shared base the customId-routed component handlers extend.\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 and the route matching those bases share.\n *\n * @typeParam Event - The component interaction type this handler processes\n * @typeParam Defs - The customId route definitions registered on the concrete handler\n */\nexport abstract class ComponentHandler<Event extends ComponentInteraction, Defs extends readonly AnyCustomId[]>\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: GatewayReplyResponse | 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.customId);\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.customId` once (cached after the first read) and throws\n * `StaleCustomId` or `InvalidCustomId` when the wire no longer matches the current shape, which the\n * controller boundary turns into a reply. On a handler registered for several routes this is\n * `never`. Use {@link match} instead.\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`, leaving match as 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 arms cover every registered route prefix, checked at compile time, and a prefix\n * unmatched at runtime throws `CustomIdMatchArmMissing`. Decoding runs before any arm, so a stale or\n * corrupt wire throws before an arm body executes.\n *\n * @param arms - One callback per registered route, keyed by prefix.\n * @returns The result of the arm that ran.\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, so 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) throw new SeedcordTypeError(SeedcordErrorCode.CustomIdMatchArmMissing, [prefix]);\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 { ButtonInteraction, CacheType } from 'discord.js';\n\n/**\n * Base class for a button interaction handler.\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 handler\n * members, or rewrite the source message with `this.update`. Passing different definitions to the decorator\n * and the generic is a compile error.\n *\n * @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof ApproveId]`.\n * @typeParam Cache - The interaction cache state, `'cached'` by default.\n *\n * @example\n * ```ts\n * \\@ButtonRoute(ApproveId)\n * class ApproveButton extends ButtonHandler<[typeof ApproveId]> {\n * async execute() {\n * const { userId } = this.params;\n * await this.reply(`approved <@${userId}>`);\n * }\n * }\n * ```\n */\nexport abstract class ButtonHandler<\n Defs extends readonly AnyCustomId[],\n Cache extends CacheType = 'cached'\n> extends ComponentHandler<ButtonInteraction<Cache>, Defs> {\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 { ComponentHandler } from './ComponentHandler';\n\nimport type { SentMessage } from '#bot/ReplySender';\nimport type { GatewayReplyResponse } from '#interfaces/ReplyResponse';\nimport type { InteractionKind } from '@seedcord/core';\nimport type { AnyCustomId } from '@seedcord/custom-id';\nimport type { CacheType, ModalSubmitFields, ModalSubmitInteraction } from 'discord.js';\n\n/**\n * Base class for a modal submit handler.\n *\n * Register the customId definitions this handler decodes with `@ModalRoute`, list the same ones in the\n * generic, then read `this.params` for a single route or `this.match` for several. Read the submitted\n * inputs from `this.fields`. Reply through the handler members. `showModal` fails compilation on this kind,\n * 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 * @typeParam Cache - The interaction cache state, `'cached'` by default.\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<\n Defs extends readonly AnyCustomId[],\n Cache extends CacheType = 'cached'\n> extends ComponentHandler<ModalSubmitInteraction<Cache>, Defs> {\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [ComponentKindBrand]?: InteractionKind.Modal;\n\n /** The fields this modal submitted, read by custom id. */\n protected get fields(): ModalSubmitFields<Cache> {\n return this.event.fields;\n }\n\n /** Rewrite the message this modal was opened from. Throws when a command opened the modal. */\n protected override update(response: GatewayReplyResponse | 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.isFromMessage()) return;\n throw new SeedcordError(SeedcordErrorCode.ReplyUpdateWithoutSource, [method, this.routeId]);\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 {\n AnySelectMenuInteraction,\n CacheType,\n ChannelSelectMenuInteraction,\n MentionableSelectMenuInteraction,\n RoleSelectMenuInteraction,\n StringSelectMenuInteraction,\n UserSelectMenuInteraction\n} from 'discord.js';\n\n/**\n * Shared base the select menu handlers extend.\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 AnySelectMenuInteraction,\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 return this.event.values;\n }\n}\n\n/**\n * Base class for a string select menu handler.\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 * @typeParam Cache - The interaction cache state, `'cached'` by default.\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<\n Defs extends readonly AnyCustomId[],\n Cache extends CacheType = 'cached'\n> extends SelectMenuHandler<StringSelectMenuInteraction<Cache>, Defs> {\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.\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 * @typeParam Cache - The interaction cache state, `'cached'` by default.\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<\n Defs extends readonly AnyCustomId[],\n Cache extends CacheType = 'cached'\n> extends SelectMenuHandler<UserSelectMenuInteraction<Cache>, Defs> {\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(): UserSelectMenuInteraction<Cache>['users'] {\n return this.event.users;\n }\n\n /** The guild members behind the picked users. Discord resolves these only inside a guild. */\n protected get members(): UserSelectMenuInteraction<Cache>['members'] {\n return this.event.members;\n }\n}\n\n/**\n * Base class for a role select menu handler.\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 * @typeParam Cache - The interaction cache state, `'cached'` by default.\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<\n Defs extends readonly AnyCustomId[],\n Cache extends CacheType = 'cached'\n> extends SelectMenuHandler<RoleSelectMenuInteraction<Cache>, Defs> {\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(): RoleSelectMenuInteraction<Cache>['roles'] {\n return this.event.roles;\n }\n}\n\n/**\n * Base class for a channel select menu handler.\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 * @typeParam Cache - The interaction cache state, `'cached'` by default.\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<\n Defs extends readonly AnyCustomId[],\n Cache extends CacheType = 'cached'\n> extends SelectMenuHandler<ChannelSelectMenuInteraction<Cache>, Defs> {\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(): ChannelSelectMenuInteraction<Cache>['channels'] {\n return this.event.channels;\n }\n}\n\n/**\n * Base class for a mentionable select menu handler.\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 * @typeParam Cache - The interaction cache state, `'cached'` by default.\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<\n Defs extends readonly AnyCustomId[],\n Cache extends CacheType = 'cached'\n> extends SelectMenuHandler<MentionableSelectMenuInteraction<Cache>, Defs> {\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(): MentionableSelectMenuInteraction<Cache>['users'] {\n return this.event.users;\n }\n\n /** The guild members behind the picked users. Discord resolves these only inside a guild. */\n protected get members(): MentionableSelectMenuInteraction<Cache>['members'] {\n return this.event.members;\n }\n\n /** The roles this select picked. */\n protected get roles(): MentionableSelectMenuInteraction<Cache>['roles'] {\n return this.event.roles;\n }\n}\n","import { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordTypeError } from '@seedcord/errors/internal';\n\nimport { BaseHandler } from '#src/handlers/BaseHandler';\n\nimport type { Core } from '#interfaces/Core';\nimport type { ValidNonInteractionKeys } from '#src/handlers/interactionTypes';\nimport type { SingleEventPayload } from './payload';\nimport type { DispatchContext } from '@seedcord/core';\nimport type { ClientEvents } from 'discord.js';\nimport type { Promisable } from 'type-fest';\n\n// a single tuple param would drop the discord.js labels from editor signature help\ntype EventMatchArms<Names extends ValidNonInteractionKeys, Ret> = {\n [Name in Names]: (...args: ClientEvents[Name]) => Promisable<Ret>;\n};\n\n/**\n * Base class for a Discord client event handler.\n *\n * Pass the event name(s) as the generic, the same one(s) as `@RegisterEvent`. A single-event handler reads\n * `this.event` (the payload tuple) directly. A handler registered for several events branches with `this.match`,\n * keyed by event name, since the union of payload tuples is not directly readable.\n *\n * @typeParam Names - One or more `ClientEvents` keys, e.g. `Events.MessageCreate` or `Events.MessageCreate | Events.MessageUpdate`.\n *\n * @example\n * ```ts\n * \\@RegisterEvent([Events.MessageCreate], [Events.MessageUpdate])\n * class PingPong extends EventHandler<Events.MessageCreate | Events.MessageUpdate> {\n * async execute() {\n * await this.match({\n * [Events.MessageCreate]: (message) => message.reply('pong'),\n * [Events.MessageUpdate]: (_oldMessage, edited) => edited.reply('pong')\n * });\n * }\n * }\n * ```\n */\nexport abstract class EventHandler<in out Names extends ValidNonInteractionKeys> extends BaseHandler<\n ClientEvents[Names]\n> {\n // the controller threads this in, undefined when a test constructs the handler directly\n private readonly firedEvent: Names | undefined;\n\n constructor(event: ClientEvents[Names], core: Core, dispatch: DispatchContext, eventName?: Names) {\n super(event, core, dispatch, 'events');\n this.firedEvent = eventName;\n }\n\n // never on a multi-event handler, where reading it is a compile error\n declare protected readonly event: SingleEventPayload<Names>;\n\n /**\n * Run the arm for whichever event fired. Use this only when the handler is registered for several\n * events. A single-event handler reads `this.event` directly. On a multi-event handler `this.event` is\n * `never`, so match is the only way to read the payload.\n *\n * Provide one arm per registered event, keyed by its name, and each arm receives that event's own\n * payload tuple. The arms must cover every event in the generic, a missing event or an unknown key is a\n * compile error.\n *\n * @param arms - One handler per registered event, keyed by event name.\n * @returns The result of the arm that ran.\n *\n * @example\n * ```ts\n * \\@RegisterEvent([Events.MessageCreate], [Events.MessageUpdate])\n * class MessageWatcher extends EventHandler<Events.MessageCreate | Events.MessageUpdate> {\n * async execute() {\n * await this.match({\n * [Events.MessageCreate]: (message) => this.scan(message),\n * [Events.MessageUpdate]: (_old, updated) => this.scan(updated)\n * });\n * }\n * }\n * ```\n */\n protected async match<Ret>(arms: EventMatchArms<Names, Ret>): Promise<Ret> {\n const name = this.firedEvent;\n if (name === undefined) throw new SeedcordTypeError(SeedcordErrorCode.EventMatchArmMissing, ['<no event>']);\n // hasOwn, since a plain lookup for an event named `toString` returns Object.prototype's\n const arm = Object.hasOwn(arms, name) ? (arms as Record<string, unknown>)[name] : undefined;\n if (typeof arm !== 'function') throw new SeedcordTypeError(SeedcordErrorCode.EventMatchArmMissing, [name]);\n // this.event is never on a multi-event handler. getEvent() returns the real tuple.\n return await (arm as (...args: unknown[]) => Promisable<Ret>)(...this.getEvent());\n }\n}\n","import { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\n\nimport { BaseHandler } from '#src/handlers/BaseHandler';\n\nimport type { Core } from '#interfaces/Core';\nimport type { ValidNonInteractionKeys } from '#src/handlers/interactionTypes';\nimport type { SingleEventPayload } from './payload';\nimport type { DispatchContext, EventDispatchResult } from '@seedcord/core';\nimport type { ClientEvents } from 'discord.js';\n\n/**\n * Base class for Discord event middleware.\n *\n * Middleware runs before event handlers and can stop the event by throwing a `Silence`. Unlike `EventHandler`, it\n * runs the SAME for every event it is registered for, so it has no `match`. Specify a single event in the\n * generic and `{ events }` to read `this.event` fully typed. Span several events (or omit `{ events }` for a\n * catchall) and `this.event` narrows to `never`, read `this.eventName` and do work that does not depend on the\n * payload shape. A middleware that needs each event's payload is written one event per class.\n *\n * @typeParam EventName - One or more `ClientEvents` keys. Defaults to every event (catchall).\n */\nexport abstract class EventMiddleware<\n in out EventName extends ValidNonInteractionKeys = ValidNonInteractionKeys\n> extends BaseHandler<ClientEvents[EventName]> {\n // the controller threads this in, undefined when a test constructs the middleware directly\n private readonly firedEvent: EventName | undefined;\n\n constructor(event: ClientEvents[EventName], core: Core, dispatch: DispatchContext, eventName?: EventName) {\n super(event, core, dispatch, 'events');\n this.firedEvent = eventName;\n }\n\n // a concrete tuple for one event only, so reading it on a multi-event middleware is a compile error\n declare protected readonly event: SingleEventPayload<EventName>;\n\n /**\n * The event that fired this middleware. Read it on a catchall or multi-event middleware, where `this.event`\n * is `never`, to do work that does not depend on the payload shape. A single-event middleware reads\n * `this.event` directly and does not need this.\n */\n protected get eventName(): EventName {\n if (this.firedEvent === undefined) throw new SeedcordError(SeedcordErrorCode.EventMiddlewareNameUnavailable);\n return this.firedEvent;\n }\n\n /**\n * Runs once the event finishes, newest middleware first. Every middleware whose `execute()`\n * started gets the call, a stopped chain and a throw included. Implement it to release something\n * this middleware took in `execute()`. A throw in here is logged and goes no further.\n *\n * @param result - `outcome` reports the chain alone. `handlers` holds one entry per handler that\n * ran, empty exactly when the chain stopped the event.\n *\n * @example\n * ```ts\n * // the base declares it. an implementation carries `override`.\n * override async after(result: EventDispatchResult) {\n * this.span.end();\n * }\n * ```\n */\n public after?(result: EventDispatchResult): Promise<void>;\n}\n","import { PaginatorBase } from '@seedcord/core';\n\nimport { ButtonHandler } from '#handlers/interaction/components';\n\nimport type { SentMessage } from '#bot/ReplySender';\nimport type { RepliableHandler } from '#handlers/RepliableHandler';\nimport type { Core } from '#interfaces/Core';\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 { CacheType } from 'discord.js';\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>], CacheType> & { execute(): Promise<void> };\n\nfunction contextOf(interaction: Repliables, core: Core): PageContext {\n return { interaction, user: interaction.user, guild: interaction.guild, core };\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) => ctx.guild?.bans.fetch().then((b) => [...b.values()]) ?? [], { perPage: 10 }),\n * renderItem: (ban) => ban.user.tag\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>], CacheType> {\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 { 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 a gateway subscriber, binding `this.core` to the gateway {@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 a gateway subscriber that delivers its event to a Discord webhook, binding\n * `this.core` to the gateway {@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 { 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/**\n * The options a gateway plugin declares, narrowed to the transport and runtime this base serves.\n * A gateway connection is a websocket that needs a long-lived process.\n */\nexport type GatewayPluginOptions = TypedOmit<PluginOptions, 'transport' | 'runtime'> & {\n transport?: 'gateway';\n runtime?: 'server';\n};\n\n/**\n * Base class for a gateway plugin, binding `this.core` to the gateway {@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<\n Opts extends GatewayPluginOptions = { transport: 'gateway'; runtime: 'server' }\n> extends CorePlugin<Opts, Core> {}\n\nexport type { PluginLifecycleSpec, PluginOptions } from '@seedcord/core/plugin';\n","import { GuildMember, Message, User } from 'discord.js';\n\nimport type { Guild } from 'discord.js';\n\nexport interface EventActor {\n guild: Guild | null;\n member: GuildMember | null;\n user: User | null;\n channelId: string | null;\n}\n\n// each event carries the actor in a different argument\nexport function deriveEventActor(args: unknown): EventActor {\n const tuple = Array.isArray(args) ? (args as unknown[]) : [args];\n for (const arg of tuple) {\n if (arg instanceof Message) {\n return { guild: arg.guild, member: arg.member, user: arg.author, channelId: arg.channelId };\n }\n if (arg instanceof GuildMember) return { guild: arg.guild, member: arg, user: arg.user, channelId: null };\n if (arg instanceof User) return { guild: null, member: null, user: arg, channelId: null };\n }\n return { guild: null, member: null, user: null, channelId: null };\n}\n","import { GuildMember } from 'discord.js';\n\nimport { deriveEventActor } from '#miscellaneous/deriveEventActor';\n\nimport type { Core } from '#interfaces/Core';\nimport type { Repliables, ValidNonInteractionKeys } from '#src/handlers/interactionTypes';\nimport type { EventGateContext, InteractionGateContext } from './Gate';\nimport type { DispatchContext } from '@seedcord/core';\nimport type { ClientEvents } from 'discord.js';\n\nexport function interactionGateContext(\n interaction: Repliables,\n core: Core,\n dispatch: DispatchContext\n): InteractionGateContext {\n const rawMember = interaction.member;\n // an uncached member's roles are already plain ids. the everyone role's id equals the guildId.\n const memberRoleIds =\n rawMember instanceof GuildMember\n ? [...rawMember.roles.cache.keys()].filter((id) => id !== interaction.guildId)\n : (rawMember?.roles ?? []);\n\n return {\n kind: 'interaction',\n interaction,\n core,\n dispatch,\n user: interaction.user,\n guild: interaction.guild,\n member: rawMember instanceof GuildMember ? rawMember : null,\n userId: interaction.user.id,\n guildId: interaction.guildId,\n channelId: interaction.channelId,\n memberRoleIds,\n memberPermissions: interaction.memberPermissions?.bitfield ?? null,\n // djs types appPermissions as non-null on interactions\n appPermissions: interaction.appPermissions.bitfield,\n memberGuildPermissions: rawMember instanceof GuildMember ? rawMember.permissions.bitfield : null,\n appGuildPermissions: interaction.guild?.members.me?.permissions.bitfield ?? null,\n declaredRoute: null // runHandlerGates overwrites this with the matched route\n };\n}\n\nexport function eventGateContext(\n eventName: ValidNonInteractionKeys,\n args: ClientEvents[ValidNonInteractionKeys],\n core: Core,\n dispatch: DispatchContext\n): EventGateContext {\n const actor = deriveEventActor(args);\n return {\n kind: 'event',\n core,\n dispatch,\n eventName,\n payload: args,\n user: actor.user,\n guild: actor.guild,\n member: actor.member,\n userId: actor.user?.id ?? null,\n guildId: actor.guild?.id ?? null,\n channelId: actor.channelId,\n // the cache carries the everyone role (id equals the guild id), filtered out to match the interaction shape\n memberRoleIds: actor.member ? [...actor.member.roles.cache.keys()].filter((id) => id !== actor.guild?.id) : [],\n memberPermissions: actor.member?.permissions.bitfield ?? null,\n appPermissions: null,\n memberGuildPermissions: actor.member?.permissions.bitfield ?? null,\n appGuildPermissions: actor.guild?.members.me?.permissions.bitfield ?? null,\n declaredRoute: null // an event handler doesn't declare a route\n };\n}\n","import * as crypto from 'node:crypto';\n\nimport { Notice, Fault } from '@seedcord/core';\nimport { PublishDefault } from '@seedcord/core/internal';\nimport { Logger } from '@seedcord/logger';\n\nimport { slashRouteOf } from '#bot/utilities/miscellaneous/slashRouteOf';\n\nimport type { Core } from '#interfaces/Core';\nimport type { Repliables } from '#src/handlers/interactionTypes';\nimport type { DispatchContext, FaultSource, SubscriptionData } from '@seedcord/core';\nimport type { RenderContext, ReplyResponse, Nullable } from '@seedcord/types';\nimport type { Guild, User } from 'discord.js';\nimport type { UUID } from 'node:crypto';\n\ntype InteractionFaultSource = Extract<FaultSource, { kind: 'interaction' }>;\ntype EventFaultSource = Extract<FaultSource, { kind: 'event' }>;\n\nconst logger = new Logger('ErrorsHandling', { channel: 'errors' });\n\ninterface EventOrigin {\n name: string;\n handler: string;\n args: unknown;\n channelId: string | null;\n}\n\nexport interface ErrorOrigin {\n interaction?: Repliables;\n event?: EventOrigin;\n origin: string;\n dispatch: DispatchContext;\n guild: Nullable<Guild>;\n user: Nullable<User>;\n metadata?: unknown;\n}\n\nexport interface ExtractedErrorResponse {\n uuid: UUID;\n response: ReplyResponse;\n}\n\nexport function extractErrorResponse(error: Error, core: Core, fault: ErrorOrigin): ExtractedErrorResponse {\n const uuid = crypto.randomUUID();\n const { dispatch } = fault;\n const developerUsername = core.config.notifications?.developerUsername;\n const ctx: RenderContext =\n developerUsername === undefined ? { uuid, dispatch } : { uuid, developerUsername, dispatch };\n\n if (error instanceof Notice) {\n if (error.report) reportFault(error, core, fault, uuid);\n return { uuid, response: error.render(ctx) };\n }\n\n reportRawFault(error, core, fault, uuid);\n\n const Override = core.config.errors?.defaultError;\n const response = Override ? new Override(uuid).render(ctx) : new Fault().render(ctx);\n\n return { uuid, response };\n}\n\nfunction reportFault(denial: Notice, core: Core, fault: ErrorOrigin, uuid: UUID): void {\n logger.error(`${denial.name}: ${uuid}`, denial);\n\n if (fault.interaction) {\n core.bus[PublishDefault]('handledException', {\n denial,\n uuid,\n dispatchId: fault.dispatch.id,\n origin: fault.origin,\n source: buildInteractionSource(fault.interaction)\n });\n } else if (fault.event) {\n core.bus[PublishDefault]('handledException', {\n denial,\n uuid,\n dispatchId: fault.dispatch.id,\n origin: fault.origin,\n source: buildEventSource(fault.event, fault)\n });\n } else {\n // an autocomplete throw has no typed source. unknownException is the only channel left\n core.bus[PublishDefault]('unknownException', {\n uuid,\n dispatchId: fault.dispatch.id,\n error: denial,\n origin: fault.origin,\n ...scalarActors(fault),\n metadata: metadataFor(fault)\n });\n }\n}\n\nfunction causeLine(error: Error): string {\n const { cause } = error;\n if (!Error.isError(cause)) return '';\n const [first] = cause.message.split('\\n');\n return `\\ncaused by ${cause.name}: ${first ?? cause.message}`;\n}\n\nfunction reportRawFault(error: Error, core: Core, fault: ErrorOrigin, uuid: UUID): void {\n const showStack = core.config.errors?.errorStack ?? false;\n if (showStack) logger.error(uuid, error);\n else logger.error(`${uuid} | ${error.message}${causeLine(error)}`);\n\n core.bus[PublishDefault]('unknownException', {\n uuid,\n dispatchId: fault.dispatch.id,\n error,\n origin: fault.origin,\n ...scalarActors(fault),\n metadata: metadataFor(fault)\n });\n}\n\n// the bus payload must stay djs-free\nfunction scalarActors(fault: ErrorOrigin): Pick<SubscriptionData<'unknownException'>, 'guild' | 'user'> {\n return {\n guild: fault.guild ? { id: fault.guild.id, name: fault.guild.name } : undefined,\n user: fault.user ? { id: fault.user.id, username: fault.user.username } : undefined\n };\n}\n\nfunction metadataFor(fault: ErrorOrigin): unknown {\n if (fault.event) return { eventName: fault.event.name, handler: fault.event.handler, args: fault.event.args };\n return fault.metadata;\n}\n\nfunction buildEventSource(event: EventOrigin, fault: ErrorOrigin): EventFaultSource {\n return {\n kind: 'event',\n eventName: event.name,\n handler: event.handler,\n userId: fault.user?.id ?? null,\n guildId: fault.guild?.id ?? null,\n channelId: event.channelId,\n raw: event.args\n };\n}\n\nfunction buildInteractionSource(interaction: Repliables): InteractionFaultSource {\n const command = interaction.isChatInputCommand()\n ? slashRouteOf(interaction)\n : interaction.isContextMenuCommand()\n ? interaction.commandName\n : null;\n const customId =\n interaction.isButton() || interaction.isAnySelectMenu() || interaction.isModalSubmit()\n ? interaction.customId\n : null;\n\n return {\n kind: 'interaction',\n interactionKind: interactionKind(interaction),\n command,\n customId,\n userId: interaction.user.id,\n guildId: interaction.guildId,\n channelId: interaction.channelId,\n interactionId: interaction.id,\n raw: interaction\n };\n}\n\nfunction interactionKind(interaction: Repliables): InteractionFaultSource['interactionKind'] {\n if (interaction.isChatInputCommand()) return 'slash';\n if (interaction.isContextMenuCommand()) return 'context-menu';\n if (interaction.isButton()) return 'button';\n if (interaction.isAnySelectMenu()) return 'select';\n return 'modal';\n}\n","import { Notice, Silence } from '@seedcord/core';\nimport { asError } from '@seedcord/core/internal';\nimport { Logger } from '@seedcord/logger';\nimport { DiscordAPIError } from 'discord.js';\n\nimport { deriveEventActor } from '#miscellaneous/deriveEventActor';\nimport { extractErrorResponse } from '#miscellaneous/extractErrorResponse';\n\nimport type { Core } from '#interfaces/Core';\nimport type { DispatchContext } from '@seedcord/core';\n\nconst logger = new Logger('Faults', { channel: 'errors' });\n\ninterface EventFault {\n readonly eventName: string;\n readonly handlerName: string;\n readonly args: unknown;\n readonly dispatch: DispatchContext;\n}\n\n// a generic event has no reply target\nexport function handleEventFault(caught: unknown, fault: EventFault, core: Core): void {\n const { eventName, handlerName, args, dispatch } = fault;\n if (caught instanceof Silence) {\n if (caught.reason !== undefined && (core.config.errors?.logSilences ?? true)) {\n logger.debug(`Silence: ${caught.reason}`);\n }\n return;\n }\n const error = asError(caught);\n\n const ignore = new Set<number | string>(core.config.errors?.ignoreEventApiCodes ?? []);\n if (error instanceof DiscordAPIError && ignore.has(error.code)) {\n logger.debug(`swallowed api code ${error.code}`);\n return;\n }\n\n if (error instanceof Notice && !error.report) return;\n\n const actor = deriveEventActor(args);\n extractErrorResponse(error, core, {\n event: { name: eventName, handler: handlerName, args, channelId: actor.channelId },\n origin: `event:${eventName}:${handlerName}`,\n dispatch,\n guild: actor.guild,\n user: actor.user\n });\n}\n","import { PublishDefault } from '@seedcord/core/internal';\n\nimport type { Core } from '#interfaces/Core';\nimport type { EventDispatchResult, SubscriptionData } from '@seedcord/core';\nimport type { ClientEvents } from 'discord.js';\n\nexport function reportEventDispatching<Name extends keyof ClientEvents>(\n core: Core,\n dispatchId: string,\n name: Name,\n args: ClientEvents[Name]\n): void {\n // justified: the generic key erases the per-event tuple and args matches name here\n core.bus[PublishDefault]('eventDispatching', { dispatchId, name, args } as SubscriptionData<'eventDispatching'>);\n}\n\n// the interaction side of this is core's reportDispatch\nexport function reportEventDispatched(\n core: Core,\n dispatchId: string,\n name: keyof ClientEvents,\n result: EventDispatchResult,\n startedAt: number\n): void {\n core.bus[PublishDefault]('eventDispatched', {\n dispatchId,\n name,\n outcome: result.outcome,\n handlers: result.handlers.map(({ handler, outcome }) => ({ handler, outcome })),\n durationMs: performance.now() - startedAt\n });\n}\n","import { DispatchContext } from '@seedcord/core';\nimport { HmrModuleHandler } from '@seedcord/core/hmr';\nimport {\n areRoutes,\n asError,\n EventMetadataKey,\n EventMiddlewareMetadataKey,\n eventResultFor,\n MiddlewareRegistry,\n PublishDefault,\n resultFor,\n runAfter,\n runHandlerGates\n} from '@seedcord/core/internal';\nimport { drainInFlight } from '@seedcord/core/node/internal';\nimport { SeedcordErrorCode, paint } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { Logger } from '@seedcord/logger';\nimport { formatFilePath, hasKeys } from '@seedcord/utils';\nimport { traverseDirectory } from '@seedcord/utils/node';\nimport { Envapter } from 'envapt';\n\nimport { eventMiddlewareMetaOf } from '#bDecorators/Middlewares';\nimport { eventGateContext } from '#bot/gates/runGates';\nimport { handleEventFault } from '#bot/handleEventFault';\nimport { reportEventDispatched, reportEventDispatching } from '#bot/reportEventDispatch';\nimport { EventHandler, EventMiddleware } from '#handlers/event';\n\nimport type { RegisterEventMetadataEntry } from '#bDecorators/Events';\nimport type { EventHandlerConstructor, EventMiddlewareConstructor } from '#handlers/constructors';\nimport type { Core } from '#interfaces/Core';\nimport type { HandlerResult } from '@seedcord/core';\nimport type { Initializeable, MiddlewareRegistrationOf } from '@seedcord/core/internal';\nimport type { EventFrequency, HmrAware, HmrUpdateEvent } from '@seedcord/types';\nimport type { ClientEvents } from 'discord.js';\n\nconst eventMiddleware: MiddlewareRegistrationOf<EventMiddlewareConstructor, keyof ClientEvents> = (ctor) => {\n const metadata = eventMiddlewareMetaOf(ctor);\n if (!metadata) return undefined;\n return { priority: metadata.priority, ...(metadata.events && { keys: metadata.events }) };\n};\n\ninterface RegisteredEventHandlerEntry {\n readonly ctor: EventHandlerConstructor;\n readonly frequency: EventFrequency;\n}\n\ntype EventArtifact = string;\n\n/**\n * Interactions route through InteractionDispatcher.\n *\n * @internal\n */\nexport class EventDispatcher implements Initializeable, HmrAware {\n private readonly logger = new Logger('Events', { channel: 'events' });\n private isInitialized = false;\n\n private readonly eventMap = new Map<keyof ClientEvents, RegisteredEventHandlerEntry[]>();\n private readonly middlewares = new MiddlewareRegistry<EventMiddlewareConstructor, keyof ClientEvents>(\n eventMiddleware\n );\n private readonly executedOnceHandlers = new Set<EventHandlerConstructor>();\n private readonly attachedEvents = new Set<keyof ClientEvents>();\n\n private readonly inFlight = new Set<Promise<void>>();\n private draining = false;\n\n // a reload reports on the hmr channel\n private loading = false;\n private readonly loadedHandlers: { name: string; from: string }[] = [];\n private readonly loadedMiddlewares: { name: string; from: string }[] = [];\n\n private readonly hmrHandler?: HmrModuleHandler<\n EventHandlerConstructor,\n EventMiddlewareConstructor,\n EventArtifact[]\n >;\n\n public constructor(protected core: Core) {\n const eventsDir = this.core.config.bot.events.path;\n if (!eventsDir) {\n // unreachable today, guards against a path regression\n throw new SeedcordError(SeedcordErrorCode.CoreControllerPathMissing, ['EventDispatcher', 'events']);\n }\n\n if (!Envapter.isDevelopment && !Envapter.isTest) return;\n\n this.hmrHandler = new HmrModuleHandler({\n handlersDir: eventsDir,\n ...(hasKeys(this.core.config.bot.events, ['middlewares']) && {\n middlewaresDir: this.core.config.bot.events.middlewares\n }),\n isHandler: this.isEventHandlerClass.bind(this),\n isMiddleware: this.isMiddlewareClass.bind(this),\n registerHandler: this.registerHandler.bind(this),\n registerMiddleware: this.registerMiddleware.bind(this),\n unregisterHandler: this.unregisterHandler.bind(this),\n unregisterMiddleware: this.unregisterMiddleware.bind(this),\n getArtifacts: this.getArtifacts.bind(this),\n logger: this.logger\n });\n }\n\n private getArtifacts(ctor: EventHandlerConstructor): EventArtifact[] {\n const events: EventArtifact[] = [];\n for (const [event, handlers] of this.eventMap.entries()) {\n if (handlers.some((h) => h.ctor === ctor)) events.push(event);\n }\n return events;\n }\n\n public async init(): Promise<void> {\n if (this.isInitialized) {\n return;\n }\n this.isInitialized = true;\n\n const handlersDir = this.core.config.bot.events.path;\n if (!handlersDir) {\n return;\n }\n\n const middlewareDir = hasKeys(this.core.config.bot.events, ['middlewares'])\n ? this.core.config.bot.events.middlewares\n : undefined;\n\n this.loading = true;\n this.loadedHandlers.length = 0;\n this.loadedMiddlewares.length = 0;\n try {\n if (middlewareDir) await this.loadMiddlewares(middlewareDir);\n await this.loadHandlers(handlersDir);\n } finally {\n this.loading = false;\n }\n\n this.attachToClient();\n this.reportLoad();\n }\n\n private reportLoad(): void {\n const { utils } = this.logger;\n\n utils.summary(\n 'Loaded',\n { 'event handlers': this.loadedHandlers.length, middlewares: this.loadedMiddlewares.length },\n 'debug'\n );\n\n if (this.loadedMiddlewares.length > 0) {\n utils.block('Loaded event middlewares', utils.entries(this.loadedMiddlewares), 'debug');\n }\n\n const perEvent: Record<string, number> = {};\n for (const [event, handlers] of this.eventMap) perEvent[event] = handlers.length;\n\n utils.block(\n 'Loaded event handlers',\n [...utils.entries(this.loadedHandlers), ...utils.counts(perEvent)],\n 'debug'\n );\n }\n\n private async loadHandlers(dir: string): Promise<void> {\n await traverseDirectory(dir, (fullPath, relativePath, imported) => {\n for (const val of Object.values(imported)) {\n if (!this.isEventHandlerClass(val)) continue;\n this.registerHandler(val, relativePath);\n this.hmrHandler?.trackHandler(fullPath, val);\n }\n });\n }\n\n private async loadMiddlewares(dir: string): Promise<void> {\n await traverseDirectory(dir, (fullPath, relativePath, imported) => {\n for (const val of Object.values(imported)) {\n if (!this.isMiddlewareClass(val)) continue;\n\n this.registerMiddleware(val, relativePath);\n this.hmrHandler?.trackMiddleware(fullPath, val);\n }\n });\n }\n\n /** @internal */\n public async onHmr(event: HmrUpdateEvent): Promise<void> {\n await this.hmrHandler?.handle(event);\n }\n\n private unregisterHandler(handlerClass: EventHandlerConstructor, artifacts?: EventArtifact[]): void {\n const events = artifacts ?? [...this.eventMap.keys()];\n for (const event of events) {\n const handlers = this.eventMap.get(event as keyof ClientEvents);\n if (!handlers) continue;\n const index = handlers.findIndex((h) => h.ctor === handlerClass);\n if (index !== -1) {\n handlers.splice(index, 1);\n if (handlers.length === 0) {\n this.eventMap.delete(event as keyof ClientEvents);\n }\n }\n }\n // leaving executedOnceHandlers alone keeps a rollback-restored ctor spent\n }\n\n private unregisterMiddleware(middlewareCtor: EventMiddlewareConstructor): void {\n this.middlewares.unregister(middlewareCtor);\n }\n\n private registerMiddleware(middlewareCtor: EventMiddlewareConstructor, relativePath: string): void {\n const registration = this.middlewares.register(middlewareCtor);\n if (!registration || !this.loading) return;\n\n // the events are the only place a dev sees that a middleware is scoped\n const scope = registration.keys\n ? `${registration.priority}, ${registration.keys.join(', ')}`\n : registration.priority;\n this.loadedMiddlewares.push({\n name: `${middlewareCtor.name} (${String(scope)})`,\n from: formatFilePath(relativePath)\n });\n }\n\n // a returned value is the throw that stopped the event before any handler ran\n private async runMiddlewares<KeyOfEvents extends keyof ClientEvents>(\n eventName: KeyOfEvents,\n args: ClientEvents[KeyOfEvents],\n dispatch: DispatchContext,\n ran: EventMiddleware[]\n ): Promise<{ caught: unknown } | null> {\n for (const Middleware of this.middlewares.chainFor(eventName)) {\n try {\n const middleware = new Middleware(args, this.core, dispatch, eventName);\n // pushed before the await because a middleware that throws still gets its after()\n ran.push(middleware);\n await middleware.execute();\n } catch (caught) {\n handleEventFault(\n caught,\n { eventName: String(eventName), handlerName: Middleware.name, args, dispatch },\n this.core\n );\n return { caught };\n }\n }\n\n return null;\n }\n\n private isEventHandlerClass(obj: unknown): obj is EventHandlerConstructor {\n if (typeof obj !== 'function') return false;\n return obj.prototype instanceof EventHandler && Reflect.hasMetadata(EventMetadataKey, obj);\n }\n\n private isMiddlewareClass(obj: unknown): obj is EventMiddlewareConstructor {\n if (typeof obj !== 'function') return false;\n return obj.prototype instanceof EventMiddleware && Reflect.hasMetadata(EventMiddlewareMetadataKey, obj);\n }\n\n private registerHandler(handlerClass: EventHandlerConstructor, relativePath: string): void {\n const raw = Reflect.getMetadata(EventMetadataKey, handlerClass) as unknown;\n\n const register = (key: keyof ClientEvents, frequency: EventFrequency): void => {\n let handlers = this.eventMap.get(key);\n if (!handlers) {\n handlers = [];\n this.eventMap.set(key, handlers);\n }\n\n handlers.push({\n ctor: handlerClass,\n frequency\n });\n\n // a post-init (hmr) registration can add an event with no client listener yet\n if (this.isInitialized && !this.attachedEvents.has(key)) {\n this.attachListener(key);\n }\n };\n\n if (Array.isArray(raw)) {\n for (const entry of raw as RegisterEventMetadataEntry<keyof ClientEvents>[]) {\n register(entry.event, entry.frequency);\n }\n } else {\n const names = areRoutes(raw) ? raw : typeof raw === 'string' ? [raw] : [];\n\n for (const name of names) {\n register(name as keyof ClientEvents, 'on');\n }\n }\n\n const from = formatFilePath(relativePath);\n if (this.loading) this.loadedHandlers.push({ name: handlerClass.name, from });\n }\n\n private attachToClient(): void {\n for (const [eventName] of this.eventMap) {\n this.attachListener(eventName);\n }\n }\n\n private attachListener(eventName: keyof ClientEvents): void {\n if (this.attachedEvents.has(eventName)) return;\n this.attachedEvents.add(eventName);\n\n const handlerEntries = this.eventMap.get(eventName);\n this.logger.debug(\n `Attaching ${paint.sky.bold(eventName)} to the client with ${paint.mute(handlerEntries?.length ?? 0)} handler(s)`\n );\n\n this.core.bot.client.on(eventName, (...args: ClientEvents[typeof eventName]) => {\n if (this.draining) return;\n const run = this.processEvent(eventName, args).catch((caught: unknown) => {\n const error = asError(caught);\n this.logger.error(`[${paint.coral.bold('UNHANDLED ERROR AT ROOT')}] ${error.name}`, error.stack);\n this.core.bus[PublishDefault]('unhandledEventError', { error });\n });\n this.inFlight.add(run);\n void run.finally(() => this.inFlight.delete(run));\n });\n }\n\n public stopAccepting(): void {\n this.draining = true;\n }\n\n public drain(timeoutMs: number): Promise<void> {\n return drainInFlight(this.inFlight, timeoutMs, this.logger, 'Events');\n }\n\n private async processEvent<KeyOfEvents extends keyof ClientEvents>(\n eventName: KeyOfEvents,\n args: ClientEvents[KeyOfEvents]\n ): Promise<void> {\n const startedAt = performance.now();\n const handlerEntries = this.eventMap.get(eventName);\n if (!handlerEntries || handlerEntries.length === 0) return;\n\n const handlersToExecute = handlerEntries.filter(\n (entry) => entry.frequency !== 'once' || !this.executedOnceHandlers.has(entry.ctor)\n );\n\n if (handlersToExecute.length === 0) return;\n\n const dispatch = new DispatchContext(`event:${String(eventName)}`);\n reportEventDispatching(this.core, dispatch.id, eventName, args);\n\n const ran: EventMiddleware[] = [];\n const handlers: HandlerResult[] = [];\n let stopped: { caught: unknown } | null = null;\n\n try {\n stopped = await this.runMiddlewares(eventName, args, dispatch, ran);\n if (stopped) return;\n\n for (const entry of handlersToExecute) {\n // marked spent before running so a rethrow can't re-fire it\n if (entry.frequency === 'once') {\n // a concurrent fire could have claimed it during the runMiddlewares await\n if (this.executedOnceHandlers.has(entry.ctor)) continue;\n this.executedOnceHandlers.add(entry.ctor);\n }\n\n handlers.push(await this.processHandler(eventName, entry.ctor, args, dispatch));\n }\n } finally {\n const result = eventResultFor(stopped, handlers);\n reportEventDispatched(this.core, dispatch.id, eventName, result, startedAt);\n await runAfter(ran, result, this.logger);\n }\n }\n\n private async processHandler<KeyOfEvents extends keyof ClientEvents>(\n eventName: KeyOfEvents,\n Ctor: EventHandlerConstructor,\n args: ClientEvents[KeyOfEvents],\n dispatch: DispatchContext\n ): Promise<HandlerResult> {\n try {\n this.logger.debug(`Processing ${paint.sky.bold(eventName)} with ${paint.mute(Ctor.name)}`);\n const handler = new Ctor(args, this.core, dispatch, eventName);\n const eventCtx = eventGateContext(eventName, args, this.core, dispatch);\n await runHandlerGates(Ctor, eventCtx);\n await handler.execute();\n return { handler: Ctor.name, outcome: 'handled' };\n } catch (caught) {\n handleEventFault(\n caught,\n { eventName: String(eventName), handlerName: Ctor.name, args, dispatch },\n this.core\n );\n return { handler: Ctor.name, ...resultFor(caught) };\n }\n }\n}\n","import { InteractionHandler } from '#handlers/interaction/InteractionHandler';\n\nimport type { Repliables } from '#src/handlers/interactionTypes';\n\nexport class UnhandledRepliable extends InteractionHandler<Repliables> {\n async execute(): Promise<void> {\n await this.reply('Feature not implemented yet.');\n }\n}\n","import { AutocompleteHandler } from '#handlers/interaction/AutocompleteHandler';\n\nimport type { SlashRegistry } from '@seedcord/core';\nimport type { CacheType } from 'discord.js';\n\n// eslint-disable-next-line @seedcord/interaction-handler-missing-route -- the dispatcher's autocomplete fallback, never registered\nexport class UnhandledAutocomplete extends AutocompleteHandler<keyof SlashRegistry, CacheType> {\n async execute(): Promise<void> {\n await this.respond([]);\n }\n}\n","import { RESTJSONErrorCodes } from 'discord.js';\n\n/**\n * Discord API error codes that mean a dead end on an interaction, a dead token, a double ack, or a gone\n * message. Nothing to show the user and no bug to report, so the boundary's fault-card send drops them.\n *\n * @internal\n */\nexport const HARMLESS_API_CODES: ReadonlySet<number | string> = new Set([\n RESTJSONErrorCodes.UnknownInteraction,\n RESTJSONErrorCodes.InteractionHasAlreadyBeenAcknowledged,\n RESTJSONErrorCodes.UnknownMessage\n]);\n","import { Notice, Silence } from '@seedcord/core';\nimport { asError, reportedWrite } from '@seedcord/core/internal';\nimport { Logger } from '@seedcord/logger';\nimport { DiscordAPIError } from 'discord.js';\n\nimport { ReplySender } from '#bot/ReplySender';\nimport { extractErrorResponse } from '#miscellaneous/extractErrorResponse';\n\nimport { HARMLESS_API_CODES } from './harmlessApiCodes';\n\nimport type { Core } from '#interfaces/Core';\nimport type { ValidInteractionTypes } from '#src/handlers/interactionTypes';\nimport type { DispatchContext } from '@seedcord/core';\nimport type { ReplyResponse } from '@seedcord/types';\nimport type { AutocompleteInteraction } from 'discord.js';\n\nconst logger = new Logger('Faults', { channel: 'errors' });\n\nexport async function handleInteractionFault(\n caught: unknown,\n interaction: ValidInteractionTypes,\n core: Core,\n dispatch: DispatchContext,\n sender?: ReplySender\n): Promise<void> {\n const { routeId } = dispatch;\n if (caught instanceof Silence) {\n if (caught.reason !== undefined && (core.config.errors?.logSilences ?? true)) {\n logger.debug(`Silence: ${caught.reason}`);\n }\n return;\n }\n const error = asError(caught);\n\n const ignore = new Set<number | string>(core.config.errors?.ignoreApiCodes ?? []);\n if (error instanceof DiscordAPIError && ignore.has(error.code)) {\n logger.debug(`swallowed api code ${error.code}`);\n return;\n }\n\n // discord does not accept a message on an autocomplete. the fault is only reported.\n if (interaction.isAutocomplete()) {\n extractErrorResponse(error, core, {\n origin: routeId,\n dispatch,\n guild: interaction.guild,\n user: interaction.user,\n metadata: interaction\n });\n // empty choices clear the client's loading spinner\n await sendEmptyChoices(interaction, core, dispatch);\n return;\n }\n\n const { response } = extractErrorResponse(error, core, {\n interaction,\n origin: routeId,\n dispatch,\n guild: interaction.guild,\n user: interaction.user,\n metadata: interaction\n });\n // the handler's own sender carries its ack state. a middleware throw arrives without one\n const liveSender = sender ?? new ReplySender(interaction, dispatch, core.bus);\n await sendGuarded(liveSender, response, error instanceof Notice ? error.ephemeral : true);\n}\n\nasync function sendEmptyChoices(\n interaction: AutocompleteInteraction,\n core: Core,\n dispatch: DispatchContext\n): Promise<void> {\n const telemetry = { bus: core.bus, dispatch, interactionId: interaction.id };\n try {\n await reportedWrite(telemetry, 'respond', () => interaction.respond([]));\n } catch (error) {\n logger.debug(`autocomplete empty-choices send failed: ${String(error)}`);\n }\n}\n\n// only this send swallows the harmless codes. a handler's own write still reports them\nasync function sendGuarded(sender: ReplySender, response: ReplyResponse, ephemeral: boolean): Promise<void> {\n try {\n await sender.send(response, { ephemeral });\n } catch (error) {\n if (error instanceof DiscordAPIError && HARMLESS_API_CODES.has(error.code)) {\n logger.debug(`reply send hit harmless code ${error.code}`);\n return;\n }\n logger.error('reply send failed', error);\n }\n}\n","/* eslint-disable max-lines -- one handler method per interaction type keeps the router in one file */\nimport { DispatchContext, InteractionKind } from '@seedcord/core';\nimport { HmrModuleHandler } from '@seedcord/core/hmr';\nimport {\n InteractionMetadataKey,\n interactionRoutesOf,\n asError,\n outcomeFor,\n queuedMsFor,\n reportDispatch,\n interactionMiddleware,\n InteractionMiddlewareMetadataKey,\n MiddlewareRegistry,\n PublishDefault,\n resultFor,\n runAfter,\n runHandlerGates,\n slowGateMonitor\n} from '@seedcord/core/internal';\nimport { drainInFlight } from '@seedcord/core/node/internal';\nimport { prefixOf } from '@seedcord/custom-id';\nimport { SeedcordErrorCode, paint } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { Logger } from '@seedcord/logger';\nimport { formatFilePath, hasKeys } from '@seedcord/utils';\nimport { traverseDirectory } from '@seedcord/utils/node';\nimport { Events } from 'discord.js';\nimport { Envapter } from 'envapt';\n\nimport { CONFIRM_DEF } from '#bot/confirm/reserved';\nimport { UnhandledAutocomplete, UnhandledRepliable } from '#bot/defaults';\nimport { interactionGateContext } from '#bot/gates/runGates';\nimport { handleInteractionFault } from '#bot/handleInteractionFault';\nimport { slashRouteOf } from '#bUtilities/miscellaneous/slashRouteOf';\nimport { AutocompleteHandler, InteractionMiddleware } from '#handlers/interaction';\nimport { InteractionHandler } from '#handlers/interaction/InteractionHandler';\nimport { RepliableHandler } from '#handlers/RepliableHandler';\n\nimport type { ReplySender } from '#bot/ReplySender';\nimport type { HandlerConstructor, InteractionMiddlewareConstructor } from '#handlers/constructors';\nimport type { InteractionOf } from '#handlers/interaction/middlewareKinds';\nimport type { Core } from '#interfaces/Core';\nimport type { Repliables, ValidInteractionTypes } from '#src/handlers/interactionTypes';\nimport type { DispatchOutcome, DispatchResult, MiddlewareKind } from '@seedcord/core';\nimport type { Initializeable, ContextMenuLeaves } from '@seedcord/core/internal';\nimport type { CustomIdMatcher, HmrAware, HmrUpdateEvent } from '@seedcord/types';\nimport type {\n AutocompleteInteraction,\n ButtonInteraction,\n ChannelSelectMenuInteraction,\n ChatInputCommandInteraction,\n Interaction,\n MentionableSelectMenuInteraction,\n MessageContextMenuCommandInteraction,\n ModalSubmitInteraction,\n RoleSelectMenuInteraction,\n StringSelectMenuInteraction,\n UserContextMenuCommandInteraction,\n UserSelectMenuInteraction\n} from 'discord.js';\n\ninterface InteractionArtifact {\n routeType: InteractionKind;\n routes: string[];\n}\n\ninterface DispatchedHandler {\n execute(): Promise<void>;\n}\n\ninterface DispatchReportRow {\n readonly interaction: Interaction;\n readonly kind: InteractionKind;\n readonly fallback: boolean;\n readonly startedAt: number;\n readonly queuedMs: number;\n readonly dispatchId: string;\n readonly routeId: string;\n}\n\ninterface BeforeHandler {\n readonly HandlerCtor: HandlerConstructor;\n readonly kind: InteractionKind;\n readonly interaction: Interaction;\n readonly dispatch: DispatchContext;\n readonly sender: ReplySender | undefined;\n readonly ran: InteractionMiddleware[];\n readonly declaredRoute: string | undefined;\n}\n\nexport class InteractionDispatcher implements Initializeable, HmrAware {\n private readonly logger = new Logger('Interactions', { channel: 'interactions' });\n private isInitialized = false;\n\n private readonly maps: Record<InteractionKind, Map<string, HandlerConstructor>> = {\n [InteractionKind.Slash]: new Map(),\n [InteractionKind.Button]: new Map(),\n [InteractionKind.Modal]: 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.MessageContextMenu]: new Map(),\n [InteractionKind.UserContextMenu]: new Map(),\n [InteractionKind.Autocomplete]: new Map()\n };\n\n private readonly handlerFiles = new Map<HandlerConstructor, string>();\n\n private readonly keysToIgnore = new Set<CustomIdMatcher>();\n private readonly middlewares = new MiddlewareRegistry<InteractionMiddlewareConstructor>(interactionMiddleware);\n\n private readonly inFlight = new Set<Promise<void>>();\n private draining = false;\n\n // a reload reports on the hmr channel\n private loading = false;\n private readonly loadedHandlers: { name: string; from: string }[] = [];\n private readonly loadedMiddlewares: { name: string; from: string }[] = [];\n\n private readonly hmrHandler?: HmrModuleHandler<\n HandlerConstructor,\n InteractionMiddlewareConstructor,\n InteractionArtifact[]\n >;\n\n constructor(protected core: Core) {\n const ignoredKeysFromConfig = hasKeys(this.core.config.bot.interactions, ['ignoreCustomIds'])\n ? this.core.config.bot.interactions.ignoreCustomIds\n : undefined;\n if (ignoredKeysFromConfig) {\n for (const ignoredKey of ignoredKeysFromConfig) this.keysToIgnore.add(ignoredKey);\n }\n\n // the in-process getConfirmation() collector consumes these clicks, so the global router would double-ack them\n this.keysToIgnore.add(CONFIRM_DEF);\n\n const interactionsDir = this.core.config.bot.interactions.path;\n if (!interactionsDir) {\n throw new SeedcordError(SeedcordErrorCode.CoreControllerPathMissing, [\n 'InteractionDispatcher',\n 'interactions'\n ]);\n }\n\n if (!Envapter.isDevelopment && !Envapter.isTest) return;\n this.hmrHandler = new HmrModuleHandler({\n handlersDir: interactionsDir,\n ...(hasKeys(this.core.config.bot.interactions, ['middlewares']) &&\n this.core.config.bot.interactions.middlewares && {\n middlewaresDir: this.core.config.bot.interactions.middlewares\n }),\n isHandler: this.isHandlerClass.bind(this),\n isMiddleware: this.isMiddlewareClass.bind(this),\n registerHandler: this.registerHandler.bind(this),\n registerMiddleware: this.registerMiddleware.bind(this),\n unregisterHandler: this.unregisterHandler.bind(this),\n unregisterMiddleware: this.unregisterMiddleware.bind(this),\n getArtifacts: this.getArtifacts.bind(this),\n logger: this.logger\n });\n }\n\n public warnUnhandledRoutes(commandLeaves: Iterable<string>): void {\n for (const route of commandLeaves) {\n if (!this.maps[InteractionKind.Slash].has(route)) {\n this.logger.warn(\n `Slash route ${paint.sky.bold(route)} has no registered ${paint.bold('@SlashRoute')} handler.`\n );\n }\n }\n }\n\n public warnUnhandledContextMenuRoutes(leaves: ContextMenuLeaves): void {\n for (const name of leaves.user) {\n if (!this.maps[InteractionKind.UserContextMenu].has(name)) {\n this.logger.warn(\n `User context menu ${paint.sky.bold(name)} has no registered ${paint.bold('@ContextMenuRoute')} handler.`\n );\n }\n }\n for (const name of leaves.message) {\n if (!this.maps[InteractionKind.MessageContextMenu].has(name)) {\n this.logger.warn(\n `Message context menu ${paint.sky.bold(name)} has no registered ${paint.bold('@ContextMenuRoute')} handler.`\n );\n }\n }\n }\n\n private getArtifacts(handlerClass: HandlerConstructor): InteractionArtifact[] {\n return interactionRoutesOf(handlerClass).map(([routeType, routes]) => ({ routeType, routes }));\n }\n\n public async init(): Promise<void> {\n if (this.isInitialized) return;\n\n this.isInitialized = true;\n\n const handlersDir = this.core.config.bot.interactions.path;\n // the constructor already threw on this\n if (!handlersDir) return;\n\n const middlewareDir = hasKeys(this.core.config.bot.interactions, ['middlewares'])\n ? this.core.config.bot.interactions.middlewares\n : undefined;\n\n this.loading = true;\n this.loadedHandlers.length = 0;\n this.loadedMiddlewares.length = 0;\n try {\n if (middlewareDir) await this.loadMiddlewares(middlewareDir);\n await this.loadHandlers(handlersDir);\n } finally {\n this.loading = false;\n }\n\n this.attachToClient();\n this.reportLoad();\n }\n\n private reportLoad(): void {\n const { utils } = this.logger;\n\n utils.summary(\n 'Loaded',\n { 'interaction handlers': this.loadedHandlers.length, middlewares: this.loadedMiddlewares.length },\n 'debug'\n );\n\n if (this.loadedMiddlewares.length > 0) {\n utils.block('Loaded middlewares', utils.entries(this.loadedMiddlewares), 'debug');\n }\n\n utils.block(\n 'Loaded interaction handlers',\n [\n ...utils.entries(this.loadedHandlers),\n ...utils.counts({\n slash: this.maps[InteractionKind.Slash].size,\n buttons: this.maps[InteractionKind.Button].size,\n modals: this.maps[InteractionKind.Modal].size,\n 'string selects': this.maps[InteractionKind.StringMenu].size,\n 'user selects': this.maps[InteractionKind.UserMenu].size,\n 'role selects': this.maps[InteractionKind.RoleMenu].size,\n 'channel selects': this.maps[InteractionKind.ChannelMenu].size,\n 'mentionable selects': this.maps[InteractionKind.MentionableMenu].size,\n 'message menus': this.maps[InteractionKind.MessageContextMenu].size,\n 'user menus': this.maps[InteractionKind.UserContextMenu].size,\n autocomplete: this.maps[InteractionKind.Autocomplete].size\n })\n ],\n 'debug'\n );\n }\n\n private async loadHandlers(dir: string): Promise<void> {\n await traverseDirectory(dir, (fullPath, relativePath, imported) => {\n for (const val of Object.values(imported)) {\n if (!this.isHandlerClass(val)) continue;\n this.registerHandler(val, relativePath);\n this.hmrHandler?.trackHandler(fullPath, val);\n }\n });\n }\n\n private async loadMiddlewares(dir: string): Promise<void> {\n await traverseDirectory(dir, (fullPath, relativePath, imported) => {\n for (const val of Object.values(imported)) {\n if (!this.isMiddlewareClass(val)) continue;\n\n this.registerMiddleware(val, relativePath);\n this.hmrHandler?.trackMiddleware(fullPath, val);\n }\n });\n }\n\n private registerMiddleware(middlewareCtor: InteractionMiddlewareConstructor, relativePath: string): void {\n const metadata = this.middlewares.register(middlewareCtor);\n if (!metadata) return;\n\n if (this.loading) {\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: `${middlewareCtor.name} (${String(scope)})`,\n from: formatFilePath(relativePath)\n });\n }\n }\n\n private isHandlerClass(obj: unknown): obj is HandlerConstructor {\n if (typeof obj !== 'function') return false;\n return (\n (obj.prototype instanceof InteractionHandler && Reflect.hasMetadata(InteractionMetadataKey, obj)) ||\n (obj.prototype instanceof AutocompleteHandler && Reflect.hasMetadata(InteractionMetadataKey, obj))\n );\n }\n\n private isMiddlewareClass(obj: unknown): obj is InteractionMiddlewareConstructor {\n if (typeof obj !== 'function') return false;\n return (\n obj.prototype instanceof InteractionMiddleware && Reflect.hasMetadata(InteractionMiddlewareMetadataKey, obj)\n );\n }\n\n private registerHandler(handlerClass: HandlerConstructor, relativePath: string): void {\n const from = formatFilePath(relativePath);\n // a partial registration would orphan routes and break hmr rollback\n const writes: { kind: InteractionKind; route: string }[] = [];\n\n for (const [kind, routes] of interactionRoutesOf(handlerClass)) {\n for (const route of routes) {\n const existing = this.maps[kind].get(route);\n // a different class on the same route would silently shadow (last write wins)\n if (existing && existing !== handlerClass) {\n throw new SeedcordError(SeedcordErrorCode.InteractionDuplicateRoute, [\n `${kind}:${route}`,\n // a stale hmr artifact list can leave a class in a route map after its entry here is gone\n `${existing.name} (${this.handlerFiles.get(existing) ?? 'unknown file'})`,\n `${handlerClass.name} (${from})`\n ]);\n }\n writes.push({ kind, route });\n }\n }\n\n if (writes.length === 0) return;\n for (const { kind, route } of writes) this.maps[kind].set(route, handlerClass);\n this.handlerFiles.set(handlerClass, from);\n\n if (this.loading) this.loadedHandlers.push({ name: handlerClass.name, from });\n }\n\n public async onHmr(event: HmrUpdateEvent): Promise<void> {\n await this.hmrHandler?.handle(event);\n }\n\n private unregisterHandler(handlerClass: HandlerConstructor, artifacts?: InteractionArtifact[]): void {\n this.handlerFiles.delete(handlerClass);\n for (const { routeType, routes } of artifacts ?? this.getArtifacts(handlerClass)) {\n for (const route of routes) this.maps[routeType].delete(route);\n }\n }\n\n private unregisterMiddleware(middlewareCtor: InteractionMiddlewareConstructor): void {\n this.middlewares.unregister(middlewareCtor);\n }\n\n private attachToClient(): void {\n this.core.bot.client.on(Events.InteractionCreate, (interaction) => {\n if (this.draining) return;\n this.core.bus[PublishDefault]('anyInteraction', { interaction });\n const run = this.handleInteraction(interaction).catch((caught: unknown) => {\n const error = asError(caught);\n this.logger.error(`[${paint.coral.bold('UNHANDLED ERROR AT ROOT')}] ${error.name}`, error.stack);\n this.core.bus[PublishDefault]('unhandledInteractionError', { error });\n });\n this.inFlight.add(run);\n void run.finally(() => this.inFlight.delete(run));\n });\n }\n\n public stopAccepting(): void {\n this.draining = true;\n }\n\n public drain(timeoutMs: number): Promise<void> {\n return drainInFlight(this.inFlight, timeoutMs, this.logger, 'Interactions');\n }\n\n private async handleCustomIdInteraction<TInteraction extends Interaction & { customId: string }>(\n interaction: TInteraction,\n kind: InteractionKind\n ): Promise<void> {\n if ([...this.keysToIgnore].some((matcher) => matcher.owns(interaction.customId))) return;\n\n // the stable prefix (the routeKey minus its shape hash) routes an older-shape wire to its handler\n const prefix = prefixOf(interaction.customId);\n // no route matches an empty prefix. the unhandled default answers it like http does\n if (!prefix)\n this.logger.warn(`${paint.sky.bold(kind)} has invalid customId: ${paint.mute(interaction.customId)}`);\n\n await this.processInteraction(interaction, kind, () => prefix);\n }\n\n private async processInteraction<TInteraction extends Interaction>(\n interaction: TInteraction,\n kind: InteractionKind,\n extractKey: (i: TInteraction) => string,\n fallback: HandlerConstructor = UnhandledRepliable\n ): Promise<void> {\n const key = extractKey(interaction);\n const startedAt = performance.now();\n const queuedMs = queuedMsFor(interaction.id);\n const matched = this.maps[kind].get(key);\n\n const HandlerCtor = matched ?? fallback;\n // an empty key means a customId seedcord never minted\n const dispatch = new DispatchContext(`${kind}:${key || 'unrouted'}`);\n const report = this.reporterFor({\n interaction,\n kind,\n fallback: !matched,\n startedAt,\n queuedMs,\n dispatchId: dispatch.id,\n routeId: dispatch.routeId\n });\n\n // outside the try so the fault boundary keeps the handler's ack state\n let sender: ReplySender | undefined;\n const ran: InteractionMiddleware[] = [];\n let result: DispatchResult = { outcome: 'handled' };\n try {\n const handler = this.buildHandler(HandlerCtor, interaction as Repliables, dispatch, key, !matched);\n if (handler instanceof RepliableHandler) sender = handler.sender;\n\n const refusal = await this.refusalBeforeHandler({\n HandlerCtor,\n kind,\n interaction,\n dispatch,\n sender,\n ran,\n declaredRoute: matched ? dispatch.routeId : undefined\n });\n if (refusal) {\n result = resultFor(refusal.caught);\n await this.answer(refusal.caught, interaction as ValidInteractionTypes, dispatch, sender, report);\n return;\n }\n await handler.execute();\n report('handled');\n } catch (caught) {\n // a refusal already labelled the dispatch. a throw from answering it must not relabel.\n if (result.outcome === 'handled') result = resultFor(caught);\n await this.answer(caught, interaction as ValidInteractionTypes, dispatch, sender, report);\n } finally {\n await runAfter(ran, result, this.logger);\n }\n }\n\n private async answer(\n caught: unknown,\n interaction: ValidInteractionTypes,\n dispatch: DispatchContext,\n sender: ReplySender | undefined,\n report: (outcome: DispatchOutcome) => void\n ): Promise<void> {\n try {\n await handleInteractionFault(caught, interaction, this.core, dispatch, sender);\n } finally {\n report(outcomeFor(caught));\n }\n }\n\n private buildHandler(\n HandlerCtor: HandlerConstructor,\n interaction: Repliables,\n dispatch: DispatchContext,\n key: string,\n isFallback: boolean\n ): DispatchedHandler {\n if (isFallback) {\n this.logger.warn(`No handler found for key ${paint.sky.bold(key)}. Falling back to ${HandlerCtor.name}.`);\n }\n this.logger.debug(`Processing ${paint.sky.bold(key)} with ${paint.mute(HandlerCtor.name)}`);\n // in a union of both handler bases, the event parameter is never. the maps pair each kind with its class.\n return new HandlerCtor(interaction as never, this.core, dispatch);\n }\n\n // answering a refusal can throw into the catch and report twice\n private reporterFor(row: DispatchReportRow): (outcome: DispatchOutcome) => void {\n let reported = false;\n return (outcome) => {\n if (reported) return;\n reported = true;\n reportDispatch(this.core.bus, {\n dispatchId: row.dispatchId,\n routeId: row.routeId,\n interactionId: row.interaction.id,\n kind: row.kind,\n outcome,\n startedAt: row.startedAt,\n fallback: row.fallback,\n userId: row.interaction.user.id,\n guildId: row.interaction.guildId,\n queuedMs: row.queuedMs\n });\n };\n }\n\n // a returned value is the throw that stops the dispatch before the handler runs\n private async refusalBeforeHandler(step: BeforeHandler): Promise<{ caught: unknown } | null> {\n const { HandlerCtor, kind, interaction, dispatch, sender, ran, declaredRoute } = step;\n\n if (kind !== InteractionKind.Autocomplete && sender) {\n try {\n await this.runMiddlewares(kind, interaction as Repliables, dispatch, sender, ran);\n } catch (caught) {\n return { caught };\n }\n }\n\n // @Gated rejects autocomplete at compile time, since it has no reply target. this is the backstop\n if (interaction.isAutocomplete()) return null;\n return this.gateRefusal(HandlerCtor, interaction as Repliables, dispatch, declaredRoute);\n }\n\n private async runMiddlewares(\n kind: MiddlewareKind,\n interaction: Repliables,\n dispatch: DispatchContext,\n sender: ReplySender,\n ran: InteractionMiddleware[]\n ): Promise<void> {\n for (const Middleware of this.middlewares.chainFor(kind)) {\n // chainFor picked this kind. the interaction is the one the class declares.\n const event = interaction as InteractionOf<MiddlewareKind>;\n const middleware = new Middleware(event, this.core, dispatch, sender);\n // pushed before the await because a middleware that throws still gets its after()\n ran.push(middleware);\n await middleware.execute();\n }\n }\n\n private async gateRefusal(\n HandlerCtor: HandlerConstructor,\n interaction: Repliables,\n dispatch: DispatchContext,\n declaredRoute: string | undefined\n ): Promise<{ caught: unknown } | null> {\n const monitor = slowGateMonitor();\n try {\n await runHandlerGates(\n HandlerCtor,\n interactionGateContext(interaction, this.core, dispatch),\n declaredRoute,\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(declaredRoute ?? null);\n }\n }\n\n private async handleInteraction(interaction: Interaction): Promise<void> {\n switch (true) {\n case interaction.isChatInputCommand(): {\n await this.handleSlashCommand(interaction);\n break;\n }\n case interaction.isButton(): {\n await this.handleButton(interaction);\n break;\n }\n case interaction.isModalSubmit(): {\n await this.handleModal(interaction);\n break;\n }\n case interaction.isStringSelectMenu(): {\n await this.handleStringSelectMenu(interaction);\n break;\n }\n case interaction.isUserSelectMenu(): {\n await this.handleUserSelectMenu(interaction);\n break;\n }\n case interaction.isRoleSelectMenu(): {\n await this.handleRoleSelectMenu(interaction);\n break;\n }\n case interaction.isChannelSelectMenu(): {\n await this.handleChannelSelectMenu(interaction);\n break;\n }\n case interaction.isMentionableSelectMenu(): {\n await this.handleMentionableSelectMenu(interaction);\n break;\n }\n case interaction.isMessageContextMenuCommand(): {\n await this.handleMessageContextMenu(interaction);\n break;\n }\n case interaction.isUserContextMenuCommand(): {\n await this.handleUserContextMenu(interaction);\n break;\n }\n case interaction.isAutocomplete(): {\n await this.handleAutocomplete(interaction);\n break;\n }\n default: {\n this.logger.warn(`Unhandled interaction type: ${interaction.type}`);\n break;\n }\n }\n }\n\n private async handleSlashCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n const route = slashRouteOf(interaction);\n await this.processInteraction(interaction, InteractionKind.Slash, () => route);\n }\n\n private async handleButton(interaction: ButtonInteraction): Promise<void> {\n await this.handleCustomIdInteraction(interaction, InteractionKind.Button);\n }\n\n private async handleModal(interaction: ModalSubmitInteraction): Promise<void> {\n await this.handleCustomIdInteraction(interaction, InteractionKind.Modal);\n }\n\n private async handleStringSelectMenu(interaction: StringSelectMenuInteraction): Promise<void> {\n await this.handleCustomIdInteraction(interaction, InteractionKind.StringMenu);\n }\n\n private async handleUserSelectMenu(interaction: UserSelectMenuInteraction): Promise<void> {\n await this.handleCustomIdInteraction(interaction, InteractionKind.UserMenu);\n }\n\n private async handleRoleSelectMenu(interaction: RoleSelectMenuInteraction): Promise<void> {\n await this.handleCustomIdInteraction(interaction, InteractionKind.RoleMenu);\n }\n\n private async handleChannelSelectMenu(interaction: ChannelSelectMenuInteraction): Promise<void> {\n await this.handleCustomIdInteraction(interaction, InteractionKind.ChannelMenu);\n }\n\n private async handleMentionableSelectMenu(interaction: MentionableSelectMenuInteraction): Promise<void> {\n await this.handleCustomIdInteraction(interaction, InteractionKind.MentionableMenu);\n }\n\n private async handleMessageContextMenu(interaction: MessageContextMenuCommandInteraction): Promise<void> {\n await this.processInteraction(interaction, InteractionKind.MessageContextMenu, () => interaction.commandName);\n }\n\n private async handleUserContextMenu(interaction: UserContextMenuCommandInteraction): Promise<void> {\n await this.processInteraction(interaction, InteractionKind.UserContextMenu, () => interaction.commandName);\n }\n\n private async handleAutocomplete(interaction: AutocompleteInteraction): Promise<void> {\n const route = slashRouteOf(interaction);\n await this.processInteraction(interaction, InteractionKind.Autocomplete, () => route, UnhandledAutocomplete);\n }\n}\n","import { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { GatewayIntentBits, InteractionContextType, IntentsBitField } from 'discord.js';\n\nimport type { BitFieldResolvable, GatewayIntentsString } from 'discord.js';\n\ninterface DeployableCommand {\n readonly name: string;\n toJSON(): { contexts?: InteractionContextType[] | undefined };\n}\n\n// discord reads a command with no contexts as reachable from all three\nfunction reachesGuilds(command: DeployableCommand): boolean {\n const contexts = command.toJSON().contexts;\n if (!contexts || contexts.length === 0) return true;\n return contexts.includes(InteractionContextType.Guild);\n}\n\n// djs resolves interaction.guild out of a cache that stays empty without the Guilds intent\nexport function assertGuildsIntent(\n intents: BitFieldResolvable<GatewayIntentsString, number>,\n commands: readonly DeployableCommand[]\n): void {\n if ((IntentsBitField.resolve(intents) & GatewayIntentBits.Guilds) !== 0) return;\n\n const needing = commands.filter((command) => reachesGuilds(command)).map((command) => command.name);\n if (needing.length === 0) return;\n\n throw new SeedcordError(SeedcordErrorCode.MissingGuildsIntent, [needing.join(', ')]);\n}\n","import { CommandRegistry, DRAIN_TASK_TIMEOUT_MS, DRAIN_WINDOW_MS, ShutdownPhase } from '@seedcord/core/node/internal';\nimport { SeedcordErrorCode, paint } from '@seedcord/errors';\nimport { SeedcordError, validateDiscordToken } from '@seedcord/errors/internal';\nimport { Logger } from '@seedcord/logger';\nimport { Client, Events } from 'discord.js';\nimport { Envapt } from 'envapt/legacy';\n\nimport { EventDispatcher } from '#bControllers/EventDispatcher';\nimport { InteractionDispatcher } from '#bControllers/InteractionDispatcher';\nimport { assertGuildsIntent } from '#miscellaneous/assertGuildsIntent';\n\nimport { EmojiInjector } from './injectors/EmojiInjector';\n\nimport type { Core } from '#interfaces/Core';\nimport type { HmrAware, HmrUpdateEvent } from '@seedcord/types';\nimport type { BitFieldResolvable, GatewayIntentsString } from 'discord.js';\n\nconst UNBIND_TIMEOUT_MS = 2000;\nconst LOGOUT_TIMEOUT_MS = 2000;\n\nconst loggerSlot = Symbol('seedcord:bot:logger');\nconst initSlot = Symbol('seedcord:bot:init');\nconst controllersSlot = Symbol('seedcord:bot:controllers');\n\ninterface Controllers {\n readonly interactions?: InteractionDispatcher | undefined;\n readonly events?: EventDispatcher | undefined;\n readonly commandRegistry?: CommandRegistry | undefined;\n}\n\n/**\n * The Discord client and its controllers. Access it through `core.bot`.\n */\nexport class Bot implements HmrAware {\n @Envapt<string>('DISCORD_BOT_TOKEN', {\n converter: (raw) => validateDiscordToken(raw)\n })\n declare public readonly botToken: string;\n\n readonly #logger = new Logger('Bot', { channel: 'bot' });\n\n /** @internal */\n readonly [loggerSlot]: Logger = this.#logger;\n #isInitialized = false;\n\n readonly #intents: BitFieldResolvable<GatewayIntentsString, number>;\n readonly #client: Client;\n readonly #emojiInjector: EmojiInjector;\n readonly #interactions?: InteractionDispatcher;\n readonly #events?: EventDispatcher;\n readonly #commandRegistry?: CommandRegistry;\n\n /** @internal */\n public async onHmr(event: HmrUpdateEvent): Promise<void> {\n if (this.#interactions) await this.#interactions.onHmr(event);\n if (this.#events) await this.#events.onHmr(event);\n if (this.#commandRegistry) await this.#commandRegistry.onHmr(event);\n }\n\n /** @internal */\n constructor(core: Core) {\n this.#intents = core.config.bot.clientOptions.intents;\n this.#client = new Client(core.config.bot.clientOptions);\n\n if (core.config.bot.interactions.path) {\n this.#interactions = new InteractionDispatcher(core);\n }\n if (core.config.bot.events.path) {\n this.#events = new EventDispatcher(core);\n }\n\n if (core.config.bot.commands.path) this.#commandRegistry = new CommandRegistry(core);\n\n this.#emojiInjector = new EmojiInjector(core);\n\n this.#registerShutdownTasks(core);\n }\n\n /** @internal */\n public get [controllersSlot](): Controllers {\n return { interactions: this.#interactions, events: this.#events, commandRegistry: this.#commandRegistry };\n }\n\n /** @internal */\n public get applicationId(): string {\n const { application } = this.#client;\n if (!application) throw new SeedcordError(SeedcordErrorCode.CoreApplicationUnavailable);\n return application.id;\n }\n\n #registerShutdownTasks(core: Core): void {\n core.shutdown.addTask(\n ShutdownPhase.Unbind,\n 'stop-dispatch',\n () => {\n this.#stopAccepting();\n return Promise.resolve();\n },\n UNBIND_TIMEOUT_MS\n );\n core.shutdown.addTask(ShutdownPhase.Drain, 'drain-dispatch', () => this.#drain(), DRAIN_TASK_TIMEOUT_MS);\n core.shutdown.addTask(ShutdownPhase.Logout, 'stop-bot', async () => await this.#stop(), LOGOUT_TIMEOUT_MS);\n }\n\n #stopAccepting(): void {\n this.#interactions?.stopAccepting();\n this.#events?.stopAccepting();\n }\n\n async #drain(): Promise<void> {\n // runs through allSettled since a rejecting drain must not abort the other dispatcher's drain\n await Promise.allSettled([this.#interactions?.drain(DRAIN_WINDOW_MS), this.#events?.drain(DRAIN_WINDOW_MS)]);\n }\n\n /** @internal */\n public async [initSlot](): Promise<void> {\n if (this.#isInitialized) {\n return;\n }\n this.#isInitialized = true;\n\n const token = this.botToken;\n\n if (this.#interactions) await this.#interactions.init();\n if (this.#events) await this.#events.init();\n\n await this.#login(token);\n\n await this.#emojiInjector.init();\n\n if (this.#commandRegistry) {\n await this.#commandRegistry.init();\n assertGuildsIntent(this.#intents, this.#commandRegistry.allCommands());\n await this.#commandRegistry.setCommands();\n this.#interactions?.warnUnhandledRoutes(this.#commandRegistry.routeLeaves());\n this.#interactions?.warnUnhandledContextMenuRoutes(this.#commandRegistry.contextMenuLeaves());\n }\n }\n\n async #stop(): Promise<void> {\n this.#client.removeAllListeners();\n\n await this.#logout();\n }\n\n async #login(token: string): Promise<Bot> {\n const ready: PromiseWithResolvers<void> = Promise.withResolvers();\n this.#client.once(Events.ClientReady, () => ready.resolve());\n void this.#client.login(token);\n await ready.promise;\n this.#logger.info(`Logged in as ${paint.sky.bold(this.#client.user?.username)}!`);\n return this;\n }\n\n async #logout(): Promise<void> {\n await this.#client.destroy();\n this.#logger.info(paint.coral.bold('Logged out of Discord!'));\n }\n\n public get client(): Client {\n return this.#client;\n }\n}\n\nexport function botLoggerOf(bot: Bot): Logger {\n return bot[loggerSlot];\n}\n\nexport function initBot(bot: Bot): Promise<void> {\n return bot[initSlot]();\n}\n\n// the gateway integration tests call these three off a live host\nexport function interactionsOf(bot: Bot): InteractionDispatcher | undefined {\n return bot[controllersSlot].interactions;\n}\n\nexport function eventsOf(bot: Bot): EventDispatcher | undefined {\n return bot[controllersSlot].events;\n}\n\nexport function commandRegistryOf(bot: Bot): CommandRegistry | undefined {\n return bot[controllersSlot].commandRegistry;\n}\n","/** Package version */\nexport const version = process.env.PACKAGE_VERSION ?? '0.0.0';\n","import { Bus } from '@seedcord/core';\nimport { busLoggerOf, HmrManager, setBotColor } from '@seedcord/core/internal';\nimport { CoordinatedShutdown, CoordinatedStartup, Pluggable } from '@seedcord/core/node';\nimport { HealthCheck, shutdownOf, StartupPhase, SubscriberLoader } from '@seedcord/core/node/internal';\nimport { LoggerChannelRegistry } from '@seedcord/logger';\nimport { installNodeDefaults } from '@seedcord/logger/node';\nimport { MemoryRateLimiter } from '@seedcord/rate-limiter';\nimport { HostAugmentTarget, HostVersion, SeedcordBrand } from '@seedcord/types/internal';\nimport { Envapter } from 'envapt';\n\nimport { botLoggerOf, Bot, initBot } from './bot/Bot';\nimport { version as packageVersion } from './version';\n\nimport type { GatewayConfig } from './interfaces/Config';\nimport type { Core } from './interfaces/Core';\nimport type { REST } from '@discordjs/rest';\nimport type { IRateLimiter } from '@seedcord/types';\nimport type { SeedcordInstance } from '@seedcord/types/internal';\n\n/**\n * The gateway bot host. Opens a discord.js gateway session, discovers handlers, and runs\n * coordinated startup and shutdown. Attach plugins with `attach()`.\n */\nexport class Seedcord extends Pluggable<'gateway', 'server'> implements Core, SeedcordInstance {\n // the CLI reads these to detect and augment the instance\n /** @internal */\n public readonly [SeedcordBrand] = true;\n /** @internal */\n public readonly [HostAugmentTarget] = '@seedcord/gateway';\n /** @internal */\n public readonly [HostVersion]: string = packageVersion;\n\n private readonly healthCheck?: HealthCheck | undefined;\n private readonly hmrManager: HmrManager;\n\n /** @see {@link Bus} */\n public readonly bus: Bus;\n\n private readonly subscribers: SubscriberLoader;\n\n /** @see {@link Bot} */\n public readonly bot: Bot;\n\n /** The discord.js client's REST client. Its token is set during the Login phase. */\n public readonly rest: REST;\n\n /** The bot's Discord application id. Throws if you read it before login. */\n public get applicationId(): string {\n return this.bot.applicationId;\n }\n\n /** @see {@link IRateLimiter} */\n public readonly rateLimiter: IRateLimiter;\n\n /**\n * @param config - Bot configuration including paths and Discord client options\n * @throws A **SeedcordError** When attempting to create multiple instances (singleton)\n */\n constructor(public readonly config: GatewayConfig) {\n super(new CoordinatedShutdown(config.lifecycle?.shutdownDeadline), new CoordinatedStartup());\n\n installNodeDefaults(config.logger);\n setBotColor(config.botColor);\n\n this.hmrManager = new HmrManager();\n this.hmrManager.init();\n this.bus = new Bus(this);\n this.subscribers = new SubscriberLoader(this.bus, config.subscribers.path);\n this.bot = new Bot(this);\n this.rest = this.bot.client.rest;\n this.rateLimiter = config.store ?? new MemoryRateLimiter();\n this.healthCheck = HealthCheck.fromOption(shutdownOf(this), config.healthCheck);\n\n this.registerStartupTasks();\n }\n\n /** The bot's discord username, populated after login. */\n public get username(): string | undefined {\n return this.bot.client.user?.username;\n }\n\n protected static override reset(host?: object): boolean {\n if (!super.reset(host)) return false;\n // reset() would drop the dev TUI's log sink\n LoggerChannelRegistry.instance.configure({});\n return true;\n }\n\n private registerStartupTasks(): void {\n if (Envapter.isDevelopment || Envapter.isTest) this.registerHmrAwareModules();\n\n this.startup.addTask(StartupPhase.Configuration, 'bus-initialization', async () => {\n busLoggerOf(this.bus).utils.initialization('Subscribers', 'start');\n await this.subscribers.init();\n busLoggerOf(this.bus).utils.initialization('Subscribers', 'end');\n });\n\n this.startup.addTask(StartupPhase.Login, 'bot-initialization', async () => {\n botLoggerOf(this.bot).utils.initialization('Bot', 'start');\n await initBot(this.bot);\n botLoggerOf(this.bot).utils.initialization('Bot', 'end');\n });\n\n const { healthCheck } = this;\n if (healthCheck) {\n this.startup.addTask(StartupPhase.Ready, 'health-check', async () => {\n healthCheck.logger.utils.initialization('HealthCheck', 'start');\n await healthCheck.init();\n healthCheck.logger.utils.initialization('HealthCheck', 'end');\n });\n }\n }\n\n /**\n * Starts the bot and runs all initialization tasks\n *\n * @returns This Seedcord instance when initialized\n */\n public async start(): Promise<this> {\n try {\n await super.init();\n } catch (caught) {\n // shutdown releases any resource opened before the failure, then rethrow\n await shutdownOf(this).run(1, false);\n Seedcord.reset(this);\n throw caught;\n }\n return this;\n }\n\n private registerHmrAwareModules(): void {\n this.startup.addTask(StartupPhase.Configuration, 'hmr-registration', async () => {\n this.hmrManager.register(this.bot);\n this.hmrManager.register(this.subscribers);\n for (const plugin of this.plugins) {\n this.hmrManager.register(plugin);\n }\n await Promise.resolve();\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["CoreRepliableHandler","CoreBaseHandler","CoreSubscriber","CoreWebhookLog","CorePlugin","logger","logger","event","packageVersion"],"sources":["../src/logger-bootstrap.ts","../src/bot/decorators/Events.ts","../src/bot/decorators/Gated.ts","../src/bot/decorators/Middlewares.ts","../src/bot/gates/catalog/IgnoreBots.ts","../src/bot/notices/index.ts","../src/bot/gates/catalog/Nsfw.ts","../src/bot/injectors/EmojiInjector.ts","../src/bot/notices/utils.ts","../src/bot/utilities/permissions/checkPermissions.ts","../src/bot/utilities/permissions/checkBotPermissions.ts","../src/bot/utilities/permissions/hasPermsToAssign.ts","../src/bot/confirm/reserved.ts","../src/bot/confirm/getConfirmation.ts","../src/bot/ReplySender.ts","../src/handlers/RepliableHandler.ts","../src/handlers/interaction/InteractionMiddleware.ts","../src/handlers/interaction/InteractionHandler.ts","../src/bot/utilities/miscellaneous/slashRouteOf.ts","../src/handlers/interaction/SlashHandler.ts","../src/handlers/interaction/ContextMenuHandler.ts","../src/handlers/BaseHandler.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/handlers/event/EventHandler.ts","../src/handlers/event/EventMiddleware.ts","../src/pagination/Paginator.ts","../src/pagination/sources.ts","../src/subscribers/index.ts","../src/plugin.ts","../src/miscellaneous/deriveEventActor.ts","../src/bot/gates/runGates.ts","../src/miscellaneous/extractErrorResponse.ts","../src/bot/handleEventFault.ts","../src/bot/reportEventDispatch.ts","../src/bot/controllers/EventDispatcher.ts","../src/bot/defaults/UnhandledRepliable.ts","../src/bot/defaults/UnhandledAutocomplete.ts","../src/bot/harmlessApiCodes.ts","../src/bot/handleInteractionFault.ts","../src/bot/controllers/InteractionDispatcher.ts","../src/miscellaneous/assertGuildsIntent.ts","../src/bot/Bot.ts","../src/version.ts","../src/Seedcord.ts"],"sourcesContent":["import { installNodeDefaults } from '@seedcord/logger/node';\n\n// the gateway runs on node so install the winston sinks before any logging\ninstallNodeDefaults();\n","import { EventMetadataKey } from '@seedcord/core/internal';\n\nimport type { EventHandler } from '#handlers/event';\nimport type { ValidNonInteractionKeys } from '#src/handlers/interactionTypes';\nimport type { EventFrequency } from '@seedcord/types';\nimport type { ClientEvents } from 'discord.js';\nimport type { Constructor } from 'type-fest';\n\n/** Options accepted by the event registration decorator. */\nexport interface RegisterEventOptions {\n /**\n * Frequency: 'once' or 'on'.\n *\n * @defaultValue `'on'`\n */\n readonly frequency?: EventFrequency | undefined;\n}\n\n/** @internal */\nexport interface RegisterEventMetadataEntry<EventKey extends keyof ClientEvents> {\n readonly event: EventKey;\n readonly frequency: EventFrequency;\n}\n\n/** Tuple describing a single event and optional options. */\nexport type EventSpec<EventKey extends ValidNonInteractionKeys> = readonly [\n event: EventKey,\n options?: RegisterEventOptions\n];\n\n/**\n * Registers an event handler class with one or more Discord.js events.\n *\n * Associates the decorated class with the provided Discord client events for automatic registration and execution when those events are emitted.\n *\n * Supply any number of event tuples. Each tuple can include per event options.\n *\n * @typeParam EventKey - Union of Discord.js ClientEvents keys to register for\n * @param defs - One or more tuples of [event, options]\n * @decorator\n * @example\n * ```ts\n * \\@RegisterEvent([Events.MessageCreate])\n * class MessageHandler extends EventHandler<Events.MessageCreate> {\n * async execute() {\n * // Handle message creation\n * }\n * }\n * ```\n *\n * @example\n * ```ts\n * \\@RegisterEvent([Events.MessageCreate], [Events.MessageUpdate])\n * class MessageHandler extends EventHandler<Events.MessageCreate | Events.MessageUpdate> {\n * async execute() {\n * // Handle message creation or update\n * }\n * }\n * ```\n *\n * @example\n * ```ts\n * \\@RegisterEvent([Events.MessageCreate, { frequency: 'once' }], [Events.MessageUpdate])\n * class OneTimeMessageHandler extends EventHandler<Events.MessageCreate | Events.MessageUpdate> {\n * async execute() {\n * // Handle only the first message creation, and message update normally\n * }\n * }\n * ```\n */\nexport function RegisterEvent<const Defs extends readonly EventSpec<ValidNonInteractionKeys>[]>(...defs: Defs) {\n type EventKey = Defs[number][0];\n\n // EventHandler is invariant in its Names generic (match puts Names in the arms, a contravariant position), so\n // this single constraint rejects a handler whose generic and decorator list different events, both directions.\n return function <HandlerCtor extends Constructor<EventHandler<EventKey>>>(constructor: HandlerCtor): void {\n const saved = Reflect.getMetadata(EventMetadataKey, constructor) as\n RegisterEventMetadataEntry<EventKey>[] | undefined;\n const existing = saved ?? [];\n\n const entries = defs.map<RegisterEventMetadataEntry<EventKey>>(([event, options]) => ({\n event,\n frequency: options?.frequency ?? 'on'\n }));\n\n Reflect.defineMetadata(EventMetadataKey, [...existing, ...entries], constructor);\n };\n}\n","import { GatedMetadataKey } from '@seedcord/core/internal';\n\nimport type { AnyHandlerCtor, FitAll } from '#bot/gates/matching';\nimport type { Gate, GateContextBase } from '@seedcord/core';\nimport type { NonEmptyTuple } from 'type-fest';\n\n/**\n * Attaches gates to a handler. The gates run before `execute`, and a gate refusing stops the handler with\n * the reply or drop the gate threw. Multiple gates are ANDed, so each must pass. A gate that requires a\n * context the handler does not provide (a button gate on a slash handler, an interaction gate on an event\n * handler) 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.js';\n *\n * \\@Gated(GuildOnly(), RequirePermissions([PermissionFlagsBits.Administrator]))\n * \\@SlashRoute('maintenance')\n * class Maintenance extends SlashHandler<'maintenance'> {\n * async execute() {\n * // both gates passed, so this runs in a guild with an admin caller\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 needs 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 // mismatch resolves to the error tuple, so 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","import { EventMiddlewareMetadataKey } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordTypeError } from '@seedcord/errors/internal';\n\nimport type { EventMiddleware } from '#handlers/event';\nimport type { ValidNonInteractionKeys } from '#src/handlers/interactionTypes';\nimport type { Constructor, NonEmptyTuple } from 'type-fest';\n\n/** Registration options for an event middleware. */\nexport interface EventMiddlewareOptions<Events extends NonEmptyTuple<ValidNonInteractionKeys>> {\n /**\n * Restrict this middleware to certain Discord client events. The middleware's `EventMiddleware`\n * generic must list the same events, or applying the decorator is a compile error. Omit it to run on\n * every event.\n */\n readonly events?: Events;\n /** Lower runs earlier. Two middleware sharing a priority run in registration order.\n *\n * @defaultValue 0\n */\n readonly priority?: number;\n}\n\n/** @internal */\nexport interface EventMiddlewareMetadata {\n readonly priority: number;\n readonly events?: readonly ValidNonInteractionKeys[];\n}\n\n/**\n * Registers an event middleware. It runs before the handlers for every event it lists.\n *\n * @param options - The events this middleware runs on and its ordering.\n * @decorator\n *\n * @example\n * ```ts\n * \\@RegisterEventMiddleware({ events: [Events.MessageCreate], priority: 10 })\n * class Audit extends EventMiddleware<Events.MessageCreate> {\n * async execute() {\n * this.logger.info(this.event[0].id);\n * }\n * }\n * ```\n *\n * @throws A **SeedcordTypeError** If `priority` is not a finite number.\n */\nexport function RegisterEventMiddleware<\n const Events extends NonEmptyTuple<ValidNonInteractionKeys> = NonEmptyTuple<ValidNonInteractionKeys>\n>(options: EventMiddlewareOptions<Events> = {}) {\n return function (ctor: Constructor<EventMiddleware<Events[number]>>): void {\n const priority = Number(options.priority ?? 0);\n if (!Number.isFinite(priority)) {\n throw new SeedcordTypeError(SeedcordErrorCode.DecoratorInvalidMiddlewarePriority);\n }\n if (options.events?.length === 0) {\n throw new SeedcordTypeError(SeedcordErrorCode.DecoratorEmptyMiddlewareFilter, ['events']);\n }\n\n const metadata: EventMiddlewareMetadata = {\n priority,\n ...(options.events && { events: options.events })\n };\n\n Reflect.defineMetadata(EventMiddlewareMetadataKey, metadata, ctor);\n };\n}\n\n/** @internal */\nexport function eventMiddlewareMetaOf(constructor: object): EventMiddlewareMetadata | undefined {\n const saved: unknown = Reflect.getMetadata(EventMiddlewareMetadataKey, constructor);\n return saved as EventMiddlewareMetadata | undefined;\n}\n","import { defineGate, Silence } from '@seedcord/core';\n\nimport type { EventGateContext } from '../Gate';\n\n/**\n * Drops a client event whose actor is a bot, with a {@link Silence} so nothing is replied. Event-only, because a\n * Silence on an interaction would leave Discord's failed-interaction state. It rejects an interaction handler at\n * the decorator line. Takes no options, so attach it directly without calling it.\n *\n * @see {@link Gated}\n *\n * @example\n * ```ts\n * import { Events } from 'discord.js';\n *\n * \\@Gated(IgnoreBots)\n * class OnMessage extends EventHandler<Events.MessageCreate> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n */\nexport const IgnoreBots = defineGate('IgnoreBots', (ctx: EventGateContext) => {\n if (ctx.user?.bot) throw new Silence('actor is a bot');\n});\n","import { Notice } from '@seedcord/core';\nimport { GateNotice, NoticeCard } from '@seedcord/core/internal';\n\nimport type { ReplyResponse } from '@seedcord/types';\nimport type { Role } from 'discord.js';\n\nexport class NotNsfw extends GateNotice {\n public constructor(message = 'This can only be used in an age-restricted channel.') {\n super(message);\n this.summary = 'be in an age-restricted channel';\n }\n}\n\nexport class RoleHigherThanMe extends Notice {\n public constructor(\n message: string,\n public role: Role,\n public botRole: Role\n ) {\n super(message);\n }\n\n public render(): ReplyResponse {\n const card = new NoticeCard(\n `I cannot assign a role that is higher than me.\\n\\n` +\n `The role <@&${this.role.id}> is higher than my role <@&${this.botRole.id}> in the hierarchy.`\n );\n return { components: [card.component] };\n }\n}\n\nexport class CannotAssignBotRole extends Notice {\n public constructor(message = 'I cannot assign a managed role.') {\n super(message);\n }\n\n public render(): ReplyResponse {\n return { components: [new NoticeCard('I cannot assign a managed role.').component] };\n }\n}\n","import { defineGate } from '@seedcord/core';\nimport { pickNotice } from '@seedcord/core/internal';\n\nimport { NotNsfw } from '#bot/notices';\n\nimport type { NonModalInteraction } from '#src/handlers/interactionTypes';\nimport type { InteractionGateContext } from '../Gate';\nimport type { Gate, GateNoticeOptions } from '@seedcord/core';\n\n// a thread carries no nsfw flag of its own\nfunction channelIsNsfw(channel: InteractionGateContext['interaction']['channel']): boolean {\n if (!channel) return false;\n if (channel.isThread()) return channel.parent?.nsfw ?? false;\n return 'nsfw' in channel ? channel.nsfw : false;\n}\n\n/**\n * Requires an age-restricted channel, else refuses. Pass {@link GateNoticeOptions} to reword or replace the refusal.\n *\n * A thread inherits its parent channel's nsfw flag. ModalSubmit has no reliable channel, so it is excluded.\n *\n * @param options - Reword the default refusal with `message`, or replace it with `notice`.\n *\n * @see {@link Gated}\n *\n * @example\n * ```ts\n * \\@Gated(Nsfw())\n * \\@SlashRoute('nsfwcmd')\n * class NsfwHandler extends SlashHandler<'nsfwcmd'> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n */\nexport function Nsfw(options?: GateNoticeOptions): Gate<InteractionGateContext<NonModalInteraction>, 'Nsfw'> {\n return defineGate('Nsfw', (ctx: InteractionGateContext<NonModalInteraction>) => {\n if (channelIsNsfw(ctx.interaction.channel)) return;\n throw pickNotice(options, (message) => new NotNsfw(message));\n });\n}\n","import { ResolvedEmoji } from '@seedcord/core';\nimport { accessorStore, clearStore, guardedAccessor, isEmojiTuple } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { Logger } from '@seedcord/logger';\n\nimport type { Core } from '#interfaces/Core';\nimport type { EmojiMap } from '@seedcord/types';\nimport type { ApplicationEmoji, GuildEmoji } from 'discord.js';\n\ntype SavedEmojiType = GuildEmoji | ApplicationEmoji;\n\n/** A resolved emoji, plus the discord.js emoji it came from on {@link GatewayEmoji.source}. */\nexport class GatewayEmoji<Source extends SavedEmojiType = SavedEmojiType> extends ResolvedEmoji {\n // Object.entries skips a private field\n readonly #source: Source;\n\n constructor(source: Source) {\n super(source.name, source.id, source.animated);\n this.#source = source;\n }\n\n /** What discord.js resolved, for `.url` and the management calls. */\n public get source(): Source {\n return this.#source;\n }\n}\n\nconst emojiStorage = accessorStore<GatewayEmoji>();\n\n/**\n * The global {@link Emojis} accessor type. Each key's `source` resolves to its precise class, `GuildEmoji`\n * for a `'guild'` tag and `ApplicationEmoji` for an `'application'` tag, the tags `seedcord codegen`\n * writes into {@link EmojiMap}.\n */\nexport type InjectedEmojiMap = {\n [K in keyof EmojiMap]: EmojiMap[K] extends 'guild' ? GatewayEmoji<GuildEmoji> : GatewayEmoji<ApplicationEmoji>;\n};\n\n/**\n * The bot's resolved emojis, keyed by {@link EmojiMap}. Filled by {@link EmojiInjector} during startup.\n * Throws if you read a key the injector did not fill.\n */\nexport const Emojis = guardedAccessor('Emojis', emojiStorage) as InjectedEmojiMap;\n\n// a guild emoji requires the Guilds intent in the client options\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 this.clearEmojis();\n\n if (!this.core.config.bot.emojis || Object.keys(this.core.config.bot.emojis).length === 0) {\n this.logger.debug('No emojis configured, skipping emoji injection.');\n return;\n }\n\n const configEmojis = this.core.config.bot.emojis;\n await this.core.bot.client.application?.emojis.fetch();\n\n const failures: string[] = [];\n const fetchedGuilds = new Set<string>();\n for (const [key, value] of Object.entries(configEmojis)) {\n if (isEmojiTuple(value)) {\n await this.resolveTuple(key, value, failures, fetchedGuilds);\n } else if (typeof value === 'string') {\n this.resolveString(key, value, failures);\n } else {\n failures.push(` - \"${key}\" has an invalid value (expected a name or [name, guildId])`);\n }\n }\n\n if (failures.length > 0) {\n throw new SeedcordError(SeedcordErrorCode.ConfigEmojiUnresolved, [failures.length, failures.join('\\n')]);\n }\n\n this.logger.utils.summary('Loaded emojis', { emojis: Object.keys(emojiStorage).length });\n }\n\n private async resolveTuple(\n key: string,\n value: readonly [string, string],\n failures: string[],\n fetchedGuilds: Set<string>\n ): Promise<void> {\n const [emojiName, guildId] = value;\n\n const guild = this.core.bot.client.guilds.cache.get(guildId);\n if (!guild) {\n failures.push(\n ` - \"${emojiName}\" for \"${key}\" targets guild ${guildId}, which is not available (check the Guilds intent)`\n );\n return;\n }\n\n if (!fetchedGuilds.has(guildId)) {\n await guild.emojis.fetch();\n fetchedGuilds.add(guildId);\n }\n const guildEmoji = guild.emojis.cache.find((e) => e.name === emojiName);\n if (!guildEmoji) {\n failures.push(` - \"${emojiName}\" for \"${key}\" was not found in guild ${guildId}`);\n return;\n }\n\n emojiStorage[key] = new GatewayEmoji(guildEmoji);\n }\n\n private resolveString(key: string, emojiName: string, failures: string[]): void {\n const appEmoji = this.core.bot.client.application?.emojis.cache.find((e) => e.name === emojiName);\n if (!appEmoji) {\n failures.push(` - \"${emojiName}\" for \"${key}\" was not found among the application emojis`);\n return;\n }\n\n emojiStorage[key] = new GatewayEmoji(appEmoji);\n }\n\n private clearEmojis(): void {\n clearStore(emojiStorage);\n }\n}\n","import { Role } from 'discord.js';\n\nimport type { GuildMember } from 'discord.js';\n\n// whose permissions a check ran against, mentioned as the refusal subject\ntype PermSubject = Role | GuildMember;\n\nexport function mentionFor(subject: PermSubject): string {\n if (subject instanceof Role) return `<@&${subject.id}>`;\n return `<@${subject.id}>`;\n}\n","import { assertPermissions } from '@seedcord/core';\nimport { Guild, GuildMember, Role } from 'discord.js';\n\nimport { mentionFor } from '#bot/notices/utils';\n\nimport type { PermissionNoticeOverrides, PermissionScope } from '@seedcord/core';\nimport type { TextChannel } from 'discord.js';\n\n/** Options for {@link checkPermissions}. */\nexport interface CheckPermissionOptions extends PermissionNoticeOverrides {\n /** The role or member to check. */\n for: Role | GuildMember;\n /** A guild reads the base bits from roles, a text channel reads the overwrite-resolved set. */\n in: Guild | TextChannel;\n /** The permission flag bits to check. */\n scope: PermissionScope;\n /** Refuse when the target holds a scope bit. */\n inverse?: boolean;\n}\n\n/**\n * Checks a {@link Role} or a {@link GuildMember} against the base permission bits in a {@link Guild},\n * before channel overwrites. Refuses when a permission in `scope` is missing, or with `inverse` when one\n * is present.\n *\n * @example\n * ```ts\n * import { PermissionFlagsBits } from 'discord.js';\n * import { checkPermissions } from '@seedcord/gateway';\n *\n * checkPermissions(role, guild, [PermissionFlagsBits.ManageMessages, PermissionFlagsBits.KickMembers]);\n * ```\n *\n * @example\n * ```ts\n * // refuse when the member holds Administrator, and replace the refusal\n * checkPermissions(member, guild, [PermissionFlagsBits.Administrator], true, {\n * dangerousNotice: CustomDangerousNotice\n * });\n * ```\n */\nexport function checkPermissions(\n target: Role | GuildMember,\n ctx: Guild,\n scope: PermissionScope,\n inverse?: boolean,\n errors?: PermissionNoticeOverrides\n): void;\n\n/**\n * Checks a {@link Role} or a {@link GuildMember} against the overwrite-resolved set in a\n * {@link TextChannel}. Refuses when a permission in `scope` is missing, or with `inverse` when one is\n * present.\n *\n * @example\n * ```ts\n * import { PermissionFlagsBits } from 'discord.js';\n * import { checkPermissions } from '@seedcord/gateway';\n *\n * checkPermissions(role, textChannel, [PermissionFlagsBits.SendMessages, PermissionFlagsBits.ViewChannel]);\n * ```\n */\nexport function checkPermissions(\n target: Role | GuildMember,\n // eslint-disable-next-line @typescript-eslint/unified-signatures -- the guild and channel forms resolve different bits, documented separately\n ctx: TextChannel,\n scope: PermissionScope,\n inverse?: boolean,\n errors?: PermissionNoticeOverrides\n): void;\n\n/**\n * Checks permissions with an options object. Refuses when a permission in\n * {@link CheckPermissionOptions.scope} is missing, or with `options.inverse` when one is present.\n *\n * @example\n * ```ts\n * import { PermissionFlagsBits } from 'discord.js';\n * import { checkPermissions } from '@seedcord/gateway';\n *\n * checkPermissions({\n * for: member,\n * in: textChannel,\n * scope: [PermissionFlagsBits.SendMessages, PermissionFlagsBits.ViewChannel]\n * });\n * ```\n */\nexport function checkPermissions(options: CheckPermissionOptions): void;\n\nexport function checkPermissions(\n a: Role | GuildMember | CheckPermissionOptions,\n b?: Guild | TextChannel,\n c?: PermissionScope,\n d?: boolean,\n e?: PermissionNoticeOverrides\n): void {\n const opts: CheckPermissionOptions =\n a instanceof Role || a instanceof GuildMember\n ? // justified: the positional overloads always supply b and c, the implementation signature widens them to | undefined\n {\n for: a,\n in: b as Guild | TextChannel,\n scope: c as PermissionScope,\n inverse: d ?? false,\n ...e\n }\n : a;\n\n const { for: pFor, in: pIn, scope, inverse = false, missingNotice, dangerousNotice } = opts;\n\n const perms = pIn instanceof Guild ? pFor.permissions : pIn.permissionsFor(pFor, true);\n\n assertPermissions({\n subject: mentionFor(pFor),\n permissions: perms.bitfield,\n scope,\n inverse,\n ...(missingNotice && { missingNotice }),\n ...(dangerousNotice && { dangerousNotice })\n });\n}\n","import { MissingPermissions, PermissionNames } from '@seedcord/core/internal';\nimport { Logger } from '@seedcord/logger';\nimport { Guild } from 'discord.js';\n\nimport { checkPermissions } from './checkPermissions';\n\nimport type { PermissionNoticeOverrides, PermissionScope } from '@seedcord/core';\nimport type { TextChannel } from 'discord.js';\n\n/**\n * Checks the bot's own permissions in a {@link Guild} or {@link TextChannel}. Refuses when a permission in\n * `scope` is missing, or with `inverse` when one is present. When the bot member is uncached, the refusal\n * reports every permission in `scope` as missing.\n *\n * @example\n * ```ts\n * import { PermissionFlagsBits } from 'discord.js';\n * import { checkBotPermissions } from '@seedcord/gateway';\n *\n * checkBotPermissions(textChannel, [PermissionFlagsBits.SendMessages, PermissionFlagsBits.ViewChannel]);\n * ```\n */\nexport function checkBotPermissions(\n target: Guild | TextChannel,\n scope: PermissionScope,\n inverse = false,\n errors?: PermissionNoticeOverrides\n): void {\n if (target instanceof Guild) {\n const me = target.members.me;\n if (!me) {\n const names = scope.map((bit) => PermissionNames.get(bit) ?? String(bit));\n const Missing = errors?.missingNotice ?? MissingPermissions;\n throw new Missing(undefined, 'The bot', names);\n }\n checkPermissions(me, target, scope, inverse, errors);\n return;\n }\n\n const me = target.guild.members.me;\n\n if (!me) {\n const logger = new Logger('checkBotPermissions', { channel: 'errors' });\n logger.warn(\n `Bot member is unavailable in guild ${target.guild.id} while checking permissions in channel ${target.id}`\n );\n const names = scope.map((bit) => PermissionNames.get(bit) ?? String(bit));\n const Missing = errors?.missingNotice ?? MissingPermissions;\n throw new Missing(undefined, 'The bot', names);\n }\n\n checkPermissions(me, target, scope, inverse, errors);\n}\n","import { MissingPermissions } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { PermissionFlagsBits, Role } from 'discord.js';\n\nimport { CannotAssignBotRole, RoleHigherThanMe } from '#bot/notices';\n\nimport { checkBotPermissions } from './checkBotPermissions';\n\nimport type { Notice } from '@seedcord/core';\nimport type { Guild } from 'discord.js';\n\n/**\n * Optional custom error constructors for {@link HasPermsToAssignOptions}.\n */\nexport interface AssignRoleNoticeOverrides {\n higherNotice?: new (message: string, role: Role, botRole: Role) => Notice;\n managedNotice?: new (message: string) => Notice;\n missingNotice?: new (message: string | undefined, subject: string, missingPerms: readonly string[]) => Notice;\n}\n\n/**\n * Options for {@link hasPermsToAssign}.\n */\nexport interface HasPermsToAssignOptions {\n targetRole: Role;\n noticeOverrides?: AssignRoleNoticeOverrides;\n}\n\n// botRoleFor searches the guild's role cache, so a cold cache returns null\nfunction botRoleOf(guild: Guild): Role {\n const botRole = guild.roles.botRoleFor(guild.client.user);\n if (!botRole) throw new SeedcordError(SeedcordErrorCode.CoreBotRoleMissing, [guild.id]);\n return botRole;\n}\n\n/**\n * Validates that the bot can assign a target role. Refuses when the target role is above the bot's, is managed, or the bot lacks Manage Roles.\n *\n * @param roleOrOptions - Target role or complete options for the check\n * @throws A `Notice` on refusal, or a `SeedcordError` when the bot has no role in the guild's role cache.\n *\n * @example\n * ```ts\n * import { hasPermsToAssign } from '@seedcord/gateway';\n *\n * // Check if the bot can assign a specific role\n * hasPermsToAssign(role);\n *\n * // Check with custom error handling\n * hasPermsToAssign({\n * targetRole: role,\n * noticeOverrides: {\n * higherNotice: CustomHigherNotice,\n * managedNotice: CustomManagedNotice,\n * missingNotice: CustomMissingPermissionsNotice\n * }\n * });\n * ```\n */\nexport function hasPermsToAssign(roleOrOptions: Role | HasPermsToAssignOptions): void {\n const { targetRole, noticeOverrides: errors } =\n roleOrOptions instanceof Role\n ? {\n targetRole: roleOrOptions,\n noticeOverrides: undefined\n }\n : roleOrOptions;\n\n const HigherNotice = errors?.higherNotice ?? RoleHigherThanMe;\n const ManagedNotice = errors?.managedNotice ?? CannotAssignBotRole;\n const MissingNotice = errors?.missingNotice ?? MissingPermissions;\n\n const botRole = botRoleOf(targetRole.guild);\n\n if (targetRole.comparePositionTo(botRole) >= 0) {\n throw new HigherNotice('Role is higher than me', targetRole, botRole);\n }\n\n if (targetRole.managed) {\n throw new ManagedNotice(`Cannot assign managed role ${targetRole.name}`);\n }\n\n checkBotPermissions(targetRole.guild, [PermissionFlagsBits.ManageRoles], false, { missingNotice: MissingNotice });\n}\n","import { CustomId } from '@seedcord/core';\n\nconst RESERVED_CONFIRM_PREFIX = '__seedcord_confirm';\n\n// no route, so the dispatcher skips these clicks and the in-process collector reads them instead. never mint a real component from this id.\nexport const CONFIRM_DEF = new CustomId(RESERVED_CONFIRM_PREFIX).oneOf('choice', ['confirm', 'cancel']);\n","import { ButtonBuilder, TextDisplayBuilder } from '@discordjs/builders';\nimport { BuilderComponent, RowComponent } from '@seedcord/core';\nimport { ButtonStyle, ComponentType } from 'discord.js';\n\nimport { CONFIRM_DEF } from './reserved';\n\nimport type { ReplySender } from '#bot/ReplySender';\nimport type { NonModalInteraction } from '#src/handlers/interactionTypes';\nimport type { RepliableHandler } from '#src/handlers/RepliableHandler';\nimport type { ReplyResponse } from '@seedcord/types';\nimport type { ButtonInteraction, Message } from 'discord.js';\nimport type { Promisable } from 'type-fest';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n// encode the ids once because the reserved def's shape and choices never change\nconst CONFIRM_IDS = {\n confirm: CONFIRM_DEF.encode({ choice: 'confirm' }),\n cancel: CONFIRM_DEF.encode({ choice: 'cancel' })\n};\n\ntype Outcome = ReplyResponse | (() => Promisable<ReplyResponse>);\n\ntype ConfirmPrompt = string | ((ids: { confirm: string; cancel: string }) => Promisable<ReplyResponse>);\n\n/** Options shared by both confirmation forms. */\nexport interface ConfirmOptions {\n /**\n * Whether the prompt is ephemeral. Only the invoking user can act on it either way, a non-invoker's\n * click is ignored.\n *\n * @defaultValue `true`\n */\n ephemeral?: boolean;\n /**\n * Milliseconds to wait for a click before the prompt is settled and the result resolves to `false`.\n *\n * @defaultValue `30_000`\n */\n timeoutMs?: number;\n /** Shown in place of the prompt when the user confirms. Absent removes the prompt. */\n onConfirm?: Outcome;\n /** Shown in place of the prompt when the user cancels. Absent removes the prompt. */\n onCancel?: Outcome;\n /** Shown in place of the prompt when the prompt times out. Absent removes the prompt. */\n onTimeout?: Outcome;\n}\n\n/** Options for the string-prompt form, adding the built-in Confirm/Cancel buttons' labels and style. */\nexport interface DefaultConfirmOptions extends ConfirmOptions {\n /**\n * Confirm-button label.\n *\n * @defaultValue `'Confirm'`\n */\n confirmLabel?: string;\n /**\n * Cancel-button label.\n *\n * @defaultValue `'Cancel'`\n */\n cancelLabel?: string;\n /**\n * Confirm-button style.\n *\n * @defaultValue {@link ButtonStyle.Danger}\n */\n confirmStyle?: ButtonStyle;\n}\n\nclass ConfirmButtons extends RowComponent<'button'> {\n constructor(options: DefaultConfirmOptions | undefined) {\n super('button');\n this.instance.addComponents(\n new ButtonBuilder()\n .setCustomId(CONFIRM_IDS.confirm)\n .setLabel(options?.confirmLabel ?? 'Confirm')\n .setStyle(options?.confirmStyle ?? ButtonStyle.Danger),\n new ButtonBuilder()\n .setCustomId(CONFIRM_IDS.cancel)\n .setLabel(options?.cancelLabel ?? 'Cancel')\n .setStyle(ButtonStyle.Secondary)\n );\n }\n}\n\nclass ConfirmPromptCard extends BuilderComponent<'container'> {\n constructor(text: string, options: DefaultConfirmOptions | undefined) {\n super('container');\n this.instance\n .addTextDisplayComponents(new TextDisplayBuilder().setContent(text))\n .addActionRowComponents(new ConfirmButtons(options).component);\n }\n}\n\nfunction defaultPrompt(text: string, options: DefaultConfirmOptions | undefined): ReplyResponse {\n return { components: [new ConfirmPromptCard(text, options).component] };\n}\n\nasync function collectChoice(message: Message, userId: string, timeoutMs: number): Promise<ButtonInteraction | null> {\n try {\n return await message.awaitMessageComponent({\n componentType: ComponentType.Button,\n time: timeoutMs,\n filter: (click) => click.user.id === userId && CONFIRM_DEF.owns(click.customId)\n });\n } catch {\n // awaitMessageComponent rejects on timeout, which resolves to no decision here\n return null;\n }\n}\n\nasync function settle(sender: ReplySender, message: Message, outcome: Outcome | undefined): Promise<void> {\n if (outcome === undefined) {\n // a plain message.delete() cannot remove an ephemeral message\n await sender.delete(message).catch(() => undefined);\n return;\n }\n await sender.edit(message, typeof outcome === 'function' ? await outcome() : outcome);\n}\n\n/**\n * Shows a confirm/cancel prompt with built-in Confirm and Cancel buttons and resolves to `true` only if the\n * invoking user clicks confirm. A cancel click or a timeout resolves to `false`. Gate the action behind it\n * with an early return. A failed prompt send throws into the fault boundary. A {@link ModalHandler} is\n * excluded at compile time.\n *\n * @param handler - The handler to prompt from, `this` inside a non-modal handler.\n * @param prompt - The message shown above the Confirm and Cancel buttons.\n * @param options - Ephemeral flag, timeout, the built-in buttons' labels and style, and the optional\n * `onConfirm`/`onCancel`/`onTimeout` outcome replies that edit the prompt in place.\n * @returns `true` if confirmed, `false` on cancel or timeout.\n *\n * @example\n * ```ts\n * import { getConfirmation } from '@seedcord/gateway';\n *\n * \\@SlashRoute('ban')\n * class BanHandler extends SlashHandler<'ban'> {\n * async execute() {\n * const target = this.options.getUser('target');\n * if (!(await getConfirmation(this, `Ban ${target.tag}? This cannot be undone.`))) return;\n * await this.event.guild?.members.ban(target.id);\n * }\n * }\n * ```\n */\nexport function getConfirmation(\n handler: RepliableHandler<NonModalInteraction>,\n prompt: string,\n options?: DefaultConfirmOptions\n): Promise<boolean>;\n/**\n * Shows a confirm/cancel prompt you build yourself and resolves to `true` only if the invoking user clicks\n * confirm. The factory receives the two minted button ids. Set them on your own buttons. A cancel click or a\n * timeout resolves to `false`. A failed prompt send throws into the fault boundary. A {@link ModalHandler} is\n * excluded at compile time.\n *\n * @param handler - The handler to prompt from, `this` inside a non-modal handler.\n * @param prompt - A factory given the minted `{ confirm, cancel }` ids that returns the reply to show. Build\n * it with the `BuilderComponent` and `RowComponent` wrappers.\n * @param options - Ephemeral flag, timeout, and the optional `onConfirm`/`onCancel`/`onTimeout` outcome\n * replies that edit the prompt in place.\n * @returns `true` if confirmed, `false` on cancel or timeout.\n *\n * @remarks\n * The prompt is collected in-process, so it does not survive a bot restart. Without an outcome hook the\n * prompt is gone once the user confirms, so deliver the result with a fresh `this.followUp(...)`.\n *\n * @example\n * ```ts\n * import { ButtonBuilder, TextDisplayBuilder } from '@discordjs/builders';\n * import { ButtonStyle } from 'discord.js';\n * import { BuilderComponent, RowComponent, getConfirmation } from '@seedcord/gateway';\n *\n * class BanPrompt extends BuilderComponent<'container'> {\n * constructor(text: string) {\n * super('container');\n * this.instance.addTextDisplayComponents(new TextDisplayBuilder().setContent(text));\n * }\n * }\n *\n * class ConfirmRow extends RowComponent<'button'> {\n * constructor(ids: { confirm: string; cancel: string }) {\n * super('button');\n * const buttons = [\n * [ids.confirm, 'Ban', ButtonStyle.Danger],\n * [ids.cancel, 'Cancel', ButtonStyle.Secondary]\n * ] as const;\n * this.instance.addComponents(\n * ...buttons.map(([id, label, style]) => new ButtonBuilder().setCustomId(id).setLabel(label).setStyle(style))\n * );\n * }\n * }\n *\n * const target = this.options.getUser('target');\n * const confirmed = await getConfirmation(\n * this,\n * (ids) => ({ components: [new BanPrompt(`Ban ${target.tag}?`).component, new ConfirmRow(ids).component] }),\n * { onConfirm: { components: [new BanPrompt(`Banned ${target.tag}.`).component] } }\n * );\n * if (!confirmed) return;\n * ```\n */\nexport function getConfirmation(\n handler: RepliableHandler<NonModalInteraction>,\n prompt: (ids: { confirm: string; cancel: string }) => Promisable<ReplyResponse>,\n options?: ConfirmOptions\n): Promise<boolean>;\nexport async function getConfirmation(\n handler: RepliableHandler<NonModalInteraction>,\n prompt: ConfirmPrompt,\n options?: DefaultConfirmOptions\n): Promise<boolean> {\n const { ephemeral = true, timeoutMs = DEFAULT_TIMEOUT_MS } = options ?? {};\n\n const response = typeof prompt === 'string' ? defaultPrompt(prompt, options) : await prompt(CONFIRM_IDS);\n const interaction = handler.getEvent();\n const { sender } = handler;\n const message = await sender.send(response, { ephemeral });\n\n const winner = await collectChoice(message, interaction.user.id, timeoutMs);\n if (!winner) {\n await settle(sender, message, options?.onTimeout);\n return false;\n }\n\n // discord can expire the 3s ack window between the filter firing and this ack\n await winner.deferUpdate().catch(() => undefined);\n const confirmed = winner.customId === CONFIRM_IDS.confirm;\n await settle(sender, message, confirmed ? options?.onConfirm : options?.onCancel);\n return confirmed;\n}\n","import { BaseReplySender } from '@seedcord/core';\nimport { deferFlags, sendFlags } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { MessageFlags } from 'discord.js';\n\nimport type { GatewayFile, GatewayReplyResponse } from '#interfaces/ReplyResponse';\nimport type { Repliables } from '#src/handlers/interactionTypes';\nimport type { Bus, DispatchContext } from '@seedcord/core';\nimport type { AckState } from '@seedcord/core/internal';\nimport type { DeferOpts, ReplyFile, SendOpts } from '@seedcord/types';\nimport type {\n APIModalInteractionResponseCallbackData,\n InteractionCallbackResponse,\n InteractionReplyOptions,\n InteractionUpdateOptions,\n MessageComponentInteraction,\n ModalMessageModalSubmitInteraction,\n Message,\n WebhookMessageEditOptions\n} from 'discord.js';\n\n// djs kinds that carry a source message\ntype SourceInteraction = MessageComponentInteraction | ModalMessageModalSubmitInteraction;\n\nexport type SentMessage = Message;\n\nfunction isReplyFile(file: ReplyFile | GatewayFile): file is ReplyFile {\n return typeof file === 'object' && 'data' in file && ArrayBuffer.isView(file.data);\n}\n\n// discord.js rejects a plain Uint8Array\nfunction toDjsFile(file: ReplyFile | GatewayFile): GatewayFile {\n if (!isReplyFile(file)) return file;\n return {\n attachment: Buffer.from(file.data),\n name: file.name,\n ...(file.description !== undefined && { description: file.description }),\n ...(file.title !== undefined && { title: file.title })\n };\n}\n\n// djs flips `replied` on editReply, so per-call derivation would break repeated update() and post-edit\n// send() parity\nfunction seedState(interaction: Repliables): AckState {\n if (interaction.deferred && interaction.ephemeral === null) return 'deferred-update';\n if (interaction.replied) return 'replied';\n if (interaction.deferred) return 'deferred-reply';\n return 'unacked';\n}\n\n/** Writes interaction responses through discord.js. The repliable handler bases and the dispatcher construct it. */\nexport class ReplySender extends BaseReplySender<SentMessage, GatewayFile> {\n public constructor(\n private readonly interaction: Repliables,\n dispatch: DispatchContext,\n bus: Bus\n ) {\n super({ bus, dispatch, interactionId: interaction.id }, seedState(interaction));\n }\n\n protected async writeReply(\n response: GatewayReplyResponse | string,\n opts?: SendOpts\n ): Promise<SentMessage | undefined> {\n const result = await this.interaction.reply({\n ...this.replyOptions(response, sendFlags(opts)),\n withResponse: true\n });\n return this.createdMessage(result);\n }\n\n protected async writeDefer(opts?: DeferOpts): Promise<void> {\n await this.interaction.deferReply({ flags: deferFlags(opts) });\n }\n\n protected async writeDeferUpdate(): Promise<void> {\n await this.sourceInteraction('deferUpdate').deferUpdate();\n }\n\n protected async writeUpdate(response: GatewayReplyResponse | string): Promise<SentMessage | undefined> {\n const source = this.sourceInteraction('update');\n const result = await source.update({ ...this.updateOptions(response), withResponse: true });\n return this.createdMessage(result);\n }\n\n protected async writeFollowUp(response: GatewayReplyResponse | string, opts?: SendOpts): Promise<SentMessage> {\n return await this.interaction.followUp(this.replyOptions(response, sendFlags(opts)));\n }\n\n protected async writeEditOriginal(response: GatewayReplyResponse | string): Promise<SentMessage> {\n return await this.interaction.editReply(this.editOptions(response));\n }\n\n protected async writeEditTarget(targetId: string, response: GatewayReplyResponse | string): Promise<SentMessage> {\n return await this.interaction.webhook.editMessage(targetId, this.editOptions(response));\n }\n\n protected async writeDeleteOriginal(): Promise<void> {\n await this.interaction.deleteReply();\n }\n\n protected async writeDeleteTarget(targetId: string): Promise<void> {\n await this.interaction.deleteReply(targetId);\n }\n\n protected async writeModal(data: APIModalInteractionResponseCallbackData): Promise<void> {\n const { interaction } = this;\n // unreachable after guardModalSource, the throw re-narrows the union for showModal\n if (interaction.isModalSubmit()) this.rejectModalSubmit();\n await interaction.showModal(data);\n }\n\n protected override guardModalSource(): void {\n // the bases gate this at compile time. a direct sender caller skips that\n if (this.interaction.isModalSubmit()) this.rejectModalSubmit();\n }\n\n private rejectModalSubmit(): never {\n throw new SeedcordError(SeedcordErrorCode.ReplyIllegalAckState, [\n 'showModal',\n 'this interaction is a modal submit',\n 'A modal cannot open another modal.',\n this.routeId\n ]);\n }\n\n private sourceInteraction(method: 'update' | 'deferUpdate'): SourceInteraction {\n const { interaction } = this;\n if (interaction.isMessageComponent()) return interaction;\n if (interaction.isModalSubmit() && interaction.isFromMessage()) return interaction;\n throw new SeedcordError(SeedcordErrorCode.ReplyUpdateWithoutSource, [method, this.routeId]);\n }\n\n private replyOptions(response: GatewayReplyResponse | string, flags: number): InteractionReplyOptions {\n const reply = this.serialize(response);\n return {\n components: reply.components,\n flags,\n ...(reply.allowedMentions && { allowedMentions: reply.allowedMentions }),\n ...(reply.files && { files: reply.files.map(toDjsFile) })\n };\n }\n\n private editOptions(response: GatewayReplyResponse | string): WebhookMessageEditOptions {\n const reply = this.serialize(response);\n return {\n components: reply.components,\n flags: MessageFlags.IsComponentsV2,\n ...(reply.allowedMentions && { allowedMentions: reply.allowedMentions }),\n ...(reply.files && { files: reply.files.map(toDjsFile) })\n };\n }\n\n private updateOptions(response: GatewayReplyResponse | string): InteractionUpdateOptions {\n const reply = this.serialize(response);\n return {\n components: reply.components,\n flags: MessageFlags.IsComponentsV2,\n ...(reply.allowedMentions && { allowedMentions: reply.allowedMentions }),\n ...(reply.files && { files: reply.files.map(toDjsFile) })\n };\n }\n\n private createdMessage(result: InteractionCallbackResponse): SentMessage | undefined {\n return result.resource?.message ?? undefined;\n }\n}\n","import { RepliableHandler as CoreRepliableHandler } from '@seedcord/core';\n\nimport { ReplySender } from '#bot/ReplySender';\n\nimport type { SentMessage } from '#bot/ReplySender';\nimport type { Core } from '#interfaces/Core';\nimport type { GatewayFile } from '#interfaces/ReplyResponse';\nimport type { Repliables } from './interactionTypes';\nimport type { DispatchContext } from '@seedcord/core';\n\n/**\n * Shared base the repliable 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 gateway 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 GatewayFile,\n ReplySender\n> {\n // this chain skips gateway BaseHandler, the only class that defines getEvent\n /** @internal */\n public getEvent(): Event {\n return this.event;\n }\n\n protected buildSender(event: Event, core: Core, dispatch: DispatchContext): ReplySender {\n return new ReplySender(event, dispatch, core.bus);\n }\n}\n","import { RepliableHandler } from '#src/handlers/RepliableHandler';\n\nimport type { ReplySender } from '#bot/ReplySender';\nimport type { Core } from '#interfaces/Core';\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.\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. The discord.js guards narrow it. A catchall reads every repliable 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.customId);\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 { RepliableHandler } from '#handlers/RepliableHandler';\n\nimport type { Core } from '#interfaces/Core';\nimport type { NonModalInteraction, Repliables } from '#src/handlers/interactionTypes';\nimport type { DispatchContext, ModalLike } from '@seedcord/core';\n\n/**\n * Shared base the typed interaction handlers extend.\n *\n * Not a public entry point. Extend {@link SlashHandler}, {@link ButtonHandler}, {@link ModalHandler},\n * or one of the select menu bases instead. This class adds `showModal` on top of the reply members\n * those bases share.\n *\n * @typeParam Repliable - The interaction type this handler processes\n */\nexport abstract class InteractionHandler<Repliable extends Repliables> extends RepliableHandler<Repliable> {\n // keep this ctor. inheriting RepliableHandler's protected one collapses HandlerConstructor to never.\n constructor(event: Repliable, 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(this: InteractionHandler<NonModalInteraction>, modal: ModalLike): Promise<void> {\n return this.sender.showModal(modal);\n }\n}\n","import { buildSlashRoute } from '@seedcord/utils/internal';\n\nimport type { AutocompleteInteraction, ChatInputCommandInteraction } from 'discord.js';\n\n// the controller and seedcord codegen both build routes through buildSlashRoute, so a dispatched\n// interaction always matches its generated registry key\nexport function slashRouteOf(interaction: ChatInputCommandInteraction | AutocompleteInteraction): string {\n const group = interaction.options.getSubcommandGroup(false) ?? undefined;\n const subcommand = interaction.options.getSubcommand(false) ?? undefined;\n return buildSlashRoute(interaction.commandName, subcommand, group);\n}\n","import { SlashRouteBrand } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordTypeError } from '@seedcord/errors/internal';\n\nimport { slashRouteOf } from '#bUtilities/miscellaneous/slashRouteOf';\nimport { InteractionHandler } from '#handlers/interaction/InteractionHandler';\n\nimport type { SlashOptions } from '#inputs/SlashOptions';\nimport type { SlashRegistry } from '@seedcord/core';\nimport type { CacheFor } from '@seedcord/core/internal';\nimport type { CacheType, ChatInputCommandInteraction } from 'discord.js';\nimport type { Promisable } from 'type-fest';\n\ntype SlashMatchArms<Route extends keyof SlashRegistry, Cache extends CacheType, Ret> = {\n [Key in Route]: (options: SlashOptions<Key, Cache>) => Promisable<Ret>;\n};\n\n/**\n * Base class for a chat-input (slash) command handler.\n *\n * Pass the route from the generated registry as the generic, the same string as `@SlashRoute`, then read\n * `this.options` for a single command or `this.match` for several. Command authoring stays plain\n * discord.js, `seedcord codegen` 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 * @typeParam Cache - The interaction cache state. The command's contexts set it.\n *\n * @example\n * ```ts\n * \\@SlashRoute('ban')\n * class BanHandler extends SlashHandler<'ban'> {\n * async execute() {\n * const target = this.options.getUser('target'); // User\n * const reason = this.options.getString('reason'); // string | null\n * }\n * }\n * ```\n */\nexport abstract class SlashHandler<\n Route extends keyof SlashRegistry,\n Cache extends CacheType = CacheFor<Route>\n> extends InteractionHandler<ChatInputCommandInteraction<Cache>> {\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [SlashRouteBrand]?: Route;\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 * Use `this.event.options` directly for anything outside this view, such as `getSubcommand()`.\n * However, for the common case, the methods in this would suffice.\n */\n protected get options(): SlashOptions<Route, Cache> {\n // the djs resolver already carries every getter. SlashOptions is its stricter registry-typed view.\n return this.event.options as SlashOptions<Route, Cache>;\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 * @example\n * ```ts\n * \\@SlashRoute('ban', 'kick')\n * class ModHandler extends SlashHandler<'ban' | 'kick'> {\n * async execute() {\n * await this.match({\n * ban: (options) => this.event.guild?.members.ban(options.getUser('target').id),\n * kick: (options) => this.event.guild?.members.kick(options.getUser('member').id)\n * });\n * }\n * }\n * ```\n */\n protected async match<Ret>(arms: SlashMatchArms<Route, Cache, Ret>): Promise<Ret> {\n const route = slashRouteOf(this.event);\n // justified: SlashMatchArms is keyed by Route literals, so 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, Cache>) => Promisable<Ret>>)[route]\n : undefined;\n if (!arm) throw new SeedcordTypeError(SeedcordErrorCode.SlashMatchArmMissing, [route]);\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 { MenuCacheFor, NamesFor } from '@seedcord/core/internal';\nimport type {\n APIInteractionGuildMember,\n ApplicationCommandType,\n BooleanCache,\n CacheType,\n CacheTypeReducer,\n GuildMember,\n Message,\n MessageContextMenuCommandInteraction,\n User,\n UserContextMenuCommandInteraction\n} from 'discord.js';\nimport type { Promisable } from 'type-fest';\n\ntype UserMenuArms<Names extends NamesFor<ApplicationCommandType.User>, Ret> = {\n [Name in Names]: (\n target: User,\n member: CacheTypeReducer<\n MenuCacheFor<ApplicationCommandType.User, Name>,\n GuildMember,\n APIInteractionGuildMember\n > | null\n ) => Promisable<Ret>;\n};\n\ntype MessageMenuArms<Names extends NamesFor<ApplicationCommandType.Message>, Ret> = {\n [Name in Names]: (\n target: Message<BooleanCache<MenuCacheFor<ApplicationCommandType.Message, Name>>>\n ) => Promisable<Ret>;\n};\n\nfunction armFor<Ret>(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') throw new SeedcordTypeError(SeedcordErrorCode.ContextMenuMatchArmMissing, [name]);\n return arm as (...args: never[]) => Promisable<Ret>;\n}\n\n/**\n * Base class for a user context-menu command handler (right-click a user).\n *\n * Pass the command name(s) as the generic, the same as `@UserContextMenuRoute`. Read the right-clicked\n * user 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 * @typeParam Cache - The interaction cache state. The command's contexts set it.\n *\n * @example\n * ```ts\n * \\@UserContextMenuRoute('View Profile')\n * class ViewProfile extends UserContextMenuHandler<'View Profile'> {\n * async execute() {\n * const user = this.target;\n * }\n * }\n * ```\n */\nexport abstract class UserContextMenuHandler<\n Names extends NamesFor<ApplicationCommandType.User>,\n Cache extends CacheType = MenuCacheFor<ApplicationCommandType.User, Names>\n> extends InteractionHandler<UserContextMenuCommandInteraction<Cache>> {\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(): User {\n return this.event.targetUser;\n }\n\n /** The right-clicked user's guild member, null outside a guild. */\n protected get targetMember(): CacheTypeReducer<Cache, GuildMember, APIInteractionGuildMember> | null {\n return this.event.targetMember;\n }\n\n /** Which of the registered commands fired. */\n protected get commandName(): Names {\n return this.event.commandName 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, both narrowed to the cache state of that\n * one command. The arms must cover every name in the generic. A missing name or an unknown key is a\n * 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.tag}.`),\n * Warn: (user, member) => this.reply(`Warned ${member?.displayName ?? user.tag}.`)\n * });\n * }\n * }\n * ```\n */\n protected async match<Ret>(arms: UserMenuArms<Names, Ret>): Promise<Ret> {\n const arm = armFor<Ret>(arms, this.event.commandName);\n return await (arm as (target: User, member: unknown) => Promisable<Ret>)(this.target, this.targetMember);\n }\n}\n\n/**\n * Base class for a message context-menu command handler (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 * @typeParam Cache - The interaction cache state. The command's contexts set it.\n *\n * @example\n * ```ts\n * \\@MessageContextMenuRoute('Report Message')\n * class ReportMessage extends MessageContextMenuHandler<'Report Message'> {\n * async execute() {\n * const message = this.target;\n * }\n * }\n * ```\n */\nexport abstract class MessageContextMenuHandler<\n Names extends NamesFor<ApplicationCommandType.Message>,\n Cache extends CacheType = MenuCacheFor<ApplicationCommandType.Message, Names>\n> extends InteractionHandler<MessageContextMenuCommandInteraction<Cache>> {\n /** @internal */\n declare readonly [ContextMenuKindBrand]?: ApplicationCommandType.Message;\n /** @internal */\n declare readonly [ContextMenuNamesBrand]?: Names;\n\n protected get target(): Message<BooleanCache<Cache>> {\n return this.event.targetMessage;\n }\n\n /** Which of the registered commands fired. */\n protected get commandName(): Names {\n return this.event.commandName 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, narrowed to the cache state of that one command. The arms must\n * cover every name in the 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 * \\@MessageContextMenuRoute('Report Message', 'Pin Message')\n * class MessageTools extends MessageContextMenuHandler<'Report Message' | 'Pin Message'> {\n * async execute() {\n * await this.match({\n * 'Report Message': (message) => this.report(message),\n * 'Pin Message': (message) => message.pin()\n * });\n * }\n * }\n * ```\n */\n protected async match<Ret>(arms: MessageMenuArms<Names, Ret>): Promise<Ret> {\n const arm = armFor<Ret>(arms, this.event.commandName);\n return await (arm as (target: Message<BooleanCache<Cache>>) => Promisable<Ret>)(this.target);\n }\n}\n","import { BaseHandler as CoreBaseHandler } from '@seedcord/core';\n\nimport type { Core } from '../interfaces';\nimport type { ValidEventTypes } from './interactionTypes';\n\n/**\n * The gateway base, fixes the core base's `TCore` to the gateway {@link Core} and adds the `getEvent`\n * gate hook.\n */\nexport abstract class BaseHandler<ValidEvent extends ValidEventTypes> extends CoreBaseHandler<ValidEvent, Core> {\n // gates infer which event a handler is for from this return type\n public getEvent(): ValidEvent {\n return this.event;\n }\n}\n","import { AutocompleteRouteBrand, reportedWrite } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordTypeError } from '@seedcord/errors/internal';\n\nimport { slashRouteOf } from '#bUtilities/miscellaneous/slashRouteOf';\nimport { BaseHandler } from '#src/handlers/BaseHandler';\n\nimport type { Core } from '#interfaces/Core';\nimport type { AutocompleteOptions, DispatchContext, SlashRegistry } from '@seedcord/core';\nimport type { AutocompletableNames, CacheFor, ChoiceValueOf, EntryFor, FocusedField } from '@seedcord/core/internal';\nimport type { ApplicationCommandOptionChoiceData, AutocompleteInteraction, CacheType } from 'discord.js';\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 ApplicationCommandOptionChoiceData<ChoiceValueOf<EntryFor<Route, Name>>>[]\n ) => Promise<void>\n ) => Promisable<Ret>;\n};\n\n/**\n * Base class for a Discord autocomplete handler.\n *\n * Pass the command route(s) from the generated registry as the generic, the same string(s) as\n * `@AutocompleteRoute`. Branch on the focused field with `this.match`, read already-entered sibling options\n * with `this.options`, and find which command fired with `this.route`.\n *\n * @typeParam Route - One or more route keys from {@link SlashRegistry}, e.g. `'search'` or `'search' | 'find'`.\n * @typeParam Cache - The interaction cache state. The command's contexts set it.\n *\n * @example\n * ```ts\n * \\@AutocompleteRoute('search')\n * class SearchAutocomplete extends AutocompleteHandler<'search'> {\n * async execute() {\n * await this.match({\n * query: (value, respond) => respond([{ name: value, value }])\n * });\n * }\n * }\n * ```\n */\nexport abstract class AutocompleteHandler<\n Route extends keyof SlashRegistry,\n Cache extends CacheType = CacheFor<Route>\n> extends BaseHandler<AutocompleteInteraction<Cache>> {\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [AutocompleteRouteBrand]?: Route;\n\n // keep this ctor. inheriting BaseHandler's protected one collapses HandlerConstructor to never.\n constructor(event: AutocompleteInteraction<Cache>, core: Core, dispatch: DispatchContext) {\n super(event, core, dispatch, 'interactions');\n }\n\n private decodedFocused?: { name: string; value: string };\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 if (this.decodedFocused) return this.decodedFocused as FocusedField<Route>;\n const raw = this.event.options.getFocused(true);\n const focused = { name: raw.name, value: raw.value };\n this.decodedFocused = focused;\n // the registry constrains the names\n return focused as FocusedField<Route>;\n }\n\n /**\n * Run the arm for the focused field. Because an autocomplete always dispatches by which field is\n * focused, match is how you read it. There is no single-field shortcut the way slash/component handlers have one.\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. A\n * focused field with no arm, only reachable from a stale-deployed command, throws at runtime.\n *\n * @param arms - One handler per autocompletable field, keyed by field name.\n * @returns The result of the arm that ran.\n *\n * @example\n * ```ts\n * \\@AutocompleteRoute('search')\n * class SearchAutocomplete extends AutocompleteHandler<'search'> {\n * async execute() {\n * await this.match({\n * query: (value, respond) => respond(titles(value).map((s) => ({ name: s, value: s }))),\n * tag: (value, respond) => respond(tags(value).map((s) => ({ name: s, value: s })))\n * });\n * }\n * }\n * ```\n */\n protected async match<Ret>(arms: FocusedArms<Route, Ret>): Promise<Ret> {\n const { name, value } = this.focused;\n const respond = (choices: readonly ApplicationCommandOptionChoiceData[]): Promise<void> =>\n this.respond(choices);\n // justified: FocusedArms is keyed by field literals, so the Record cast indexes it with the runtime field name.\n type Arm = (\n value: string,\n respond: (choices: readonly ApplicationCommandOptionChoiceData[]) => Promise<void>\n ) => Promisable<Ret>;\n const arm = Object.hasOwn(arms, name) ? (arms as Record<string, Arm>)[name] : undefined;\n if (!arm) throw new SeedcordTypeError(SeedcordErrorCode.AutocompleteMatchArmMissing, [name]);\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 ApplicationCommandOptionChoiceData[]): Promise<void> {\n await reportedWrite(\n { bus: this.core.bus, dispatch: this.dispatch, interactionId: this.event.id },\n 'respond',\n () =>\n // eslint-disable-next-line @seedcord/no-raw-interaction-acks -- this is the base respond and calls djs directly\n this.event.respond(choices)\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) 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 // the djs resolver exposes these getters. AutocompleteOptions is the registry-typed view over it.\n return this.event.options 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 '#bot/ReplySender';\nimport type { GatewayReplyResponse } from '#interfaces/ReplyResponse';\nimport type { DecodedComponentRoute, HasComponentDefs, MatchArms, SingleParams } from '@seedcord/core/internal';\nimport type { AnyCustomId } from '@seedcord/custom-id';\nimport type { AnySelectMenuInteraction, ButtonInteraction, ModalSubmitInteraction } from 'discord.js';\nimport type { Promisable } from 'type-fest';\n\ntype ComponentInteraction = ButtonInteraction | ModalSubmitInteraction | AnySelectMenuInteraction;\n\n/**\n * Shared base the customId-routed component handlers extend.\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 and the route matching those bases share.\n *\n * @typeParam Event - The component interaction type this handler processes\n * @typeParam Defs - The customId route definitions registered on the concrete handler\n */\nexport abstract class ComponentHandler<Event extends ComponentInteraction, Defs extends readonly AnyCustomId[]>\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: GatewayReplyResponse | 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.customId);\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.customId` once (cached after the first read) and throws\n * `StaleCustomId` or `InvalidCustomId` when the wire no longer matches the current shape, which the\n * controller boundary turns into a reply. On a handler registered for several routes this is\n * `never`. Use {@link match} instead.\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`, leaving match as 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 arms cover every registered route prefix, checked at compile time, and a prefix\n * unmatched at runtime throws `CustomIdMatchArmMissing`. Decoding runs before any arm, so a stale or\n * corrupt wire throws before an arm body executes.\n *\n * @param arms - One callback per registered route, keyed by prefix.\n * @returns The result of the arm that ran.\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, so 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) throw new SeedcordTypeError(SeedcordErrorCode.CustomIdMatchArmMissing, [prefix]);\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 { ButtonInteraction, CacheType } from 'discord.js';\n\n/**\n * Base class for a button interaction handler.\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 handler\n * members, or rewrite the source message with `this.update`. Passing different definitions to the decorator\n * and the generic is a compile error.\n *\n * @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof ApproveId]`.\n * @typeParam Cache - The interaction cache state, `'cached'` by default.\n *\n * @example\n * ```ts\n * \\@ButtonRoute(ApproveId)\n * class ApproveButton extends ButtonHandler<[typeof ApproveId]> {\n * async execute() {\n * const { userId } = this.params;\n * await this.reply(`approved <@${userId}>`);\n * }\n * }\n * ```\n */\nexport abstract class ButtonHandler<\n Defs extends readonly AnyCustomId[],\n Cache extends CacheType = 'cached'\n> extends ComponentHandler<ButtonInteraction<Cache>, Defs> {\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 { ComponentHandler } from './ComponentHandler';\n\nimport type { SentMessage } from '#bot/ReplySender';\nimport type { GatewayReplyResponse } from '#interfaces/ReplyResponse';\nimport type { InteractionKind } from '@seedcord/core';\nimport type { AnyCustomId } from '@seedcord/custom-id';\nimport type { CacheType, ModalSubmitFields, ModalSubmitInteraction } from 'discord.js';\n\n/**\n * Base class for a modal submit handler.\n *\n * Register the customId definitions this handler decodes with `@ModalRoute`, list the same ones in the\n * generic, then read `this.params` for a single route or `this.match` for several. Read the submitted\n * inputs from `this.fields`. Reply through the handler members. `showModal` fails compilation on this kind,\n * 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 * @typeParam Cache - The interaction cache state, `'cached'` by default.\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<\n Defs extends readonly AnyCustomId[],\n Cache extends CacheType = 'cached'\n> extends ComponentHandler<ModalSubmitInteraction<Cache>, Defs> {\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [ComponentKindBrand]?: InteractionKind.Modal;\n\n /** The fields this modal submitted, read by custom id. */\n protected get fields(): ModalSubmitFields<Cache> {\n return this.event.fields;\n }\n\n /** Rewrite the message this modal was opened from. Throws when a command opened the modal. */\n protected override update(response: GatewayReplyResponse | 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.isFromMessage()) return;\n throw new SeedcordError(SeedcordErrorCode.ReplyUpdateWithoutSource, [method, this.routeId]);\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 {\n AnySelectMenuInteraction,\n CacheType,\n ChannelSelectMenuInteraction,\n MentionableSelectMenuInteraction,\n RoleSelectMenuInteraction,\n StringSelectMenuInteraction,\n UserSelectMenuInteraction\n} from 'discord.js';\n\n/**\n * Shared base the select menu handlers extend.\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 AnySelectMenuInteraction,\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 return this.event.values;\n }\n}\n\n/**\n * Base class for a string select menu handler.\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 * @typeParam Cache - The interaction cache state, `'cached'` by default.\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<\n Defs extends readonly AnyCustomId[],\n Cache extends CacheType = 'cached'\n> extends SelectMenuHandler<StringSelectMenuInteraction<Cache>, Defs> {\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.\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 * @typeParam Cache - The interaction cache state, `'cached'` by default.\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<\n Defs extends readonly AnyCustomId[],\n Cache extends CacheType = 'cached'\n> extends SelectMenuHandler<UserSelectMenuInteraction<Cache>, Defs> {\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(): UserSelectMenuInteraction<Cache>['users'] {\n return this.event.users;\n }\n\n /** The guild members behind the picked users. Discord resolves these only inside a guild. */\n protected get members(): UserSelectMenuInteraction<Cache>['members'] {\n return this.event.members;\n }\n}\n\n/**\n * Base class for a role select menu handler.\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 * @typeParam Cache - The interaction cache state, `'cached'` by default.\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<\n Defs extends readonly AnyCustomId[],\n Cache extends CacheType = 'cached'\n> extends SelectMenuHandler<RoleSelectMenuInteraction<Cache>, Defs> {\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(): RoleSelectMenuInteraction<Cache>['roles'] {\n return this.event.roles;\n }\n}\n\n/**\n * Base class for a channel select menu handler.\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 * @typeParam Cache - The interaction cache state, `'cached'` by default.\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<\n Defs extends readonly AnyCustomId[],\n Cache extends CacheType = 'cached'\n> extends SelectMenuHandler<ChannelSelectMenuInteraction<Cache>, Defs> {\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(): ChannelSelectMenuInteraction<Cache>['channels'] {\n return this.event.channels;\n }\n}\n\n/**\n * Base class for a mentionable select menu handler.\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 * @typeParam Cache - The interaction cache state, `'cached'` by default.\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<\n Defs extends readonly AnyCustomId[],\n Cache extends CacheType = 'cached'\n> extends SelectMenuHandler<MentionableSelectMenuInteraction<Cache>, Defs> {\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(): MentionableSelectMenuInteraction<Cache>['users'] {\n return this.event.users;\n }\n\n /** The guild members behind the picked users. Discord resolves these only inside a guild. */\n protected get members(): MentionableSelectMenuInteraction<Cache>['members'] {\n return this.event.members;\n }\n\n /** The roles this select picked. */\n protected get roles(): MentionableSelectMenuInteraction<Cache>['roles'] {\n return this.event.roles;\n }\n}\n","import { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordTypeError } from '@seedcord/errors/internal';\n\nimport { BaseHandler } from '#src/handlers/BaseHandler';\n\nimport type { Core } from '#interfaces/Core';\nimport type { ValidNonInteractionKeys } from '#src/handlers/interactionTypes';\nimport type { SingleEventPayload } from './payload';\nimport type { DispatchContext } from '@seedcord/core';\nimport type { ClientEvents } from 'discord.js';\nimport type { Promisable } from 'type-fest';\n\n// a single tuple param would drop the discord.js labels from editor signature help\ntype EventMatchArms<Names extends ValidNonInteractionKeys, Ret> = {\n [Name in Names]: (...args: ClientEvents[Name]) => Promisable<Ret>;\n};\n\n/**\n * Base class for a Discord client event handler.\n *\n * Pass the event name(s) as the generic, the same one(s) as `@RegisterEvent`. A single-event handler reads\n * `this.event` (the payload tuple) directly. A handler registered for several events branches with `this.match`,\n * keyed by event name, since the union of payload tuples is not directly readable.\n *\n * @typeParam Names - One or more `ClientEvents` keys, e.g. `Events.MessageCreate` or `Events.MessageCreate | Events.MessageUpdate`.\n *\n * @example\n * ```ts\n * \\@RegisterEvent([Events.MessageCreate], [Events.MessageUpdate])\n * class PingPong extends EventHandler<Events.MessageCreate | Events.MessageUpdate> {\n * async execute() {\n * await this.match({\n * [Events.MessageCreate]: (message) => message.reply('pong'),\n * [Events.MessageUpdate]: (_oldMessage, edited) => edited.reply('pong')\n * });\n * }\n * }\n * ```\n */\nexport abstract class EventHandler<in out Names extends ValidNonInteractionKeys> extends BaseHandler<\n ClientEvents[Names]\n> {\n // the controller threads this in, undefined when a test constructs the handler directly\n private readonly firedEvent: Names | undefined;\n\n constructor(event: ClientEvents[Names], core: Core, dispatch: DispatchContext, eventName?: Names) {\n super(event, core, dispatch, 'events');\n this.firedEvent = eventName;\n }\n\n // never on a multi-event handler, where reading it is a compile error\n declare protected readonly event: SingleEventPayload<Names>;\n\n /**\n * Run the arm for whichever event fired. Use this only when the handler is registered for several\n * events. A single-event handler reads `this.event` directly. On a multi-event handler `this.event` is\n * `never`, so match is the only way to read the payload.\n *\n * Provide one arm per registered event, keyed by its name, and each arm receives that event's own\n * payload tuple. The arms must cover every event in the generic, a missing event or an unknown key is a\n * compile error.\n *\n * @param arms - One handler per registered event, keyed by event name.\n * @returns The result of the arm that ran.\n *\n * @example\n * ```ts\n * \\@RegisterEvent([Events.MessageCreate], [Events.MessageUpdate])\n * class MessageWatcher extends EventHandler<Events.MessageCreate | Events.MessageUpdate> {\n * async execute() {\n * await this.match({\n * [Events.MessageCreate]: (message) => this.scan(message),\n * [Events.MessageUpdate]: (_old, updated) => this.scan(updated)\n * });\n * }\n * }\n * ```\n */\n protected async match<Ret>(arms: EventMatchArms<Names, Ret>): Promise<Ret> {\n const name = this.firedEvent;\n if (name === undefined) throw new SeedcordTypeError(SeedcordErrorCode.EventMatchArmMissing, ['<no event>']);\n // hasOwn, since a plain lookup for an event named `toString` returns Object.prototype's\n const arm = Object.hasOwn(arms, name) ? (arms as Record<string, unknown>)[name] : undefined;\n if (typeof arm !== 'function') throw new SeedcordTypeError(SeedcordErrorCode.EventMatchArmMissing, [name]);\n // this.event is never on a multi-event handler. getEvent() returns the real tuple.\n return await (arm as (...args: unknown[]) => Promisable<Ret>)(...this.getEvent());\n }\n}\n","import { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\n\nimport { BaseHandler } from '#src/handlers/BaseHandler';\n\nimport type { Core } from '#interfaces/Core';\nimport type { ValidNonInteractionKeys } from '#src/handlers/interactionTypes';\nimport type { SingleEventPayload } from './payload';\nimport type { DispatchContext, EventDispatchResult } from '@seedcord/core';\nimport type { ClientEvents } from 'discord.js';\n\n/**\n * Base class for Discord event middleware.\n *\n * Middleware runs before event handlers and can stop the event by throwing a `Silence`. Unlike `EventHandler`, it\n * runs the SAME for every event it is registered for, so it has no `match`. Specify a single event in the\n * generic and `{ events }` to read `this.event` fully typed. Span several events (or omit `{ events }` for a\n * catchall) and `this.event` narrows to `never`, read `this.eventName` and do work that does not depend on the\n * payload shape. A middleware that needs each event's payload is written one event per class.\n *\n * @typeParam EventName - One or more `ClientEvents` keys. Defaults to every event (catchall).\n */\nexport abstract class EventMiddleware<\n in out EventName extends ValidNonInteractionKeys = ValidNonInteractionKeys\n> extends BaseHandler<ClientEvents[EventName]> {\n // the controller threads this in, undefined when a test constructs the middleware directly\n private readonly firedEvent: EventName | undefined;\n\n constructor(event: ClientEvents[EventName], core: Core, dispatch: DispatchContext, eventName?: EventName) {\n super(event, core, dispatch, 'events');\n this.firedEvent = eventName;\n }\n\n // a concrete tuple for one event only, so reading it on a multi-event middleware is a compile error\n declare protected readonly event: SingleEventPayload<EventName>;\n\n /**\n * The event that fired this middleware. Read it on a catchall or multi-event middleware, where `this.event`\n * is `never`, to do work that does not depend on the payload shape. A single-event middleware reads\n * `this.event` directly and does not need this.\n */\n protected get eventName(): EventName {\n if (this.firedEvent === undefined) throw new SeedcordError(SeedcordErrorCode.EventMiddlewareNameUnavailable);\n return this.firedEvent;\n }\n\n /**\n * Runs once the event finishes, newest middleware first. Every middleware whose `execute()`\n * started gets the call, a stopped chain and a throw included. Implement it to release something\n * this middleware took in `execute()`. A throw in here is logged and goes no further.\n *\n * @param result - `outcome` reports the chain alone. `handlers` holds one entry per handler that\n * ran, empty exactly when the chain stopped the event.\n *\n * @example\n * ```ts\n * // the base declares it. an implementation carries `override`.\n * override async after(result: EventDispatchResult) {\n * this.span.end();\n * }\n * ```\n */\n public after?(result: EventDispatchResult): Promise<void>;\n}\n","import { PaginatorBase } from '@seedcord/core';\n\nimport { ButtonHandler } from '#handlers/interaction/components';\n\nimport type { SentMessage } from '#bot/ReplySender';\nimport type { RepliableHandler } from '#handlers/RepliableHandler';\nimport type { Core } from '#interfaces/Core';\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 { CacheType } from 'discord.js';\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>], CacheType> & { execute(): Promise<void> };\n\nfunction contextOf(interaction: Repliables, core: Core): PageContext {\n return { interaction, user: interaction.user, guild: interaction.guild, core };\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) => ctx.guild?.bans.fetch().then((b) => [...b.values()]) ?? [], { perPage: 10 }),\n * renderItem: (ban) => ban.user.tag\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>], CacheType> {\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 { 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 a gateway subscriber, binding `this.core` to the gateway {@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 a gateway subscriber that delivers its event to a Discord webhook, binding\n * `this.core` to the gateway {@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 { 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/**\n * The options a gateway plugin declares, narrowed to the transport and runtime this base serves.\n * A gateway connection is a websocket that needs a long-lived process.\n */\nexport type GatewayPluginOptions = TypedOmit<PluginOptions, 'transport' | 'runtime'> & {\n transport?: 'gateway';\n runtime?: 'server';\n};\n\n/**\n * Base class for a gateway plugin, binding `this.core` to the gateway {@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<\n Opts extends GatewayPluginOptions = { transport: 'gateway'; runtime: 'server' }\n> extends CorePlugin<Opts, Core> {}\n\nexport type { PluginLifecycleSpec, PluginOptions } from '@seedcord/core/plugin';\n","import { GuildMember, Message, User } from 'discord.js';\n\nimport type { Guild } from 'discord.js';\n\nexport interface EventActor {\n guild: Guild | null;\n member: GuildMember | null;\n user: User | null;\n channelId: string | null;\n}\n\n// each event carries the actor in a different argument\nexport function deriveEventActor(args: unknown): EventActor {\n const tuple = Array.isArray(args) ? (args as unknown[]) : [args];\n for (const arg of tuple) {\n if (arg instanceof Message) {\n return { guild: arg.guild, member: arg.member, user: arg.author, channelId: arg.channelId };\n }\n if (arg instanceof GuildMember) return { guild: arg.guild, member: arg, user: arg.user, channelId: null };\n if (arg instanceof User) return { guild: null, member: null, user: arg, channelId: null };\n }\n return { guild: null, member: null, user: null, channelId: null };\n}\n","import { GuildMember } from 'discord.js';\n\nimport { deriveEventActor } from '#miscellaneous/deriveEventActor';\n\nimport type { Core } from '#interfaces/Core';\nimport type { Repliables, ValidNonInteractionKeys } from '#src/handlers/interactionTypes';\nimport type { EventGateContext, InteractionGateContext } from './Gate';\nimport type { DispatchContext } from '@seedcord/core';\nimport type { ClientEvents } from 'discord.js';\n\nexport function interactionGateContext(\n interaction: Repliables,\n core: Core,\n dispatch: DispatchContext\n): InteractionGateContext {\n const rawMember = interaction.member;\n // an uncached member's roles are already plain ids. the everyone role's id equals the guildId.\n const memberRoleIds =\n rawMember instanceof GuildMember\n ? [...rawMember.roles.cache.keys()].filter((id) => id !== interaction.guildId)\n : (rawMember?.roles ?? []);\n\n return {\n kind: 'interaction',\n interaction,\n core,\n dispatch,\n user: interaction.user,\n guild: interaction.guild,\n member: rawMember instanceof GuildMember ? rawMember : null,\n userId: interaction.user.id,\n guildId: interaction.guildId,\n channelId: interaction.channelId,\n memberRoleIds,\n memberPermissions: interaction.memberPermissions?.bitfield ?? null,\n // djs types appPermissions as non-null on interactions\n appPermissions: interaction.appPermissions.bitfield,\n memberGuildPermissions: rawMember instanceof GuildMember ? rawMember.permissions.bitfield : null,\n appGuildPermissions: interaction.guild?.members.me?.permissions.bitfield ?? null,\n declaredRoute: null // runHandlerGates overwrites this with the matched route\n };\n}\n\nexport function eventGateContext(\n eventName: ValidNonInteractionKeys,\n args: ClientEvents[ValidNonInteractionKeys],\n core: Core,\n dispatch: DispatchContext\n): EventGateContext {\n const actor = deriveEventActor(args);\n return {\n kind: 'event',\n core,\n dispatch,\n eventName,\n payload: args,\n user: actor.user,\n guild: actor.guild,\n member: actor.member,\n userId: actor.user?.id ?? null,\n guildId: actor.guild?.id ?? null,\n channelId: actor.channelId,\n // the cache carries the everyone role (id equals the guild id), filtered out to match the interaction shape\n memberRoleIds: actor.member ? [...actor.member.roles.cache.keys()].filter((id) => id !== actor.guild?.id) : [],\n memberPermissions: actor.member?.permissions.bitfield ?? null,\n appPermissions: null,\n memberGuildPermissions: actor.member?.permissions.bitfield ?? null,\n appGuildPermissions: actor.guild?.members.me?.permissions.bitfield ?? null,\n declaredRoute: null // an event handler doesn't declare a route\n };\n}\n","import * as crypto from 'node:crypto';\n\nimport { Notice, Fault } from '@seedcord/core';\nimport { PublishDefault } from '@seedcord/core/internal';\nimport { Logger } from '@seedcord/logger';\n\nimport { slashRouteOf } from '#bot/utilities/miscellaneous/slashRouteOf';\n\nimport type { Core } from '#interfaces/Core';\nimport type { Repliables } from '#src/handlers/interactionTypes';\nimport type { DispatchContext, FaultSource, SubscriptionData } from '@seedcord/core';\nimport type { RenderContext, ReplyResponse, Nullable } from '@seedcord/types';\nimport type { Guild, User } from 'discord.js';\nimport type { UUID } from 'node:crypto';\n\ntype InteractionFaultSource = Extract<FaultSource, { kind: 'interaction' }>;\ntype EventFaultSource = Extract<FaultSource, { kind: 'event' }>;\n\nconst logger = new Logger('ErrorsHandling', { channel: 'errors' });\n\ninterface EventOrigin {\n name: string;\n handler: string;\n args: unknown;\n channelId: string | null;\n}\n\nexport interface ErrorOrigin {\n interaction?: Repliables;\n event?: EventOrigin;\n origin: string;\n dispatch: DispatchContext;\n guild: Nullable<Guild>;\n user: Nullable<User>;\n metadata?: unknown;\n}\n\nexport interface ExtractedErrorResponse {\n uuid: UUID;\n response: ReplyResponse;\n}\n\nexport function extractErrorResponse(error: Error, core: Core, fault: ErrorOrigin): ExtractedErrorResponse {\n const uuid = crypto.randomUUID();\n const { dispatch } = fault;\n const developerUsername = core.config.notifications?.developerUsername;\n const ctx: RenderContext =\n developerUsername === undefined ? { uuid, dispatch } : { uuid, developerUsername, dispatch };\n\n if (error instanceof Notice) {\n if (error.report) reportFault(error, core, fault, uuid);\n return { uuid, response: error.render(ctx) };\n }\n\n reportRawFault(error, core, fault, uuid);\n\n const Override = core.config.errors?.defaultError;\n const response = Override ? new Override(uuid).render(ctx) : new Fault().render(ctx);\n\n return { uuid, response };\n}\n\nfunction reportFault(denial: Notice, core: Core, fault: ErrorOrigin, uuid: UUID): void {\n logger.error(`${denial.name}: ${uuid}`, denial);\n\n if (fault.interaction) {\n core.bus[PublishDefault]('handledException', {\n denial,\n uuid,\n dispatchId: fault.dispatch.id,\n origin: fault.origin,\n source: buildInteractionSource(fault.interaction)\n });\n } else if (fault.event) {\n core.bus[PublishDefault]('handledException', {\n denial,\n uuid,\n dispatchId: fault.dispatch.id,\n origin: fault.origin,\n source: buildEventSource(fault.event, fault)\n });\n } else {\n // an autocomplete throw has no typed source. unknownException is the only channel left\n core.bus[PublishDefault]('unknownException', {\n uuid,\n dispatchId: fault.dispatch.id,\n error: denial,\n origin: fault.origin,\n ...scalarActors(fault),\n metadata: metadataFor(fault)\n });\n }\n}\n\nfunction causeLine(error: Error): string {\n const { cause } = error;\n if (!Error.isError(cause)) return '';\n const [first] = cause.message.split('\\n');\n return `\\ncaused by ${cause.name}: ${first ?? cause.message}`;\n}\n\nfunction reportRawFault(error: Error, core: Core, fault: ErrorOrigin, uuid: UUID): void {\n const showStack = core.config.errors?.errorStack ?? false;\n if (showStack) logger.error(uuid, error);\n else logger.error(`${uuid} | ${error.message}${causeLine(error)}`);\n\n core.bus[PublishDefault]('unknownException', {\n uuid,\n dispatchId: fault.dispatch.id,\n error,\n origin: fault.origin,\n ...scalarActors(fault),\n metadata: metadataFor(fault)\n });\n}\n\n// the bus payload must stay djs-free\nfunction scalarActors(fault: ErrorOrigin): Pick<SubscriptionData<'unknownException'>, 'guild' | 'user'> {\n return {\n guild: fault.guild ? { id: fault.guild.id, name: fault.guild.name } : undefined,\n user: fault.user ? { id: fault.user.id, username: fault.user.username } : undefined\n };\n}\n\nfunction metadataFor(fault: ErrorOrigin): unknown {\n if (fault.event) return { eventName: fault.event.name, handler: fault.event.handler, args: fault.event.args };\n return fault.metadata;\n}\n\nfunction buildEventSource(event: EventOrigin, fault: ErrorOrigin): EventFaultSource {\n return {\n kind: 'event',\n eventName: event.name,\n handler: event.handler,\n userId: fault.user?.id ?? null,\n guildId: fault.guild?.id ?? null,\n channelId: event.channelId,\n raw: event.args\n };\n}\n\nfunction buildInteractionSource(interaction: Repliables): InteractionFaultSource {\n const command = interaction.isChatInputCommand()\n ? slashRouteOf(interaction)\n : interaction.isContextMenuCommand()\n ? interaction.commandName\n : null;\n const customId =\n interaction.isButton() || interaction.isAnySelectMenu() || interaction.isModalSubmit()\n ? interaction.customId\n : null;\n\n return {\n kind: 'interaction',\n interactionKind: interactionKind(interaction),\n command,\n customId,\n userId: interaction.user.id,\n guildId: interaction.guildId,\n channelId: interaction.channelId,\n interactionId: interaction.id,\n raw: interaction\n };\n}\n\nfunction interactionKind(interaction: Repliables): InteractionFaultSource['interactionKind'] {\n if (interaction.isChatInputCommand()) return 'slash';\n if (interaction.isContextMenuCommand()) return 'context-menu';\n if (interaction.isButton()) return 'button';\n if (interaction.isAnySelectMenu()) return 'select';\n return 'modal';\n}\n","import { Notice, Silence } from '@seedcord/core';\nimport { asError } from '@seedcord/core/internal';\nimport { Logger } from '@seedcord/logger';\nimport { DiscordAPIError } from 'discord.js';\n\nimport { deriveEventActor } from '#miscellaneous/deriveEventActor';\nimport { extractErrorResponse } from '#miscellaneous/extractErrorResponse';\n\nimport type { Core } from '#interfaces/Core';\nimport type { DispatchContext } from '@seedcord/core';\n\nconst logger = new Logger('Faults', { channel: 'errors' });\n\ninterface EventFault {\n readonly eventName: string;\n readonly handlerName: string;\n readonly args: unknown;\n readonly dispatch: DispatchContext;\n}\n\n// a generic event has no reply target\nexport function handleEventFault(caught: unknown, fault: EventFault, core: Core): void {\n const { eventName, handlerName, args, dispatch } = fault;\n if (caught instanceof Silence) {\n if (caught.reason !== undefined && (core.config.errors?.logSilences ?? true)) {\n logger.debug(`Silence: ${caught.reason}`);\n }\n return;\n }\n const error = asError(caught);\n\n const ignore = new Set<number | string>(core.config.errors?.ignoreEventApiCodes ?? []);\n if (error instanceof DiscordAPIError && ignore.has(error.code)) {\n logger.debug(`swallowed api code ${error.code}`);\n return;\n }\n\n if (error instanceof Notice && !error.report) return;\n\n const actor = deriveEventActor(args);\n extractErrorResponse(error, core, {\n event: { name: eventName, handler: handlerName, args, channelId: actor.channelId },\n origin: `event:${eventName}:${handlerName}`,\n dispatch,\n guild: actor.guild,\n user: actor.user\n });\n}\n","import { PublishDefault } from '@seedcord/core/internal';\n\nimport type { Core } from '#interfaces/Core';\nimport type { EventDispatchResult, SubscriptionData } from '@seedcord/core';\nimport type { ClientEvents } from 'discord.js';\n\nexport function reportEventDispatching<Name extends keyof ClientEvents>(\n core: Core,\n dispatchId: string,\n name: Name,\n args: ClientEvents[Name]\n): void {\n // justified: the generic key erases the per-event tuple and args matches name here\n core.bus[PublishDefault]('eventDispatching', { dispatchId, name, args } as SubscriptionData<'eventDispatching'>);\n}\n\n// the interaction side of this is core's reportDispatch\nexport function reportEventDispatched(\n core: Core,\n dispatchId: string,\n name: keyof ClientEvents,\n result: EventDispatchResult,\n startedAt: number\n): void {\n core.bus[PublishDefault]('eventDispatched', {\n dispatchId,\n name,\n outcome: result.outcome,\n handlers: result.handlers.map(({ handler, outcome }) => ({ handler, outcome })),\n durationMs: performance.now() - startedAt\n });\n}\n","/* eslint-disable max-lines -- splitting this would split one event's path from load to dispatch across files */\nimport { DispatchContext } from '@seedcord/core';\nimport { HmrModuleHandler } from '@seedcord/core/hmr';\nimport {\n areRoutes,\n asError,\n EventMetadataKey,\n EventMiddlewareMetadataKey,\n eventResultFor,\n MiddlewareRegistry,\n PublishDefault,\n resultFor,\n runAfter,\n runHandlerGates\n} from '@seedcord/core/internal';\nimport { drainInFlight } from '@seedcord/core/node/internal';\nimport { SeedcordErrorCode, paint } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { Logger } from '@seedcord/logger';\nimport { formatFilePath, hasKeys } from '@seedcord/utils';\nimport { traverseDirectory } from '@seedcord/utils/node';\nimport { Envapter } from 'envapt';\n\nimport { eventMiddlewareMetaOf } from '#bDecorators/Middlewares';\nimport { eventGateContext } from '#bot/gates/runGates';\nimport { handleEventFault } from '#bot/handleEventFault';\nimport { reportEventDispatched, reportEventDispatching } from '#bot/reportEventDispatch';\nimport { EventHandler, EventMiddleware } from '#handlers/event';\n\nimport type { RegisterEventMetadataEntry } from '#bDecorators/Events';\nimport type {\n ConstructableEventHandler,\n EventHandlerConstructor,\n EventMiddlewareConstructor\n} from '#handlers/constructors';\nimport type { Core } from '#interfaces/Core';\nimport type { HandlerResult } from '@seedcord/core';\nimport type { Initializeable, MiddlewareRegistrationOf } from '@seedcord/core/internal';\nimport type { EventFrequency, HmrAware, HmrUpdateEvent } from '@seedcord/types';\nimport type { ClientEvents } from 'discord.js';\n\nconst eventMiddleware: MiddlewareRegistrationOf<EventMiddlewareConstructor, keyof ClientEvents> = (ctor) => {\n const metadata = eventMiddlewareMetaOf(ctor);\n if (!metadata) return undefined;\n return { priority: metadata.priority, ...(metadata.events && { keys: metadata.events }) };\n};\n\ninterface RegisteredEventHandlerEntry {\n readonly ctor: EventHandlerConstructor;\n readonly frequency: EventFrequency;\n}\n\ntype EventArtifact = string;\n\n/**\n * Interactions route through InteractionDispatcher.\n *\n * @internal\n */\nexport class EventDispatcher implements Initializeable, HmrAware {\n private readonly logger = new Logger('Events', { channel: 'events' });\n private isInitialized = false;\n\n private readonly eventMap = new Map<keyof ClientEvents, RegisteredEventHandlerEntry[]>();\n private readonly middlewares = new MiddlewareRegistry<EventMiddlewareConstructor, keyof ClientEvents>(\n eventMiddleware\n );\n private readonly executedOnceHandlers = new Set<EventHandlerConstructor>();\n private readonly attachedEvents = new Set<keyof ClientEvents>();\n\n private readonly inFlight = new Set<Promise<void>>();\n private draining = false;\n\n // a reload reports on the hmr channel\n private loading = false;\n private readonly loadedHandlers: { name: string; from: string }[] = [];\n private readonly loadedMiddlewares: { name: string; from: string }[] = [];\n\n private readonly hmrHandler?: HmrModuleHandler<\n EventHandlerConstructor,\n EventMiddlewareConstructor,\n EventArtifact[]\n >;\n\n public constructor(protected core: Core) {\n const eventsDir = this.core.config.bot.events.path;\n if (!eventsDir) {\n // unreachable today, guards against a path regression\n throw new SeedcordError(SeedcordErrorCode.CoreControllerPathMissing, ['EventDispatcher', 'events']);\n }\n\n if (!Envapter.isDevelopment && !Envapter.isTest) return;\n\n this.hmrHandler = new HmrModuleHandler({\n handlersDir: eventsDir,\n ...(hasKeys(this.core.config.bot.events, ['middlewares']) && {\n middlewaresDir: this.core.config.bot.events.middlewares\n }),\n isHandler: this.isEventHandlerClass.bind(this),\n isMiddleware: this.isMiddlewareClass.bind(this),\n registerHandler: this.registerHandler.bind(this),\n registerMiddleware: this.registerMiddleware.bind(this),\n unregisterHandler: this.unregisterHandler.bind(this),\n unregisterMiddleware: this.unregisterMiddleware.bind(this),\n getArtifacts: this.getArtifacts.bind(this),\n logger: this.logger\n });\n }\n\n private getArtifacts(ctor: EventHandlerConstructor): EventArtifact[] {\n const events: EventArtifact[] = [];\n for (const [event, handlers] of this.eventMap.entries()) {\n if (handlers.some((h) => h.ctor === ctor)) events.push(event);\n }\n return events;\n }\n\n public async init(): Promise<void> {\n if (this.isInitialized) {\n return;\n }\n this.isInitialized = true;\n\n const handlersDir = this.core.config.bot.events.path;\n if (!handlersDir) {\n return;\n }\n\n const middlewareDir = hasKeys(this.core.config.bot.events, ['middlewares'])\n ? this.core.config.bot.events.middlewares\n : undefined;\n\n this.loading = true;\n this.loadedHandlers.length = 0;\n this.loadedMiddlewares.length = 0;\n try {\n if (middlewareDir) await this.loadMiddlewares(middlewareDir);\n await this.loadHandlers(handlersDir);\n } finally {\n this.loading = false;\n }\n\n this.attachToClient();\n this.reportLoad();\n }\n\n private reportLoad(): void {\n const { utils } = this.logger;\n\n utils.summary(\n 'Loaded',\n { 'event handlers': this.loadedHandlers.length, middlewares: this.loadedMiddlewares.length },\n 'debug'\n );\n\n if (this.loadedMiddlewares.length > 0) {\n utils.block('Loaded event middlewares', utils.entries(this.loadedMiddlewares), 'debug');\n }\n\n const perEvent: Record<string, number> = {};\n for (const [event, handlers] of this.eventMap) perEvent[event] = handlers.length;\n\n utils.block(\n 'Loaded event handlers',\n [...utils.entries(this.loadedHandlers), ...utils.counts(perEvent)],\n 'debug'\n );\n }\n\n private async loadHandlers(dir: string): Promise<void> {\n await traverseDirectory(dir, (fullPath, relativePath, imported) => {\n for (const val of Object.values(imported)) {\n if (!this.isEventHandlerClass(val)) continue;\n this.registerHandler(val, relativePath);\n this.hmrHandler?.trackHandler(fullPath, val);\n }\n });\n }\n\n private async loadMiddlewares(dir: string): Promise<void> {\n await traverseDirectory(dir, (fullPath, relativePath, imported) => {\n for (const val of Object.values(imported)) {\n if (!this.isMiddlewareClass(val)) continue;\n\n this.registerMiddleware(val, relativePath);\n this.hmrHandler?.trackMiddleware(fullPath, val);\n }\n });\n }\n\n /** @internal */\n public async onHmr(event: HmrUpdateEvent): Promise<void> {\n await this.hmrHandler?.handle(event);\n }\n\n private unregisterHandler(handlerClass: EventHandlerConstructor, artifacts?: EventArtifact[]): void {\n const events = artifacts ?? [...this.eventMap.keys()];\n for (const event of events) {\n const handlers = this.eventMap.get(event as keyof ClientEvents);\n if (!handlers) continue;\n const index = handlers.findIndex((h) => h.ctor === handlerClass);\n if (!(index !== -1)) {\n continue;\n }\n\n handlers.splice(index, 1);\n if (handlers.length === 0) {\n this.eventMap.delete(event as keyof ClientEvents);\n }\n }\n // leaving executedOnceHandlers alone keeps a rollback-restored ctor spent\n }\n\n private unregisterMiddleware(middlewareCtor: EventMiddlewareConstructor): void {\n this.middlewares.unregister(middlewareCtor);\n }\n\n private registerMiddleware(middlewareCtor: EventMiddlewareConstructor, relativePath: string): void {\n const registration = this.middlewares.register(middlewareCtor);\n if (!registration || !this.loading) return;\n\n // the events are the only place a dev sees that a middleware is scoped\n const scope = registration.keys\n ? `${registration.priority}, ${registration.keys.join(', ')}`\n : registration.priority;\n this.loadedMiddlewares.push({\n name: `${middlewareCtor.name} (${String(scope)})`,\n from: formatFilePath(relativePath)\n });\n }\n\n // a returned value is the throw that stopped the event before any handler ran\n private async runMiddlewares<KeyOfEvents extends keyof ClientEvents>(\n eventName: KeyOfEvents,\n args: ClientEvents[KeyOfEvents],\n dispatch: DispatchContext,\n ran: EventMiddleware[]\n ): Promise<{ caught: unknown } | null> {\n for (const Middleware of this.middlewares.chainFor(eventName)) {\n try {\n const middleware = new Middleware(args, this.core, dispatch, eventName);\n // pushed before the await because a middleware that throws still gets its after()\n ran.push(middleware);\n await middleware.execute();\n } catch (caught) {\n handleEventFault(\n caught,\n { eventName: String(eventName), handlerName: Middleware.name, args, dispatch },\n this.core\n );\n return { caught };\n }\n }\n\n return null;\n }\n\n private isEventHandlerClass(obj: unknown): obj is EventHandlerConstructor {\n if (typeof obj !== 'function') return false;\n return obj.prototype instanceof EventHandler && Reflect.hasMetadata(EventMetadataKey, obj);\n }\n\n private isMiddlewareClass(obj: unknown): obj is EventMiddlewareConstructor {\n if (typeof obj !== 'function') return false;\n return obj.prototype instanceof EventMiddleware && Reflect.hasMetadata(EventMiddlewareMetadataKey, obj);\n }\n\n private registerHandler(handlerClass: EventHandlerConstructor, relativePath: string): void {\n const raw = Reflect.getMetadata(EventMetadataKey, handlerClass) as unknown;\n\n const register = (key: keyof ClientEvents, frequency: EventFrequency): void => {\n let handlers = this.eventMap.get(key);\n if (!handlers) {\n handlers = [];\n this.eventMap.set(key, handlers);\n }\n\n handlers.push({\n ctor: handlerClass,\n frequency\n });\n\n // a post-init (hmr) registration can add an event with no client listener yet\n if (this.isInitialized && !this.attachedEvents.has(key)) {\n this.attachListener(key);\n }\n };\n\n if (Array.isArray(raw)) {\n for (const entry of raw as RegisterEventMetadataEntry<keyof ClientEvents>[]) {\n register(entry.event, entry.frequency);\n }\n } else {\n const names = areRoutes(raw) ? raw : typeof raw === 'string' ? [raw] : [];\n\n for (const name of names) {\n register(name as keyof ClientEvents, 'on');\n }\n }\n\n const from = formatFilePath(relativePath);\n if (this.loading) this.loadedHandlers.push({ name: handlerClass.name, from });\n }\n\n private attachToClient(): void {\n for (const [eventName] of this.eventMap) {\n this.attachListener(eventName);\n }\n }\n\n private attachListener(eventName: keyof ClientEvents): void {\n if (this.attachedEvents.has(eventName)) return;\n this.attachedEvents.add(eventName);\n\n const handlerEntries = this.eventMap.get(eventName);\n this.logger.debug(\n `Attaching ${paint.sky.bold(eventName)} to the client with ${paint.mute(handlerEntries?.length ?? 0)} handler(s)`\n );\n\n this.core.bot.client.on(eventName, (...args: ClientEvents[typeof eventName]) => {\n if (this.draining) return;\n const run = this.processEvent(eventName, args).catch((caught: unknown) => {\n const error = asError(caught);\n this.logger.error(`[${paint.coral.bold('UNHANDLED ERROR AT ROOT')}] ${error.name}`, error.stack);\n this.core.bus[PublishDefault]('unhandledEventError', { error });\n });\n this.inFlight.add(run);\n void run.finally(() => this.inFlight.delete(run));\n });\n }\n\n public stopAccepting(): void {\n this.draining = true;\n }\n\n public drain(timeoutMs: number): Promise<void> {\n return drainInFlight(this.inFlight, timeoutMs, this.logger, 'Events');\n }\n\n private async processEvent<KeyOfEvents extends keyof ClientEvents>(\n eventName: KeyOfEvents,\n args: ClientEvents[KeyOfEvents]\n ): Promise<void> {\n const startedAt = performance.now();\n const handlerEntries = this.eventMap.get(eventName);\n if (!handlerEntries || handlerEntries.length === 0) return;\n\n const handlersToExecute = handlerEntries.filter(\n (entry) => entry.frequency !== 'once' || !this.executedOnceHandlers.has(entry.ctor)\n );\n\n if (handlersToExecute.length === 0) return;\n\n const dispatch = new DispatchContext(`event:${String(eventName)}`);\n reportEventDispatching(this.core, dispatch.id, eventName, args);\n\n const ran: EventMiddleware[] = [];\n const handlers: HandlerResult[] = [];\n let stopped: { caught: unknown } | null = null;\n\n try {\n stopped = await this.runMiddlewares(eventName, args, dispatch, ran);\n if (stopped) return;\n\n for (const entry of handlersToExecute) {\n // marked spent before running so a rethrow can't re-fire it\n if (entry.frequency === 'once') {\n // a concurrent fire could have claimed it during the runMiddlewares await\n if (this.executedOnceHandlers.has(entry.ctor)) continue;\n this.executedOnceHandlers.add(entry.ctor);\n }\n\n handlers.push(await this.processHandler(eventName, entry.ctor, args, dispatch));\n }\n } finally {\n const result = eventResultFor(stopped, handlers);\n reportEventDispatched(this.core, dispatch.id, eventName, result, startedAt);\n await runAfter(ran, result, this.logger);\n }\n }\n\n private async processHandler<KeyOfEvents extends keyof ClientEvents>(\n eventName: KeyOfEvents,\n Ctor: EventHandlerConstructor,\n args: ClientEvents[KeyOfEvents],\n dispatch: DispatchContext\n ): Promise<HandlerResult> {\n try {\n this.logger.debug(`Processing ${paint.sky.bold(eventName)} with ${paint.mute(Ctor.name)}`);\n // the event map paired this name with this class\n const handler = new (Ctor as ConstructableEventHandler)(args, this.core, dispatch, eventName);\n const eventCtx = eventGateContext(eventName, args, this.core, dispatch);\n await runHandlerGates(Ctor, eventCtx);\n await handler.execute();\n return { handler: Ctor.name, outcome: 'handled' };\n } catch (caught) {\n handleEventFault(\n caught,\n { eventName: String(eventName), handlerName: Ctor.name, args, dispatch },\n this.core\n );\n return { handler: Ctor.name, ...resultFor(caught) };\n }\n }\n}\n","import { InteractionHandler } from '#handlers/interaction/InteractionHandler';\n\nimport type { Repliables } from '#src/handlers/interactionTypes';\n\nexport class UnhandledRepliable extends InteractionHandler<Repliables> {\n async execute(): Promise<void> {\n await this.reply('Feature not implemented yet.');\n }\n}\n","import { AutocompleteHandler } from '#handlers/interaction/AutocompleteHandler';\n\nimport type { SlashRegistry } from '@seedcord/core';\nimport type { CacheType } from 'discord.js';\n\n// eslint-disable-next-line @seedcord/interaction-handler-missing-route -- the dispatcher's autocomplete fallback, never registered\nexport class UnhandledAutocomplete extends AutocompleteHandler<keyof SlashRegistry, CacheType> {\n async execute(): Promise<void> {\n await this.respond([]);\n }\n}\n","import { RESTJSONErrorCodes } from 'discord.js';\n\n/**\n * Discord API error codes that mean a dead end on an interaction, a dead token, a double ack, or a gone\n * message. Nothing to show the user and no bug to report, so the boundary's fault-card send drops them.\n *\n * @internal\n */\nexport const HARMLESS_API_CODES: ReadonlySet<number | string> = new Set([\n RESTJSONErrorCodes.UnknownInteraction,\n RESTJSONErrorCodes.InteractionHasAlreadyBeenAcknowledged,\n RESTJSONErrorCodes.UnknownMessage\n]);\n","import { Notice, Silence } from '@seedcord/core';\nimport { asError, reportedWrite } from '@seedcord/core/internal';\nimport { Logger } from '@seedcord/logger';\nimport { DiscordAPIError } from 'discord.js';\n\nimport { ReplySender } from '#bot/ReplySender';\nimport { extractErrorResponse } from '#miscellaneous/extractErrorResponse';\n\nimport { HARMLESS_API_CODES } from './harmlessApiCodes';\n\nimport type { Core } from '#interfaces/Core';\nimport type { ValidInteractionTypes } from '#src/handlers/interactionTypes';\nimport type { DispatchContext } from '@seedcord/core';\nimport type { ReplyResponse } from '@seedcord/types';\nimport type { AutocompleteInteraction } from 'discord.js';\n\nconst logger = new Logger('Faults', { channel: 'errors' });\n\nexport async function handleInteractionFault(\n caught: unknown,\n interaction: ValidInteractionTypes,\n core: Core,\n dispatch: DispatchContext,\n sender?: ReplySender\n): Promise<void> {\n const { routeId } = dispatch;\n if (caught instanceof Silence) {\n if (caught.reason !== undefined && (core.config.errors?.logSilences ?? true)) {\n logger.debug(`Silence: ${caught.reason}`);\n }\n return;\n }\n const error = asError(caught);\n\n const ignore = new Set<number | string>(core.config.errors?.ignoreApiCodes ?? []);\n if (error instanceof DiscordAPIError && ignore.has(error.code)) {\n logger.debug(`swallowed api code ${error.code}`);\n return;\n }\n\n // discord does not accept a message on an autocomplete. the fault is only reported.\n if (interaction.isAutocomplete()) {\n extractErrorResponse(error, core, {\n origin: routeId,\n dispatch,\n guild: interaction.guild,\n user: interaction.user,\n metadata: interaction\n });\n // empty choices clear the client's loading spinner\n await sendEmptyChoices(interaction, core, dispatch);\n return;\n }\n\n const { response } = extractErrorResponse(error, core, {\n interaction,\n origin: routeId,\n dispatch,\n guild: interaction.guild,\n user: interaction.user,\n metadata: interaction\n });\n // the handler's own sender carries its ack state. a middleware throw arrives without one\n const liveSender = sender ?? new ReplySender(interaction, dispatch, core.bus);\n await sendGuarded(liveSender, response, error instanceof Notice ? error.ephemeral : true);\n}\n\nasync function sendEmptyChoices(\n interaction: AutocompleteInteraction,\n core: Core,\n dispatch: DispatchContext\n): Promise<void> {\n const telemetry = { bus: core.bus, dispatch, interactionId: interaction.id };\n try {\n await reportedWrite(telemetry, 'respond', () => interaction.respond([]));\n } catch (error) {\n logger.debug(`autocomplete empty-choices send failed: ${String(error)}`);\n }\n}\n\n// only this send swallows the harmless codes. a handler's own write still reports them\nasync function sendGuarded(sender: ReplySender, response: ReplyResponse, ephemeral: boolean): Promise<void> {\n try {\n await sender.send(response, { ephemeral });\n } catch (error) {\n if (error instanceof DiscordAPIError && HARMLESS_API_CODES.has(error.code)) {\n logger.debug(`reply send hit harmless code ${error.code}`);\n return;\n }\n logger.error('reply send failed', error);\n }\n}\n","/* eslint-disable max-lines -- one handler method per interaction type keeps the router in one file */\nimport { DispatchContext, InteractionKind } from '@seedcord/core';\nimport { HmrModuleHandler } from '@seedcord/core/hmr';\nimport {\n InteractionMetadataKey,\n interactionRoutesOf,\n asError,\n outcomeFor,\n queuedMsFor,\n reportDispatch,\n interactionMiddleware,\n InteractionMiddlewareMetadataKey,\n MiddlewareRegistry,\n PublishDefault,\n resultFor,\n runAfter,\n runHandlerGates,\n slowGateMonitor\n} from '@seedcord/core/internal';\nimport { drainInFlight } from '@seedcord/core/node/internal';\nimport { prefixOf } from '@seedcord/custom-id';\nimport { SeedcordErrorCode, paint } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { Logger } from '@seedcord/logger';\nimport { formatFilePath, hasKeys } from '@seedcord/utils';\nimport { traverseDirectory } from '@seedcord/utils/node';\nimport { Events } from 'discord.js';\nimport { Envapter } from 'envapt';\n\nimport { CONFIRM_DEF } from '#bot/confirm/reserved';\nimport { UnhandledAutocomplete, UnhandledRepliable } from '#bot/defaults';\nimport { interactionGateContext } from '#bot/gates/runGates';\nimport { handleInteractionFault } from '#bot/handleInteractionFault';\nimport { slashRouteOf } from '#bUtilities/miscellaneous/slashRouteOf';\nimport { AutocompleteHandler, InteractionMiddleware } from '#handlers/interaction';\nimport { InteractionHandler } from '#handlers/interaction/InteractionHandler';\nimport { RepliableHandler } from '#handlers/RepliableHandler';\n\nimport type { ReplySender } from '#bot/ReplySender';\nimport type {\n ConstructableHandler,\n HandlerConstructor,\n InteractionMiddlewareConstructor\n} from '#handlers/constructors';\nimport type { InteractionOf } from '#handlers/interaction/middlewareKinds';\nimport type { Core } from '#interfaces/Core';\nimport type { Repliables, ValidInteractionTypes } from '#src/handlers/interactionTypes';\nimport type { DispatchOutcome, DispatchResult, MiddlewareKind } from '@seedcord/core';\nimport type { Initializeable, ContextMenuLeaves } from '@seedcord/core/internal';\nimport type { CustomIdMatcher, HmrAware, HmrUpdateEvent } from '@seedcord/types';\nimport type {\n AutocompleteInteraction,\n ButtonInteraction,\n ChannelSelectMenuInteraction,\n ChatInputCommandInteraction,\n Interaction,\n MentionableSelectMenuInteraction,\n MessageContextMenuCommandInteraction,\n ModalSubmitInteraction,\n RoleSelectMenuInteraction,\n StringSelectMenuInteraction,\n UserContextMenuCommandInteraction,\n UserSelectMenuInteraction\n} from 'discord.js';\n\ninterface InteractionArtifact {\n routeType: InteractionKind;\n routes: string[];\n}\n\ninterface DispatchedHandler {\n execute(): Promise<void>;\n}\n\ninterface DispatchReportRow {\n readonly interaction: Interaction;\n readonly kind: InteractionKind;\n readonly fallback: boolean;\n readonly startedAt: number;\n readonly queuedMs: number;\n readonly dispatchId: string;\n readonly routeId: string;\n}\n\ninterface BeforeHandler {\n readonly HandlerCtor: HandlerConstructor;\n readonly kind: InteractionKind;\n readonly interaction: Interaction;\n readonly dispatch: DispatchContext;\n readonly sender: ReplySender | undefined;\n readonly ran: InteractionMiddleware[];\n readonly declaredRoute: string | undefined;\n}\n\nexport class InteractionDispatcher implements Initializeable, HmrAware {\n private readonly logger = new Logger('Interactions', { channel: 'interactions' });\n private isInitialized = false;\n\n private readonly maps: Record<InteractionKind, Map<string, HandlerConstructor>> = {\n [InteractionKind.Slash]: new Map(),\n [InteractionKind.Button]: new Map(),\n [InteractionKind.Modal]: 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.MessageContextMenu]: new Map(),\n [InteractionKind.UserContextMenu]: new Map(),\n [InteractionKind.Autocomplete]: new Map()\n };\n\n private readonly handlerFiles = new Map<HandlerConstructor, string>();\n\n private readonly keysToIgnore = new Set<CustomIdMatcher>();\n private readonly middlewares = new MiddlewareRegistry<InteractionMiddlewareConstructor>(interactionMiddleware);\n\n private readonly inFlight = new Set<Promise<void>>();\n private draining = false;\n\n // a reload reports on the hmr channel\n private loading = false;\n private readonly loadedHandlers: { name: string; from: string }[] = [];\n private readonly loadedMiddlewares: { name: string; from: string }[] = [];\n\n private readonly hmrHandler?: HmrModuleHandler<\n HandlerConstructor,\n InteractionMiddlewareConstructor,\n InteractionArtifact[]\n >;\n\n constructor(protected core: Core) {\n const ignoredKeysFromConfig = hasKeys(this.core.config.bot.interactions, ['ignoreCustomIds'])\n ? this.core.config.bot.interactions.ignoreCustomIds\n : undefined;\n if (ignoredKeysFromConfig) {\n for (const ignoredKey of ignoredKeysFromConfig) this.keysToIgnore.add(ignoredKey);\n }\n\n // the in-process getConfirmation() collector consumes these clicks, so the global router would double-ack them\n this.keysToIgnore.add(CONFIRM_DEF);\n\n const interactionsDir = this.core.config.bot.interactions.path;\n if (!interactionsDir) {\n throw new SeedcordError(SeedcordErrorCode.CoreControllerPathMissing, [\n 'InteractionDispatcher',\n 'interactions'\n ]);\n }\n\n if (!Envapter.isDevelopment && !Envapter.isTest) return;\n this.hmrHandler = new HmrModuleHandler({\n handlersDir: interactionsDir,\n ...(hasKeys(this.core.config.bot.interactions, ['middlewares']) &&\n this.core.config.bot.interactions.middlewares && {\n middlewaresDir: this.core.config.bot.interactions.middlewares\n }),\n isHandler: this.isHandlerClass.bind(this),\n isMiddleware: this.isMiddlewareClass.bind(this),\n registerHandler: this.registerHandler.bind(this),\n registerMiddleware: this.registerMiddleware.bind(this),\n unregisterHandler: this.unregisterHandler.bind(this),\n unregisterMiddleware: this.unregisterMiddleware.bind(this),\n getArtifacts: this.getArtifacts.bind(this),\n logger: this.logger\n });\n }\n\n public warnUnhandledRoutes(commandLeaves: Iterable<string>): void {\n for (const route of commandLeaves) {\n if (!this.maps[InteractionKind.Slash].has(route)) {\n this.logger.warn(\n `Slash route ${paint.sky.bold(route)} has no registered ${paint.bold('@SlashRoute')} handler.`\n );\n }\n }\n }\n\n public warnUnhandledContextMenuRoutes(leaves: ContextMenuLeaves): void {\n for (const name of leaves.user) {\n if (!this.maps[InteractionKind.UserContextMenu].has(name)) {\n this.logger.warn(\n `User context menu ${paint.sky.bold(name)} has no registered ${paint.bold('@ContextMenuRoute')} handler.`\n );\n }\n }\n for (const name of leaves.message) {\n if (!this.maps[InteractionKind.MessageContextMenu].has(name)) {\n this.logger.warn(\n `Message context menu ${paint.sky.bold(name)} has no registered ${paint.bold('@ContextMenuRoute')} handler.`\n );\n }\n }\n }\n\n private getArtifacts(handlerClass: HandlerConstructor): InteractionArtifact[] {\n return interactionRoutesOf(handlerClass).map(([routeType, routes]) => ({ routeType, routes }));\n }\n\n public async init(): Promise<void> {\n if (this.isInitialized) return;\n\n this.isInitialized = true;\n\n const handlersDir = this.core.config.bot.interactions.path;\n // the constructor already threw on this\n if (!handlersDir) return;\n\n const middlewareDir = hasKeys(this.core.config.bot.interactions, ['middlewares'])\n ? this.core.config.bot.interactions.middlewares\n : undefined;\n\n this.loading = true;\n this.loadedHandlers.length = 0;\n this.loadedMiddlewares.length = 0;\n try {\n if (middlewareDir) await this.loadMiddlewares(middlewareDir);\n await this.loadHandlers(handlersDir);\n } finally {\n this.loading = false;\n }\n\n this.attachToClient();\n this.reportLoad();\n }\n\n private reportLoad(): void {\n const { utils } = this.logger;\n\n utils.summary(\n 'Loaded',\n { 'interaction handlers': this.loadedHandlers.length, middlewares: this.loadedMiddlewares.length },\n 'debug'\n );\n\n if (this.loadedMiddlewares.length > 0) {\n utils.block('Loaded middlewares', utils.entries(this.loadedMiddlewares), 'debug');\n }\n\n utils.block(\n 'Loaded interaction handlers',\n [\n ...utils.entries(this.loadedHandlers),\n ...utils.counts({\n slash: this.maps[InteractionKind.Slash].size,\n buttons: this.maps[InteractionKind.Button].size,\n modals: this.maps[InteractionKind.Modal].size,\n 'string selects': this.maps[InteractionKind.StringMenu].size,\n 'user selects': this.maps[InteractionKind.UserMenu].size,\n 'role selects': this.maps[InteractionKind.RoleMenu].size,\n 'channel selects': this.maps[InteractionKind.ChannelMenu].size,\n 'mentionable selects': this.maps[InteractionKind.MentionableMenu].size,\n 'message menus': this.maps[InteractionKind.MessageContextMenu].size,\n 'user menus': this.maps[InteractionKind.UserContextMenu].size,\n autocomplete: this.maps[InteractionKind.Autocomplete].size\n })\n ],\n 'debug'\n );\n }\n\n private async loadHandlers(dir: string): Promise<void> {\n await traverseDirectory(dir, (fullPath, relativePath, imported) => {\n for (const val of Object.values(imported)) {\n if (!this.isHandlerClass(val)) continue;\n this.registerHandler(val, relativePath);\n this.hmrHandler?.trackHandler(fullPath, val);\n }\n });\n }\n\n private async loadMiddlewares(dir: string): Promise<void> {\n await traverseDirectory(dir, (fullPath, relativePath, imported) => {\n for (const val of Object.values(imported)) {\n if (!this.isMiddlewareClass(val)) continue;\n\n this.registerMiddleware(val, relativePath);\n this.hmrHandler?.trackMiddleware(fullPath, val);\n }\n });\n }\n\n private registerMiddleware(middlewareCtor: InteractionMiddlewareConstructor, relativePath: string): void {\n const metadata = this.middlewares.register(middlewareCtor);\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: `${middlewareCtor.name} (${String(scope)})`,\n from: formatFilePath(relativePath)\n });\n }\n\n private isHandlerClass(obj: unknown): obj is HandlerConstructor {\n if (typeof obj !== 'function') return false;\n return (\n (obj.prototype instanceof InteractionHandler && Reflect.hasMetadata(InteractionMetadataKey, obj)) ||\n (obj.prototype instanceof AutocompleteHandler && Reflect.hasMetadata(InteractionMetadataKey, obj))\n );\n }\n\n private isMiddlewareClass(obj: unknown): obj is InteractionMiddlewareConstructor {\n if (typeof obj !== 'function') return false;\n return (\n obj.prototype instanceof InteractionMiddleware && Reflect.hasMetadata(InteractionMiddlewareMetadataKey, obj)\n );\n }\n\n private registerHandler(handlerClass: HandlerConstructor, relativePath: string): void {\n const from = formatFilePath(relativePath);\n // a partial registration would orphan routes and break hmr rollback\n const writes: { kind: InteractionKind; route: string }[] = [];\n\n for (const [kind, routes] of interactionRoutesOf(handlerClass)) {\n for (const route of routes) {\n const existing = this.maps[kind].get(route);\n // a different class on the same route would silently shadow (last write wins)\n if (existing && existing !== handlerClass) {\n throw new SeedcordError(SeedcordErrorCode.InteractionDuplicateRoute, [\n `${kind}:${route}`,\n // a stale hmr artifact list can leave a class in a route map after its entry here is gone\n `${existing.name} (${this.handlerFiles.get(existing) ?? 'unknown file'})`,\n `${handlerClass.name} (${from})`\n ]);\n }\n writes.push({ kind, route });\n }\n }\n\n if (writes.length === 0) return;\n for (const { kind, route } of writes) this.maps[kind].set(route, handlerClass);\n this.handlerFiles.set(handlerClass, from);\n\n if (this.loading) this.loadedHandlers.push({ name: handlerClass.name, from });\n }\n\n public async onHmr(event: HmrUpdateEvent): Promise<void> {\n await this.hmrHandler?.handle(event);\n }\n\n private unregisterHandler(handlerClass: HandlerConstructor, artifacts?: InteractionArtifact[]): void {\n this.handlerFiles.delete(handlerClass);\n for (const { routeType, routes } of artifacts ?? this.getArtifacts(handlerClass)) {\n for (const route of routes) this.maps[routeType].delete(route);\n }\n }\n\n private unregisterMiddleware(middlewareCtor: InteractionMiddlewareConstructor): void {\n this.middlewares.unregister(middlewareCtor);\n }\n\n private attachToClient(): void {\n this.core.bot.client.on(Events.InteractionCreate, (interaction) => {\n if (this.draining) return;\n this.core.bus[PublishDefault]('anyInteraction', { interaction });\n const run = this.handleInteraction(interaction).catch((caught: unknown) => {\n const error = asError(caught);\n this.logger.error(`[${paint.coral.bold('UNHANDLED ERROR AT ROOT')}] ${error.name}`, error.stack);\n this.core.bus[PublishDefault]('unhandledInteractionError', { error });\n });\n this.inFlight.add(run);\n void run.finally(() => this.inFlight.delete(run));\n });\n }\n\n public stopAccepting(): void {\n this.draining = true;\n }\n\n public drain(timeoutMs: number): Promise<void> {\n return drainInFlight(this.inFlight, timeoutMs, this.logger, 'Interactions');\n }\n\n private async handleCustomIdInteraction<TInteraction extends Interaction & { customId: string }>(\n interaction: TInteraction,\n kind: InteractionKind\n ): Promise<void> {\n if ([...this.keysToIgnore].some((matcher) => matcher.owns(interaction.customId))) return;\n\n // the stable prefix (the routeKey minus its shape hash) routes an older-shape wire to its handler\n const prefix = prefixOf(interaction.customId);\n // no route matches an empty prefix. the unhandled default answers it like http does\n if (!prefix)\n this.logger.warn(`${paint.sky.bold(kind)} has invalid customId: ${paint.mute(interaction.customId)}`);\n\n await this.processInteraction(interaction, kind, () => prefix);\n }\n\n private async processInteraction<TInteraction extends Interaction>(\n interaction: TInteraction,\n kind: InteractionKind,\n extractKey: (i: TInteraction) => string,\n fallback: HandlerConstructor = UnhandledRepliable\n ): Promise<void> {\n const key = extractKey(interaction);\n const startedAt = performance.now();\n const queuedMs = queuedMsFor(interaction.id);\n const matched = this.maps[kind].get(key);\n\n const HandlerCtor = matched ?? fallback;\n // an empty key means a customId seedcord never minted\n const dispatch = new DispatchContext(`${kind}:${key || 'unrouted'}`);\n const report = this.reporterFor({\n interaction,\n kind,\n fallback: !matched,\n startedAt,\n queuedMs,\n dispatchId: dispatch.id,\n routeId: dispatch.routeId\n });\n\n // outside the try so the fault boundary keeps the handler's ack state\n let sender: ReplySender | undefined;\n const ran: InteractionMiddleware[] = [];\n let result: DispatchResult = { outcome: 'handled' };\n try {\n const handler = this.buildHandler(HandlerCtor, interaction as Repliables, dispatch, key, !matched);\n if (handler instanceof RepliableHandler) sender = handler.sender;\n\n const refusal = await this.refusalBeforeHandler({\n HandlerCtor,\n kind,\n interaction,\n dispatch,\n sender,\n ran,\n declaredRoute: matched ? dispatch.routeId : undefined\n });\n if (refusal) {\n result = resultFor(refusal.caught);\n await this.answer(refusal.caught, interaction as ValidInteractionTypes, dispatch, sender, report);\n return;\n }\n await handler.execute();\n report('handled');\n } catch (caught) {\n // a refusal already labelled the dispatch. a throw from answering it must not relabel.\n if (result.outcome === 'handled') result = resultFor(caught);\n await this.answer(caught, interaction as ValidInteractionTypes, dispatch, sender, report);\n } finally {\n await runAfter(ran, result, this.logger);\n }\n }\n\n private async answer(\n caught: unknown,\n interaction: ValidInteractionTypes,\n dispatch: DispatchContext,\n sender: ReplySender | undefined,\n report: (outcome: DispatchOutcome) => void\n ): Promise<void> {\n try {\n await handleInteractionFault(caught, interaction, this.core, dispatch, sender);\n } finally {\n report(outcomeFor(caught));\n }\n }\n\n private buildHandler(\n HandlerCtor: HandlerConstructor,\n interaction: Repliables,\n dispatch: DispatchContext,\n key: string,\n isFallback: boolean\n ): DispatchedHandler {\n if (isFallback) {\n this.logger.warn(`No handler found for key ${paint.sky.bold(key)}. Falling back to ${HandlerCtor.name}.`);\n }\n this.logger.debug(`Processing ${paint.sky.bold(key)} with ${paint.mute(HandlerCtor.name)}`);\n // in a union of both handler bases, the event parameter is never. the maps pair each kind with its class.\n return new (HandlerCtor as ConstructableHandler)(interaction as never, this.core, dispatch);\n }\n\n // answering a refusal can throw into the catch and report twice\n private reporterFor(row: DispatchReportRow): (outcome: DispatchOutcome) => void {\n let reported = false;\n return (outcome) => {\n if (reported) return;\n reported = true;\n reportDispatch(this.core.bus, {\n dispatchId: row.dispatchId,\n routeId: row.routeId,\n interactionId: row.interaction.id,\n kind: row.kind,\n outcome,\n startedAt: row.startedAt,\n fallback: row.fallback,\n userId: row.interaction.user.id,\n guildId: row.interaction.guildId,\n queuedMs: row.queuedMs\n });\n };\n }\n\n // a returned value is the throw that stops the dispatch before the handler runs\n private async refusalBeforeHandler(step: BeforeHandler): Promise<{ caught: unknown } | null> {\n const { HandlerCtor, kind, interaction, dispatch, sender, ran, declaredRoute } = step;\n\n if (kind !== InteractionKind.Autocomplete && sender) {\n try {\n await this.runMiddlewares(kind, interaction as Repliables, dispatch, sender, ran);\n } catch (caught) {\n return { caught };\n }\n }\n\n // @Gated rejects autocomplete at compile time, since it has no reply target. this is the backstop\n if (interaction.isAutocomplete()) return null;\n return this.gateRefusal(HandlerCtor, interaction as Repliables, dispatch, declaredRoute);\n }\n\n private async runMiddlewares(\n kind: MiddlewareKind,\n interaction: Repliables,\n dispatch: DispatchContext,\n sender: ReplySender,\n ran: InteractionMiddleware[]\n ): Promise<void> {\n for (const Middleware of this.middlewares.chainFor(kind)) {\n // chainFor picked this kind. the interaction is the one the class declares.\n const event = interaction as InteractionOf<MiddlewareKind>;\n const middleware = new Middleware(event, this.core, dispatch, sender);\n // pushed before the await because a middleware that throws still gets its after()\n ran.push(middleware);\n await middleware.execute();\n }\n }\n\n private async gateRefusal(\n HandlerCtor: HandlerConstructor,\n interaction: Repliables,\n dispatch: DispatchContext,\n declaredRoute: string | undefined\n ): Promise<{ caught: unknown } | null> {\n const monitor = slowGateMonitor();\n try {\n await runHandlerGates(\n HandlerCtor,\n interactionGateContext(interaction, this.core, dispatch),\n declaredRoute,\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(declaredRoute ?? null);\n }\n }\n\n private async handleInteraction(interaction: Interaction): Promise<void> {\n switch (true) {\n case interaction.isChatInputCommand(): {\n await this.handleSlashCommand(interaction);\n break;\n }\n case interaction.isButton(): {\n await this.handleButton(interaction);\n break;\n }\n case interaction.isModalSubmit(): {\n await this.handleModal(interaction);\n break;\n }\n case interaction.isStringSelectMenu(): {\n await this.handleStringSelectMenu(interaction);\n break;\n }\n case interaction.isUserSelectMenu(): {\n await this.handleUserSelectMenu(interaction);\n break;\n }\n case interaction.isRoleSelectMenu(): {\n await this.handleRoleSelectMenu(interaction);\n break;\n }\n case interaction.isChannelSelectMenu(): {\n await this.handleChannelSelectMenu(interaction);\n break;\n }\n case interaction.isMentionableSelectMenu(): {\n await this.handleMentionableSelectMenu(interaction);\n break;\n }\n case interaction.isMessageContextMenuCommand(): {\n await this.handleMessageContextMenu(interaction);\n break;\n }\n case interaction.isUserContextMenuCommand(): {\n await this.handleUserContextMenu(interaction);\n break;\n }\n case interaction.isAutocomplete(): {\n await this.handleAutocomplete(interaction);\n break;\n }\n default: {\n this.logger.warn(`Unhandled interaction type: ${interaction.type}`);\n break;\n }\n }\n }\n\n private async handleSlashCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n const route = slashRouteOf(interaction);\n await this.processInteraction(interaction, InteractionKind.Slash, () => route);\n }\n\n private async handleButton(interaction: ButtonInteraction): Promise<void> {\n await this.handleCustomIdInteraction(interaction, InteractionKind.Button);\n }\n\n private async handleModal(interaction: ModalSubmitInteraction): Promise<void> {\n await this.handleCustomIdInteraction(interaction, InteractionKind.Modal);\n }\n\n private async handleStringSelectMenu(interaction: StringSelectMenuInteraction): Promise<void> {\n await this.handleCustomIdInteraction(interaction, InteractionKind.StringMenu);\n }\n\n private async handleUserSelectMenu(interaction: UserSelectMenuInteraction): Promise<void> {\n await this.handleCustomIdInteraction(interaction, InteractionKind.UserMenu);\n }\n\n private async handleRoleSelectMenu(interaction: RoleSelectMenuInteraction): Promise<void> {\n await this.handleCustomIdInteraction(interaction, InteractionKind.RoleMenu);\n }\n\n private async handleChannelSelectMenu(interaction: ChannelSelectMenuInteraction): Promise<void> {\n await this.handleCustomIdInteraction(interaction, InteractionKind.ChannelMenu);\n }\n\n private async handleMentionableSelectMenu(interaction: MentionableSelectMenuInteraction): Promise<void> {\n await this.handleCustomIdInteraction(interaction, InteractionKind.MentionableMenu);\n }\n\n private async handleMessageContextMenu(interaction: MessageContextMenuCommandInteraction): Promise<void> {\n await this.processInteraction(interaction, InteractionKind.MessageContextMenu, () => interaction.commandName);\n }\n\n private async handleUserContextMenu(interaction: UserContextMenuCommandInteraction): Promise<void> {\n await this.processInteraction(interaction, InteractionKind.UserContextMenu, () => interaction.commandName);\n }\n\n private async handleAutocomplete(interaction: AutocompleteInteraction): Promise<void> {\n const route = slashRouteOf(interaction);\n await this.processInteraction(interaction, InteractionKind.Autocomplete, () => route, UnhandledAutocomplete);\n }\n}\n","import { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { GatewayIntentBits, InteractionContextType, IntentsBitField } from 'discord.js';\n\nimport type { BitFieldResolvable, GatewayIntentsString } from 'discord.js';\n\ninterface DeployableCommand {\n readonly name: string;\n toJSON(): { contexts?: InteractionContextType[] | undefined };\n}\n\n// discord reads a command with no contexts as reachable from all three\nfunction reachesGuilds(command: DeployableCommand): boolean {\n const contexts = command.toJSON().contexts;\n if (!contexts || contexts.length === 0) return true;\n return contexts.includes(InteractionContextType.Guild);\n}\n\n// djs resolves interaction.guild out of a cache that stays empty without the Guilds intent\nexport function assertGuildsIntent(\n intents: BitFieldResolvable<GatewayIntentsString, number>,\n commands: readonly DeployableCommand[]\n): void {\n if ((IntentsBitField.resolve(intents) & GatewayIntentBits.Guilds) !== 0) return;\n\n const needing = commands.filter((command) => reachesGuilds(command)).map((command) => command.name);\n if (needing.length === 0) return;\n\n throw new SeedcordError(SeedcordErrorCode.MissingGuildsIntent, [needing.join(', ')]);\n}\n","import { CommandRegistry, DRAIN_TASK_TIMEOUT_MS, DRAIN_WINDOW_MS, ShutdownPhase } from '@seedcord/core/node/internal';\nimport { SeedcordErrorCode, paint } from '@seedcord/errors';\nimport { SeedcordError, validateDiscordToken } from '@seedcord/errors/internal';\nimport { Logger } from '@seedcord/logger';\nimport { Client, Events } from 'discord.js';\nimport { Envapt } from 'envapt/legacy';\n\nimport { EventDispatcher } from '#bControllers/EventDispatcher';\nimport { InteractionDispatcher } from '#bControllers/InteractionDispatcher';\nimport { assertGuildsIntent } from '#miscellaneous/assertGuildsIntent';\n\nimport { EmojiInjector } from './injectors/EmojiInjector';\n\nimport type { Core } from '#interfaces/Core';\nimport type { HmrAware, HmrUpdateEvent } from '@seedcord/types';\nimport type { BitFieldResolvable, GatewayIntentsString } from 'discord.js';\n\nconst UNBIND_TIMEOUT_MS = 2000;\nconst LOGOUT_TIMEOUT_MS = 2000;\n\nconst loggerSlot = Symbol('seedcord:bot:logger');\nconst initSlot = Symbol('seedcord:bot:init');\nconst controllersSlot = Symbol('seedcord:bot:controllers');\n\ninterface Controllers {\n readonly interactions?: InteractionDispatcher | undefined;\n readonly events?: EventDispatcher | undefined;\n readonly commandRegistry?: CommandRegistry | undefined;\n}\n\n/**\n * The Discord client and its controllers. Access it through `core.bot`.\n */\nexport class Bot implements HmrAware {\n @Envapt<string>('DISCORD_BOT_TOKEN', {\n converter: (raw) => validateDiscordToken(raw)\n })\n declare public readonly botToken: string;\n\n readonly #logger = new Logger('Bot', { channel: 'bot' });\n\n /** @internal */\n readonly [loggerSlot]: Logger = this.#logger;\n #isInitialized = false;\n\n readonly #intents: BitFieldResolvable<GatewayIntentsString, number>;\n readonly #client: Client;\n readonly #emojiInjector: EmojiInjector;\n readonly #interactions?: InteractionDispatcher;\n readonly #events?: EventDispatcher;\n readonly #commandRegistry?: CommandRegistry;\n\n /** @internal */\n public async onHmr(event: HmrUpdateEvent): Promise<void> {\n if (this.#interactions) await this.#interactions.onHmr(event);\n if (this.#events) await this.#events.onHmr(event);\n if (this.#commandRegistry) await this.#commandRegistry.onHmr(event);\n }\n\n /** @internal */\n constructor(core: Core) {\n this.#intents = core.config.bot.clientOptions.intents;\n this.#client = new Client(core.config.bot.clientOptions);\n\n if (core.config.bot.interactions.path) {\n this.#interactions = new InteractionDispatcher(core);\n }\n if (core.config.bot.events.path) {\n this.#events = new EventDispatcher(core);\n }\n\n if (core.config.bot.commands.path) this.#commandRegistry = new CommandRegistry(core);\n\n this.#emojiInjector = new EmojiInjector(core);\n\n this.#registerShutdownTasks(core);\n }\n\n /** @internal */\n public get [controllersSlot](): Controllers {\n return { interactions: this.#interactions, events: this.#events, commandRegistry: this.#commandRegistry };\n }\n\n /** @internal */\n public get applicationId(): string {\n const { application } = this.#client;\n if (!application) throw new SeedcordError(SeedcordErrorCode.CoreApplicationUnavailable);\n return application.id;\n }\n\n #registerShutdownTasks(core: Core): void {\n core.shutdown.addTask(\n ShutdownPhase.Unbind,\n 'stop-dispatch',\n () => {\n this.#stopAccepting();\n return Promise.resolve();\n },\n UNBIND_TIMEOUT_MS\n );\n core.shutdown.addTask(ShutdownPhase.Drain, 'drain-dispatch', () => this.#drain(), DRAIN_TASK_TIMEOUT_MS);\n core.shutdown.addTask(ShutdownPhase.Logout, 'stop-bot', async () => await this.#stop(), LOGOUT_TIMEOUT_MS);\n }\n\n #stopAccepting(): void {\n this.#interactions?.stopAccepting();\n this.#events?.stopAccepting();\n }\n\n async #drain(): Promise<void> {\n // runs through allSettled since a rejecting drain must not abort the other dispatcher's drain\n await Promise.allSettled([this.#interactions?.drain(DRAIN_WINDOW_MS), this.#events?.drain(DRAIN_WINDOW_MS)]);\n }\n\n /** @internal */\n public async [initSlot](): Promise<void> {\n if (this.#isInitialized) {\n return;\n }\n this.#isInitialized = true;\n\n const token = this.botToken;\n\n if (this.#interactions) await this.#interactions.init();\n if (this.#events) await this.#events.init();\n\n await this.#login(token);\n\n await this.#emojiInjector.init();\n\n if (!this.#commandRegistry) {\n return;\n }\n\n await this.#commandRegistry.init();\n assertGuildsIntent(this.#intents, this.#commandRegistry.allCommands());\n await this.#commandRegistry.setCommands();\n this.#interactions?.warnUnhandledRoutes(this.#commandRegistry.routeLeaves());\n this.#interactions?.warnUnhandledContextMenuRoutes(this.#commandRegistry.contextMenuLeaves());\n }\n\n async #stop(): Promise<void> {\n this.#client.removeAllListeners();\n\n await this.#logout();\n }\n\n async #login(token: string): Promise<Bot> {\n const ready: PromiseWithResolvers<void> = Promise.withResolvers();\n this.#client.once(Events.ClientReady, () => ready.resolve());\n void this.#client.login(token);\n await ready.promise;\n this.#logger.info(`Logged in as ${paint.sky.bold(this.#client.user?.username)}!`);\n return this;\n }\n\n async #logout(): Promise<void> {\n await this.#client.destroy();\n this.#logger.info(paint.coral.bold('Logged out of Discord!'));\n }\n\n public get client(): Client {\n return this.#client;\n }\n}\n\nexport function botLoggerOf(bot: Bot): Logger {\n return bot[loggerSlot];\n}\n\nexport function initBot(bot: Bot): Promise<void> {\n return bot[initSlot]();\n}\n\n// the gateway integration tests call these three off a live host\nexport function interactionsOf(bot: Bot): InteractionDispatcher | undefined {\n return bot[controllersSlot].interactions;\n}\n\nexport function eventsOf(bot: Bot): EventDispatcher | undefined {\n return bot[controllersSlot].events;\n}\n\nexport function commandRegistryOf(bot: Bot): CommandRegistry | undefined {\n return bot[controllersSlot].commandRegistry;\n}\n","/** Package version */\nexport const version = process.env.PACKAGE_VERSION ?? '0.0.0';\n","import { Bus } from '@seedcord/core';\nimport { busLoggerOf, HmrManager, setBotColor } from '@seedcord/core/internal';\nimport { CoordinatedShutdown, CoordinatedStartup, Pluggable } from '@seedcord/core/node';\nimport { HealthCheck, shutdownOf, StartupPhase, SubscriberLoader } from '@seedcord/core/node/internal';\nimport { LoggerChannelRegistry } from '@seedcord/logger';\nimport { installNodeDefaults } from '@seedcord/logger/node';\nimport { MemoryRateLimiter } from '@seedcord/rate-limiter';\nimport { HostAugmentTarget, HostVersion, SeedcordBrand } from '@seedcord/types/internal';\nimport { Envapter } from 'envapt';\n\nimport { botLoggerOf, Bot, initBot } from './bot/Bot';\nimport { version as packageVersion } from './version';\n\nimport type { GatewayConfig } from './interfaces/Config';\nimport type { REST } from '@discordjs/rest';\nimport type { IRateLimiter } from '@seedcord/types';\nimport type { SeedcordInstance } from '@seedcord/types/internal';\n\n/**\n * The gateway bot host. Opens a discord.js gateway session, discovers handlers, and runs\n * coordinated startup and shutdown. Attach plugins with `attach()`.\n */\n// an `implements Core` clause breaks a bot's full lib check once codegen adds its plugins to Core\nexport class Seedcord extends Pluggable<'gateway', 'server'> implements SeedcordInstance {\n // the CLI reads these to detect and augment the instance\n /** @internal */\n public readonly [SeedcordBrand] = true;\n /** @internal */\n public readonly [HostAugmentTarget] = '@seedcord/gateway';\n /** @internal */\n public readonly [HostVersion]: string = packageVersion;\n\n private readonly healthCheck?: HealthCheck | undefined;\n private readonly hmrManager: HmrManager;\n\n /** @see {@link Bus} */\n public readonly bus: Bus;\n\n private readonly subscribers: SubscriberLoader;\n\n /** @see {@link Bot} */\n public readonly bot: Bot;\n\n /** The discord.js client's REST client. Its token is set during the Login phase. */\n public readonly rest: REST;\n\n /** The bot's Discord application id. Throws if you read it before login. */\n public get applicationId(): string {\n return this.bot.applicationId;\n }\n\n /** @see {@link IRateLimiter} */\n public readonly rateLimiter: IRateLimiter;\n\n /**\n * @param config - Bot configuration including paths and Discord client options\n * @throws A **SeedcordError** When attempting to create multiple instances (singleton)\n */\n constructor(public readonly config: GatewayConfig) {\n super(new CoordinatedShutdown(config.lifecycle?.shutdownDeadline), new CoordinatedStartup());\n\n installNodeDefaults(config.logger);\n setBotColor(config.botColor);\n\n this.hmrManager = new HmrManager();\n this.hmrManager.init();\n this.bus = new Bus(this);\n this.subscribers = new SubscriberLoader(this.bus, config.subscribers.path);\n this.bot = new Bot(this);\n this.rest = this.bot.client.rest;\n this.rateLimiter = config.store ?? new MemoryRateLimiter();\n this.healthCheck = HealthCheck.fromOption(shutdownOf(this), config.healthCheck);\n\n this.registerStartupTasks();\n }\n\n /** The bot's discord username, populated after login. */\n public get username(): string | undefined {\n return this.bot.client.user?.username;\n }\n\n protected static override reset(host?: object): boolean {\n if (!super.reset(host)) return false;\n // reset() would drop the dev TUI's log sink\n LoggerChannelRegistry.instance.configure({});\n return true;\n }\n\n private registerStartupTasks(): void {\n if (Envapter.isDevelopment || Envapter.isTest) this.registerHmrAwareModules();\n\n this.startup.addTask(StartupPhase.Configuration, 'bus-initialization', async () => {\n busLoggerOf(this.bus).utils.initialization('Subscribers', 'start');\n await this.subscribers.init();\n busLoggerOf(this.bus).utils.initialization('Subscribers', 'end');\n });\n\n this.startup.addTask(StartupPhase.Login, 'bot-initialization', async () => {\n botLoggerOf(this.bot).utils.initialization('Bot', 'start');\n await initBot(this.bot);\n botLoggerOf(this.bot).utils.initialization('Bot', 'end');\n });\n\n const { healthCheck } = this;\n if (healthCheck) {\n this.startup.addTask(StartupPhase.Ready, 'health-check', async () => {\n healthCheck.logger.utils.initialization('HealthCheck', 'start');\n await healthCheck.init();\n healthCheck.logger.utils.initialization('HealthCheck', 'end');\n });\n }\n }\n\n /**\n * Starts the bot and runs all initialization tasks\n *\n * @returns This Seedcord instance when initialized\n */\n public async start(): Promise<this> {\n try {\n await super.init();\n } catch (caught) {\n // shutdown releases any resource opened before the failure, then rethrow\n await shutdownOf(this).run(1, false);\n Seedcord.reset(this);\n throw caught;\n }\n return this;\n }\n\n private registerHmrAwareModules(): void {\n this.startup.addTask(StartupPhase.Configuration, 'hmr-registration', async () => {\n this.hmrManager.register(this.bot);\n this.hmrManager.register(this.subscribers);\n for (const plugin of this.plugins) {\n this.hmrManager.register(plugin);\n }\n await Promise.resolve();\n });\n }\n}\n"],"mappings":"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"}