@seedcord/gateway 0.1.0-next.5 → 0.1.0-next.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,13 +1,12 @@
1
1
  import { AnyCustomId, AutocompletableNames, BaseReplySender, ChoiceValueOf, EntryFor, FocusedField, GateFitsWith, HasComponentDefs, MatchArms, ModalLike, PageCursor, SingleParams, SlashOptions as SlashOptions$1 } from "@seedcord/core/internal";
2
- import { AutocompleteOptions, BaseHandler, BuilderComponent, Bus, CoreBase, DispatchContext, Gate, GateContextBase, GateNoticeOptions, GuildPermissionsContext, Initializeable, Notice, PageView, PermissionScope, RepliableHandler as RepliableHandler$1, RequiredOf, SelectMenuKind, SlashOptionRegistry, Subscriber as Subscriber$1, SubscriptionKey, WebhookLog as WebhookLog$1 } from "@seedcord/core";
2
+ import { ArraySource as ArraySource$1, AutocompleteOptions, BaseHandler, Bus, ContextMenuKind, CoreBase, CursorSource as CursorSource$1, DispatchContext, Gate, GateContextBase, GateNoticeOptions, GuildPermissionsContext, Initializeable, Notice, PaginatorBase, PaginatorConfig, PermissionNoticeOverrides, PermissionScope, RepliableHandler as RepliableHandler$1, RequiredOf, SelectMenuKind, SlashOptionRegistry, Subscriber as Subscriber$1, SubscriptionKey, WebhookLog as WebhookLog$1 } from "@seedcord/core";
3
3
  import { Logger } from "@seedcord/logger";
4
- import { ActionRowBuilder, ButtonBuilder, ContextMenuCommandBuilder, SlashCommandBuilder } from "@discordjs/builders";
5
- import { APIInteractionGuildMember, APIMessageComponentEmoji, APIModalInteractionResponseCallbackData, AnySelectMenuInteraction, ApplicationCommand, ApplicationCommandOptionChoiceData, ApplicationCommandType, ApplicationEmoji, AutocompleteInteraction, BooleanCache, ButtonInteraction, ButtonStyle, CacheType, CacheTypeReducer, ChannelSelectMenuInteraction, ChatInputCommandInteraction, Client, ClientEvents, ClientOptions, Collection, CommandInteractionOption, ContextMenuCommandInteraction, Events, Guild, GuildEmoji, GuildMember, Interaction, MentionableSelectMenuInteraction, Message, MessageContextMenuCommandInteraction, ModalSubmitInteraction, Role, RoleSelectMenuInteraction, Snowflake, StringSelectMenuInteraction, TextChannel, TextChannelResolvable, User, UserContextMenuCommandInteraction, UserSelectMenuInteraction } from "discord.js";
6
- import { Plugin as Plugin$1, PluginContext, PluginLifecycleSpec, PluginOptions, PluginOptions as PluginOptions$1 } from "@seedcord/core/plugin";
7
- import { CoordinatedShutdown, CoordinatedStartup, Pluggable, PluginCapabilities } from "@seedcord/core/node/internal";
4
+ import { APIInteractionGuildMember, APIModalInteractionResponseCallbackData, AnySelectMenuInteraction, ApplicationCommandOptionChoiceData, ApplicationCommandType, ApplicationEmoji, AutocompleteInteraction, BooleanCache, ButtonInteraction, ButtonStyle, CacheType, CacheTypeReducer, ChannelSelectMenuInteraction, ChatInputCommandInteraction, Client, ClientEvents, ClientOptions, CommandInteractionOption, ContextMenuCommandInteraction, Events, Guild, GuildEmoji, GuildMember, Interaction, MentionableSelectMenuInteraction, Message, MessageContextMenuCommandInteraction, ModalSubmitInteraction, Role, RoleSelectMenuInteraction, StringSelectMenuInteraction, TextChannel, User, UserContextMenuCommandInteraction, UserSelectMenuInteraction } from "discord.js";
5
+ import { Plugin as Plugin$1, PluginLifecycleSpec, PluginOptions, PluginOptions as PluginOptions$1 } from "@seedcord/core/plugin";
6
+ import { CoordinatedShutdown, CoordinatedStartup, Pluggable } from "@seedcord/core/node/internal";
8
7
  import { SeedcordBrand, SeedcordInstance } from "@seedcord/types/internal";
8
+ import { BotConfig, Config, DeferOpts, EmojiMap, EventFrequency, HealthCheckOption, HmrAware, HmrUpdateEvent, IRateLimiter, ReplyResponse, SendOpts, TypedOmit } from "@seedcord/types";
9
9
  import { REST } from "@discordjs/rest";
10
- import { BotConfig, Config, DeferOpts, EmojiMap, EventFrequency, HealthCheckOption, HmrAware, HmrUpdateEvent, IRateLimiter, ReplyResponse, SendOpts, TypedOmit, V2Component } from "@seedcord/types";
11
10
  export * from "@seedcord/errors";
12
11
  export * from "@seedcord/core";
13
12
  export * from "@seedcord/logger";
@@ -16,14 +15,6 @@ export * from "@seedcord/utils";
16
15
  export * from "@seedcord/event-emitter";
17
16
  export type * from "@seedcord/types";
18
17
 
19
- //#region src/plugin-capabilities.d.ts
20
- declare module '@seedcord/core' {
21
- interface PluginCapabilityTypes {
22
- client: Client;
23
- rest: REST;
24
- }
25
- }
26
- //#endregion
27
18
  //#region src/subscriptions.d.ts
28
19
  declare module '@seedcord/core/internal' {
29
20
  interface DefaultSubscriptions {
@@ -84,82 +75,6 @@ interface GatewayConfig extends Config {
84
75
  healthCheck?: HealthCheckOption;
85
76
  }
86
77
  //#endregion
87
- //#region src/bot/utilities/miscellaneous/contextMenuLeaves.d.ts
88
- /** The registered context-menu command names, split by kind, deduplicated. @internal */
89
- interface ContextMenuLeaves {
90
- readonly user: Set<string>;
91
- readonly message: Set<string>;
92
- }
93
- //#endregion
94
- //#region src/bot/controllers/CommandRegistry.d.ts
95
- /** The command collections Discord returns from each scope's deploy, keyed by command id. */
96
- interface DeployResult {
97
- global: Collection<Snowflake, ApplicationCommand>;
98
- guilds: Collection<Snowflake, Collection<Snowflake, ApplicationCommand>>;
99
- }
100
- /**
101
- * Manages Discord application command registration and deployment.
102
- *
103
- * Scans command directories, builds command structures, and registers both global and guild-scoped commands
104
- * to Discord's API. Accessed via `core.bot.commands`. Do not construct it directly.
105
- */
106
- declare class CommandRegistry implements Initializeable, HmrAware {
107
- private readonly core;
108
- private readonly onDeployed?;
109
- private readonly logger;
110
- private isInitialised;
111
- readonly globalCommands: (SlashCommandBuilder | ContextMenuCommandBuilder)[];
112
- readonly guildCommands: Collection<string, (SlashCommandBuilder | ContextMenuCommandBuilder)[]>;
113
- private readonly ctorToCommand;
114
- private loading;
115
- private readonly loadedCommands;
116
- private readonly hmrHandler?;
117
- private readonly pendingEvents;
118
- constructor(core: Core, onDeployed?: ((result: DeployResult) => void) | undefined);
119
- private getArtifacts;
120
- /** @internal */
121
- init(): Promise<void>;
122
- private reportLoad;
123
- /** @internal */
124
- refresh(shouldRefresh?: boolean): Promise<void>;
125
- /** @internal */
126
- onHmr(event: HmrUpdateEvent): Promise<void>;
127
- private loadCommands;
128
- private isCommandClass;
129
- private registerCommand;
130
- private unregisterCommand;
131
- /** @internal */
132
- setCommands(): Promise<DeployResult>;
133
- /** The deduplicated slash route keys across every global and guild command. @internal */
134
- routeLeaves(): Set<string>;
135
- /** The registered context-menu command names, split by kind, across every global and guild command. @internal */
136
- contextMenuLeaves(): ContextMenuLeaves;
137
- }
138
- //#endregion
139
- //#region src/bot/injectors/CommandMentionInjector.d.ts
140
- /** Each registered slash route mapped to its mention string. */
141
- type InjectedMentionMap = { [K in keyof SlashOptionRegistry]: string };
142
- /**
143
- * Ready-to-send command mention strings, keyed by {@link SlashOptionRegistry}.
144
- *
145
- * A value is a clickable `</name:id>` when the command's id resolved from the deploy, otherwise the plain
146
- * `/name` text. Populated by {@link CommandMentionInjector} after each deploy.
147
- */
148
- declare const CommandMentions: InjectedMentionMap;
149
- //#endregion
150
- //#region src/bot/injectors/EmojiInjector.d.ts
151
- /**
152
- * The global {@link Emojis} accessor type. Each key resolves to its precise class, `GuildEmoji` for a `'guild'`
153
- * tag and `ApplicationEmoji` for an `'application'` tag, the tags `seedcord codegen` writes into {@link EmojiMap}.
154
- */
155
- type InjectedEmojiMap = { [K in keyof EmojiMap]: EmojiMap[K] extends 'guild' ? GuildEmoji : ApplicationEmoji };
156
- /**
157
- * Global emoji mappings object
158
- *
159
- * @see {@link EmojiMap}
160
- */
161
- declare const Emojis: InjectedEmojiMap;
162
- //#endregion
163
78
  //#region src/bot/Bot.d.ts
164
79
  /**
165
80
  * The Discord client and its controllers. Access it through `core.bot`.
@@ -173,13 +88,12 @@ declare class Bot implements Initializeable, HmrAware {
173
88
  private readonly interactions?;
174
89
  private readonly events?;
175
90
  private readonly emojiInjector;
176
- readonly commands?: CommandRegistry;
177
- readonly emojis: InjectedEmojiMap;
178
- readonly mentions: InjectedMentionMap;
91
+ private readonly commandRegistry?;
179
92
  /** @internal */
180
93
  onHmr(event: HmrUpdateEvent): Promise<void>;
181
94
  /** @internal */
182
95
  constructor(core: Core);
96
+ private applicationId;
183
97
  private registerShutdownTasks;
184
98
  private stopAccepting;
185
99
  private drain;
@@ -836,7 +750,6 @@ declare abstract class SlashHandler<Route extends keyof SlashOptionRegistry, Cac
836
750
  }
837
751
  //#endregion
838
752
  //#region src/handlers/interaction/ContextMenuHandler.d.ts
839
- type ContextMenuKind = ApplicationCommandType.User | ApplicationCommandType.Message;
840
753
  type InteractionFor<Kind extends ContextMenuKind, Cache extends CacheType> = Kind extends ApplicationCommandType.User ? UserContextMenuCommandInteraction<Cache> : MessageContextMenuCommandInteraction<Cache>;
841
754
  type TargetFor<Kind extends ContextMenuKind, Cache extends CacheType> = Kind extends ApplicationCommandType.User ? User : Message<BooleanCache<Cache>>;
842
755
  type TargetMemberFor<Kind extends ContextMenuKind, Cache extends CacheType> = Kind extends ApplicationCommandType.User ? CacheTypeReducer<Cache, GuildMember, APIInteractionGuildMember> | null : never;
@@ -1057,6 +970,11 @@ declare abstract class ButtonHandler<Defs extends readonly AnyCustomId[], Cache
1057
970
  declare abstract class ModalHandler<Defs extends readonly AnyCustomId[], Cache extends CacheType = 'cached'> extends ComponentHandler<ModalSubmitInteraction<Cache>, Defs> {
1058
971
  /** @internal */
1059
972
  readonly __component?: 'modal';
973
+ /** Rewrite the message this modal was opened from. Throws when a command opened the modal. */
974
+ protected update(response: ReplyResponse | string): Promise<SentMessage>;
975
+ /** Acknowledge the submit without changing the source message. Throws when a command opened the modal. */
976
+ protected deferUpdate(): Promise<void>;
977
+ private ensureSourceMessage;
1060
978
  }
1061
979
  //#endregion
1062
980
  //#region src/handlers/interaction/components/SelectMenuHandler.d.ts
@@ -1175,182 +1093,100 @@ declare const IgnoreBots: import("@seedcord/core").Gate<EventGateContext<ValidNo
1175
1093
  */
1176
1094
  declare function Nsfw(options?: GateNoticeOptions): Gate<InteractionGateContext<NonModalInteraction>, 'Nsfw'>;
1177
1095
  //#endregion
1178
- //#region src/bot/utilities/channels/fetchText.d.ts
1096
+ //#region src/bot/injectors/EmojiInjector.d.ts
1179
1097
  /**
1180
- * Fetches and validates a text channel. Refuses when the channel doesn't exist or isn't a text channel.
1181
- *
1182
- * @param client - The Discord client instance
1183
- * @param channelId - Channel ID or TextChannel instance
1184
- * @returns Promise resolving to the text channel
1098
+ * The global {@link Emojis} accessor type. Each key resolves to its precise class, `GuildEmoji` for a `'guild'`
1099
+ * tag and `ApplicationEmoji` for an `'application'` tag, the tags `seedcord codegen` writes into {@link EmojiMap}.
1185
1100
  */
1186
- declare function fetchText(client: Client, channelId: TextChannelResolvable): Promise<TextChannel>;
1187
- //#endregion
1188
- //#region src/bot/utilities/permissions/checkPermissions.d.ts
1101
+ type InjectedEmojiMap = { [K in keyof EmojiMap]: EmojiMap[K] extends 'guild' ? GuildEmoji : ApplicationEmoji };
1189
1102
  /**
1190
- * Optional custom error constructors for {@link CheckPermissionOptions}.
1103
+ * The bot's resolved emojis, keyed by {@link EmojiMap}. Filled by {@link EmojiInjector} during startup.
1104
+ * A read before that throws.
1191
1105
  */
1192
- interface PermissionErrorNoticeOverrides {
1193
- missingNotice?: new (message: string | undefined, subject: string, missingPerms: readonly string[]) => Notice;
1194
- dangerousNotice?: new (message: string | undefined, subject: string, dangerousPerms: readonly string[]) => Notice;
1195
- }
1106
+ declare const Emojis: InjectedEmojiMap;
1107
+ //#endregion
1108
+ //#region src/bot/utilities/permissions/checkBotPermissions.d.ts
1196
1109
  /**
1197
- * Options for {@link checkPermissions}.
1110
+ * Checks the bot's own permissions in a {@link Guild} or {@link TextChannel}. Refuses when a permission in
1111
+ * `scope` is missing, or with `inverse` when one is present. When the bot member is uncached, the refusal
1112
+ * reports every permission in `scope` as missing.
1198
1113
  *
1199
- * @see {@link PermissionErrorNoticeOverrides}
1114
+ * @example
1115
+ * ```ts
1116
+ * import { PermissionFlagsBits } from 'discord.js';
1117
+ * import { checkBotPermissions } from '@seedcord/gateway';
1118
+ *
1119
+ * checkBotPermissions(textChannel, [PermissionFlagsBits.SendMessages, PermissionFlagsBits.ViewChannel]);
1120
+ * ```
1200
1121
  */
1201
- interface CheckPermissionOptions extends PermissionErrorNoticeOverrides {
1202
- /** Role or member whose permissions will be checked */
1122
+ declare function checkBotPermissions(target: Guild | TextChannel, scope: PermissionScope, inverse?: boolean, errors?: PermissionNoticeOverrides): void;
1123
+ //#endregion
1124
+ //#region src/bot/utilities/permissions/checkPermissions.d.ts
1125
+ /** Options for {@link checkPermissions}. */
1126
+ interface CheckPermissionOptions extends PermissionNoticeOverrides {
1127
+ /** The role or member to check. */
1203
1128
  for: Role | GuildMember;
1204
- /** Context where permissions apply */
1129
+ /** A guild reads the base bits from roles, a text channel reads the overwrite-resolved set. */
1205
1130
  in: Guild | TextChannel;
1206
- /** Permission bits to validate */
1131
+ /** The permission flag bits to check. */
1207
1132
  scope: PermissionScope;
1208
- /** When true, ensure target does NOT have the given permissions */
1133
+ /** Refuse when the target holds a scope bit. */
1209
1134
  inverse?: boolean;
1210
1135
  }
1211
1136
  /**
1212
- * Checks permissions for a {@link Role} or a {@link GuildMember} in a {@link Guild}. Refuses when a
1213
- * permission in `scope` is missing, or with `inverse` when one is present.
1214
- *
1215
- * @param target - Role or member to check
1216
- * @param ctx - Guild context
1217
- * @param scope - Permission bits to validate
1218
- * @param inverse - Whether to ensure absence of the given permissions
1219
- * @param errors - Optional custom error constructors
1220
- *
1137
+ * Checks a {@link Role} or a {@link GuildMember} against the base permission bits in a {@link Guild},
1138
+ * before channel overwrites. Refuses when a permission in `scope` is missing, or with `inverse` when one
1139
+ * is present.
1221
1140
  *
1222
1141
  * @example
1223
1142
  * ```ts
1224
1143
  * import { PermissionFlagsBits } from 'discord.js';
1225
1144
  * import { checkPermissions } from '@seedcord/gateway';
1226
1145
  *
1227
- * // Check if a role has ManageMessages and KickMembers permissions in a guild
1228
- * checkPermissions(role, guild, [
1229
- * PermissionFlagsBits.ManageMessages,
1230
- * PermissionFlagsBits.KickMembers
1231
- * ]);
1146
+ * checkPermissions(role, guild, [PermissionFlagsBits.ManageMessages, PermissionFlagsBits.KickMembers]);
1232
1147
  * ```
1233
1148
  *
1234
1149
  * @example
1235
1150
  * ```ts
1236
- * import { PermissionFlagsBits } from 'discord.js';
1237
- * import { checkPermissions } from '@seedcord/gateway';
1238
- *
1239
- * // Ensure a member does NOT have Administrator permission in a guild and show custom errors
1240
- * checkPermissions(member, guild, [
1241
- * PermissionFlagsBits.Administrator
1242
- * ], true, {
1243
- * missing: CustomMissingPermissionsError,
1244
- * dangerous: CustomDangerousPermissionsError
1151
+ * // refuse when the member holds Administrator, and replace the refusal
1152
+ * checkPermissions(member, guild, [PermissionFlagsBits.Administrator], true, {
1153
+ * dangerousNotice: CustomDangerousNotice
1245
1154
  * });
1246
1155
  * ```
1247
1156
  */
1248
- declare function checkPermissions(target: Role | GuildMember, ctx: Guild, scope: PermissionScope, inverse?: boolean, errors?: PermissionErrorNoticeOverrides): void;
1157
+ declare function checkPermissions(target: Role | GuildMember, ctx: Guild, scope: PermissionScope, inverse?: boolean, errors?: PermissionNoticeOverrides): void;
1249
1158
  /**
1250
- * Checks permissions for a {@link Role} or a {@link GuildMember} in a {@link TextChannel}. Refuses when a
1251
- * permission in `scope` is missing, or with `inverse` when one is present.
1252
- *
1253
- * @param target - Role or member to check
1254
- * @param ctx - Channel context
1255
- * @param scope - Permission bits to validate
1256
- * @param inverse - Whether to ensure absence of the given permissions
1257
- * @param errors - Optional custom error constructors
1258
- *
1159
+ * Checks a {@link Role} or a {@link GuildMember} against the overwrite-resolved set in a
1160
+ * {@link TextChannel}. Refuses when a permission in `scope` is missing, or with `inverse` when one is
1161
+ * present.
1259
1162
  *
1260
1163
  * @example
1261
1164
  * ```ts
1262
1165
  * import { PermissionFlagsBits } from 'discord.js';
1263
1166
  * import { checkPermissions } from '@seedcord/gateway';
1264
1167
  *
1265
- * // Check if a role has SendMessages and ViewChannel permissions in a text channel
1266
- * checkPermissions(role, textChannel, [
1267
- * PermissionFlagsBits.SendMessages,
1268
- * PermissionFlagsBits.ViewChannel
1269
- * ]);
1270
- * ```
1271
- *
1272
- * @example
1273
- * ```ts
1274
- * import { PermissionFlagsBits } from 'discord.js';
1275
- * import { checkPermissions } from '@seedcord/gateway';
1276
- *
1277
- * // Ensure a member does NOT have ManageChannels permission in a text channel and show custom errors
1278
- * checkPermissions(member, textChannel, [
1279
- * PermissionFlagsBits.ManageChannels
1280
- * ], true, {
1281
- * missing: CustomMissingPermissionsError,
1282
- * dangerous: CustomDangerousPermissionsError
1283
- * });
1168
+ * checkPermissions(role, textChannel, [PermissionFlagsBits.SendMessages, PermissionFlagsBits.ViewChannel]);
1284
1169
  * ```
1285
1170
  */
1286
- declare function checkPermissions(target: Role | GuildMember, ctx: TextChannel, scope: PermissionScope, inverse?: boolean, errors?: PermissionErrorNoticeOverrides): void;
1171
+ declare function checkPermissions(target: Role | GuildMember, ctx: TextChannel, scope: PermissionScope, inverse?: boolean, errors?: PermissionNoticeOverrides): void;
1287
1172
  /**
1288
- * Checks permissions using an options object. Refuses when a permission in {@link CheckPermissionOptions.scope} is missing,
1289
- * or with `options.inverse` when one is present.
1290
- *
1291
- * @param options - Complete options for the check
1292
- *
1173
+ * Checks permissions with an options object. Refuses when a permission in
1174
+ * {@link CheckPermissionOptions.scope} is missing, or with `options.inverse` when one is present.
1293
1175
  *
1294
1176
  * @example
1295
1177
  * ```ts
1296
1178
  * import { PermissionFlagsBits } from 'discord.js';
1297
1179
  * import { checkPermissions } from '@seedcord/gateway';
1298
1180
  *
1299
- * // Check permissions using an options object
1300
1181
  * checkPermissions({
1301
1182
  * for: member,
1302
1183
  * in: textChannel,
1303
- * scope: [
1304
- * PermissionFlagsBits.SendMessages,
1305
- * PermissionFlagsBits.ViewChannel
1306
- * ]
1307
- * });
1308
- * ```
1309
- *
1310
- * @example
1311
- * ```ts
1312
- * import { PermissionFlagsBits } from 'discord.js';
1313
- * import { checkPermissions } from '@seedcord/gateway';
1314
- *
1315
- * // Ensure a role does NOT have BanMembers permission in a guild using an options object
1316
- * checkPermissions({
1317
- * for: role,
1318
- * in: guild,
1319
- * scope: [
1320
- * PermissionFlagsBits.BanMembers
1321
- * ],
1322
- * inverse: true,
1323
- * missing: CustomMissingPermissionsError,
1324
- * dangerous: CustomDangerousPermissionsError
1184
+ * scope: [PermissionFlagsBits.SendMessages, PermissionFlagsBits.ViewChannel]
1325
1185
  * });
1326
1186
  * ```
1327
1187
  */
1328
1188
  declare function checkPermissions(options: CheckPermissionOptions): void;
1329
1189
  //#endregion
1330
- //#region src/bot/utilities/permissions/checkBotPermissions.d.ts
1331
- /**
1332
- * Checks if the bot has required permissions in a {@link Guild} or {@link TextChannel}. Refuses when a
1333
- * required permission is missing.
1334
- *
1335
- * @param target - Guild or text channel to check in
1336
- * @param scope - Permission bits to validate
1337
- * @param inverse - Whether to check for absence of the given permissions
1338
- * @param errors - Optional custom error constructors
1339
- *
1340
- * @example
1341
- * ```ts
1342
- * import { PermissionFlagsBits } from 'discord.js';
1343
- * import { checkBotPermissions } from '@seedcord/gateway';
1344
- *
1345
- * // Check if the bot has SendMessages and ViewChannel permissions in a text channel
1346
- * checkBotPermissions(textChannel, [
1347
- * PermissionFlagsBits.SendMessages,
1348
- * PermissionFlagsBits.ViewChannel
1349
- * ]);
1350
- * ```
1351
- */
1352
- declare function checkBotPermissions(target: Guild | TextChannel, scope: PermissionScope, inverse?: boolean, errors?: PermissionErrorNoticeOverrides): void;
1353
- //#endregion
1354
1190
  //#region src/bot/utilities/permissions/hasPermsToAssign.d.ts
1355
1191
  /**
1356
1192
  * Optional custom error constructors for {@link HasPermsToAssignOptions}.
@@ -1368,9 +1204,10 @@ interface HasPermsToAssignOptions {
1368
1204
  noticeOverrides?: AssignRoleNoticeOverrides;
1369
1205
  }
1370
1206
  /**
1371
- * Validates if 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.
1207
+ * 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.
1372
1208
  *
1373
1209
  * @param roleOrOptions - Target role or complete options for the check
1210
+ * @throws A `Notice` on refusal, or a `SeedcordError` when the bot has no role in the guild's role cache.
1374
1211
  *
1375
1212
  * @example
1376
1213
  * ```ts
@@ -1392,86 +1229,6 @@ interface HasPermsToAssignOptions {
1392
1229
  */
1393
1230
  declare function hasPermsToAssign(roleOrOptions: Role | HasPermsToAssignOptions): void;
1394
1231
  //#endregion
1395
- //#region src/bot/utilities/roles/fetchRole.d.ts
1396
- /**
1397
- * Fetches a role by ID from a client or guild. Refuses when the role doesn't exist.
1398
- *
1399
- * @param clientOrGuild - Discord client or guild instance
1400
- * @param roleId - The role ID to fetch
1401
- * @returns Promise resolving to the role
1402
- */
1403
- declare function fetchRole(clientOrGuild: Client | Guild, roleId: string): Promise<Role>;
1404
- //#endregion
1405
- //#region src/bot/utilities/roles/getBotRole.d.ts
1406
- /**
1407
- * Gets the bot's managed role in a guild.
1408
- *
1409
- * @param guild - The guild to get the bot role from
1410
- * @returns The bot's managed role in the guild
1411
- * @throws A **SeedcordError** if the client user is unavailable or if the bot role is missing
1412
- */
1413
- declare function getBotRole(guild: Guild): Role;
1414
- //#endregion
1415
- //#region src/bot/utilities/users/fetchGuildMember.d.ts
1416
- /**
1417
- * Fetches a guild member by user ID. Refuses when the user is not in the guild.
1418
- *
1419
- * @param guild - The guild to fetch the member from
1420
- * @param userId - The Discord user ID
1421
- * @returns Promise resolving to the guild member
1422
- */
1423
- declare function fetchGuildMember(guild: Guild, userId: string): Promise<GuildMember>;
1424
- //#endregion
1425
- //#region src/bot/utilities/users/fetchManyGuildMembers.d.ts
1426
- /**
1427
- * Fetches multiple guild members by user IDs.
1428
- *
1429
- * @param guild - The guild to fetch members from
1430
- * @param userIds - Array of Discord user IDs
1431
- * @returns Promise resolving to array of successfully fetched members
1432
- */
1433
- declare function fetchManyGuildMembers(guild: Guild, userIds: string[]): Promise<GuildMember[]>;
1434
- //#endregion
1435
- //#region src/bot/utilities/users/fetchUser.d.ts
1436
- /**
1437
- * Options for {@link fetchUser}.
1438
- */
1439
- interface FetchUserOptions {
1440
- /** Notice shown when the user does not exist, defaulting to the standard user-not-found notice. */
1441
- throwAs?: new (userArg: string) => Notice;
1442
- }
1443
- /**
1444
- * Fetches a Discord user by ID. Refuses when the user doesn't exist, with `options.throwAs` or the default.
1445
- *
1446
- * @param client - The Discord client instance
1447
- * @param userId - The Discord user ID
1448
- * @param options - Optional overrides, including the {@link FetchUserOptions.throwAs} notice
1449
- * @returns Promise resolving to the user
1450
- */
1451
- declare function fetchUser(client: Client, userId: string, options?: FetchUserOptions): Promise<User>;
1452
- //#endregion
1453
- //#region src/bot/utilities/users/fetchManyUsers.d.ts
1454
- /**
1455
- * Fetches multiple Discord users by IDs.
1456
- *
1457
- * @param client - The Discord client instance
1458
- * @param userIds - Array of Discord user IDs
1459
- * @param options - Optional overrides threaded to each {@link fetchUser} call
1460
- * @returns Promise resolving to array of successfully fetched users
1461
- */
1462
- declare function fetchManyUsers(client: Client, userIds: string[], options?: FetchUserOptions): Promise<User[]>;
1463
- //#endregion
1464
- //#region src/bot/utilities/users/updateMemberRoles.d.ts
1465
- /**
1466
- * Updates a guild member's roles by adding and removing specified roles.
1467
- *
1468
- * @param rolesToAdd - Array of role IDs to add to the member
1469
- * @param rolesToRemove - Array of role IDs to remove from the member
1470
- * @param member - The guild member to update
1471
- * @returns Promise that resolves when roles are updated
1472
- */
1473
- declare function updateMemberRoles(rolesToAdd: Snowflake[], rolesToRemove: Snowflake[], member: GuildMember): Promise<void>;
1474
- //#endregion
1475
1232
  //#region src/bot/confirm/getConfirmation.d.ts
1476
1233
  type Outcome = ReplyResponse | (() => Promisable<ReplyResponse>);
1477
1234
  /** Options shared by both confirmation forms. */
@@ -1520,10 +1277,10 @@ interface DefaultConfirmOptions extends ConfirmOptions {
1520
1277
  /**
1521
1278
  * Shows a confirm/cancel prompt with built-in Confirm and Cancel buttons and resolves to `true` only if the
1522
1279
  * invoking user clicks confirm. A cancel click or a timeout resolves to `false`. Gate the action behind it
1523
- * with an early return. A failed prompt send throws into the fault boundary. Not usable from a
1524
- * {@link ModalHandler}, the `interaction` parameter excludes a modal submit at compile time.
1280
+ * with an early return. A failed prompt send throws into the fault boundary. A {@link ModalHandler} is
1281
+ * excluded at compile time.
1525
1282
  *
1526
- * @param interaction - The repliable interaction to prompt on, `this.event` inside a non-modal handler.
1283
+ * @param handler - The handler to prompt from, `this` inside a non-modal handler.
1527
1284
  * @param prompt - The message shown above the Confirm and Cancel buttons.
1528
1285
  * @param options - Ephemeral flag, timeout, the built-in buttons' labels and style, and the optional
1529
1286
  * `onConfirm`/`onCancel`/`onTimeout` outcome replies that edit the prompt in place.
@@ -1537,29 +1294,29 @@ interface DefaultConfirmOptions extends ConfirmOptions {
1537
1294
  * class BanHandler extends SlashHandler<'ban'> {
1538
1295
  * async execute() {
1539
1296
  * const target = this.options.getUser('target', true);
1540
- * if (!(await getConfirmation(this.event, `Ban ${target.tag}? This cannot be undone.`))) return;
1297
+ * if (!(await getConfirmation(this, `Ban ${target.tag}? This cannot be undone.`))) return;
1541
1298
  * await this.event.guild?.members.ban(target.id);
1542
1299
  * }
1543
1300
  * }
1544
1301
  * ```
1545
1302
  */
1546
- declare function getConfirmation(interaction: NonModalInteraction, prompt: string, options?: DefaultConfirmOptions): Promise<boolean>;
1303
+ declare function getConfirmation(handler: RepliableHandler<NonModalInteraction>, prompt: string, options?: DefaultConfirmOptions): Promise<boolean>;
1547
1304
  /**
1548
1305
  * Shows a confirm/cancel prompt you build yourself and resolves to `true` only if the invoking user clicks
1549
1306
  * confirm. The factory receives the two minted button ids. Set them on your own buttons. A cancel click or a
1550
- * timeout resolves to `false`. A failed prompt send throws into the fault boundary. Not usable from a
1551
- * {@link ModalHandler}.
1307
+ * timeout resolves to `false`. A failed prompt send throws into the fault boundary. A {@link ModalHandler} is
1308
+ * excluded at compile time.
1552
1309
  *
1553
- * @param interaction - The repliable interaction to prompt on, `this.event` inside a non-modal handler.
1310
+ * @param handler - The handler to prompt from, `this` inside a non-modal handler.
1554
1311
  * @param prompt - A factory given the minted `{ confirm, cancel }` ids that returns the reply to show. Build
1555
- * it with the kit `BuilderComponent`/`RowComponent` wrappers, not raw discord.js builders.
1312
+ * it with the `BuilderComponent` and `RowComponent` wrappers.
1556
1313
  * @param options - Ephemeral flag, timeout, and the optional `onConfirm`/`onCancel`/`onTimeout` outcome
1557
1314
  * replies that edit the prompt in place.
1558
1315
  * @returns `true` if confirmed, `false` on cancel or timeout.
1559
1316
  *
1560
1317
  * @remarks
1561
- * The prompt is collected in-process, so it does not survive a bot restart. Without an outcome hook, deliver
1562
- * a result after confirming with a fresh `interaction.followUp(...)`, the prompt is already gone.
1318
+ * The prompt is collected in-process, so it does not survive a bot restart. Without an outcome hook the
1319
+ * prompt is gone once the user confirms, so deliver the result with a fresh `this.followUp(...)`.
1563
1320
  *
1564
1321
  * @example
1565
1322
  * ```ts
@@ -1589,14 +1346,14 @@ declare function getConfirmation(interaction: NonModalInteraction, prompt: strin
1589
1346
  *
1590
1347
  * const target = this.options.getUser('target', true);
1591
1348
  * const confirmed = await getConfirmation(
1592
- * this.event,
1349
+ * this,
1593
1350
  * (ids) => ({ components: [new BanPrompt(`Ban ${target.tag}?`).component, new ConfirmRow(ids).component] }),
1594
1351
  * { onConfirm: { components: [new BanPrompt(`Banned ${target.tag}.`).component] } }
1595
1352
  * );
1596
1353
  * if (!confirmed) return;
1597
1354
  * ```
1598
1355
  */
1599
- declare function getConfirmation(interaction: NonModalInteraction, prompt: (ids: {
1356
+ declare function getConfirmation(handler: RepliableHandler<NonModalInteraction>, prompt: (ids: {
1600
1357
  confirm: string;
1601
1358
  cancel: string;
1602
1359
  }) => Promisable<ReplyResponse>, options?: ConfirmOptions): Promise<boolean>;
@@ -1612,103 +1369,11 @@ interface PageContext {
1612
1369
  user: User;
1613
1370
  /** The guild, or `null` in a DM. */
1614
1371
  guild: Guild | null;
1615
- /** The framework core, passed only when a source requires framework services. */
1616
- core?: Core;
1617
- }
1618
- //#endregion
1619
- //#region src/pagination/controls.d.ts
1620
- /** The five built-in nav controls. */
1621
- type ControlKey = 'first' | 'prev' | 'indicator' | 'next' | 'last';
1622
- type CustomIdStyle = ButtonStyle.Primary | ButtonStyle.Secondary | ButtonStyle.Success | ButtonStyle.Danger;
1623
- /** Cosmetic overrides for a control button. `style` excludes Link and Premium, which would un-route it. */
1624
- interface ControlCosmetics {
1625
- label?: string;
1626
- style?: CustomIdStyle;
1627
- emoji?: APIMessageComponentEmoji;
1628
- }
1629
- /** The controls passed to `render`. Each accessor returns a fresh builder stamped with its target page. */
1630
- interface PaginatorControls {
1631
- /**
1632
- * A fresh `ButtonBuilder` for one control, already stamped with its target page and disabled-at-bounds
1633
- * state. Call only cosmetic setters on it, a `setCustomId` or `setStyle(Link)` un-routes it.
1634
- */
1635
- button(key: ControlKey, cosmetics?: ControlCosmetics): ButtonBuilder;
1636
- /**
1637
- * Assemble an action row of the chosen controls, in order. Throws on an empty set, more than five
1638
- * controls, or a duplicate.
1639
- */
1640
- row(...keys: ControlKey[]): ActionRowBuilder<ButtonBuilder>;
1641
- }
1642
- //#endregion
1643
- //#region src/pagination/render.d.ts
1644
- /** What `renderItem` returns for one item, a text line or a section. */
1645
- type ItemRender<Item> = (item: Item, index: number) => string | BuilderComponent<'section'>;
1646
- /** What the V2 reply can be built from. Each arm is normalized into a {@link ReplyResponse}. */
1647
- type Renderable = string | V2Component[] | ReplyResponse;
1648
- /** A full-page render override, handed the page data and the controls factory. */
1649
- type PageRender<Item> = (view: PageView<Item>, controls: PaginatorControls) => Renderable;
1650
- //#endregion
1651
- //#region src/pagination/sources.d.ts
1652
- /**
1653
- * The one method a paginator calls on a source, once per click. Implement it to supply a custom source.
1654
- *
1655
- * @typeParam Item - The item type the source pages over.
1656
- */
1657
- interface PageSource<Item> {
1658
- page(ctx: PageContext, n: number): Promise<PageView<Item>>;
1659
- }
1660
- /**
1661
- * A source for a bounded list you can load whole. It loads the full list on every click, then slices the
1662
- * page via {@link paginate}, so the real total is known (a real last button, "Page X of Y"). Cache inside
1663
- * your loader if the load is expensive.
1664
- *
1665
- * @typeParam Item - The item type, inferred from the loader's return.
1666
- */
1667
- declare class ArraySource<Item> implements PageSource<Item> {
1668
- private readonly load;
1669
- private readonly perPage;
1670
- constructor(load: (ctx: PageContext) => Promisable<readonly Item[]>, opts?: {
1671
- perPage?: number;
1672
- });
1673
- page(ctx: PageContext, n: number): Promise<PageView<Item>>;
1674
- }
1675
- /**
1676
- * A source for a large or unknown-length set you fetch one page at a time (SQL LIMIT/OFFSET, a paged API).
1677
- * The fetcher receives the page index and the page size and reports whether a next page exists. A cursor
1678
- * source has no cheap total, so `totalPages` is undefined, the last button is omitted, and the indicator
1679
- * reads "Page X".
1680
- *
1681
- * @typeParam Item - The item type, inferred from the fetcher's slice.
1682
- */
1683
- declare class CursorSource<Item> implements PageSource<Item> {
1684
- private readonly fetch;
1685
- private readonly perPage;
1686
- constructor(fetch: (ctx: PageContext, page: number, perPage: number) => Promisable<{
1687
- items: readonly Item[];
1688
- hasNext: boolean;
1689
- }>, opts?: {
1690
- perPage?: number;
1691
- });
1692
- page(ctx: PageContext, n: number): Promise<PageView<Item>>;
1372
+ /** The framework core. */
1373
+ core: Core;
1693
1374
  }
1694
1375
  //#endregion
1695
1376
  //#region src/pagination/Paginator.d.ts
1696
- interface PaginatorConfig<Item, Prefix extends string> {
1697
- /** The route prefix used to build the page cursor on the nav buttons. */
1698
- prefix: Prefix;
1699
- /** Where the page data comes from. */
1700
- source: PageSource<Item>;
1701
- /** Render one item, `index` is its absolute position across pages. Ignored when `render` is set. */
1702
- renderItem?: ItemRender<Item>;
1703
- /** Take over the whole page tree. Receives the page data and the controls factory. */
1704
- render?: PageRender<Item>;
1705
- /**
1706
- * Whether the first page is ephemeral.
1707
- *
1708
- * @defaultValue `false`
1709
- */
1710
- ephemeral?: boolean;
1711
- }
1712
1377
  type PaginatorHandlerCtor<Prefix extends string> = new (event: ButtonInteraction<'cached'>, core: Core) => ButtonHandler<[PageCursor<Prefix>]> & {
1713
1378
  execute(): Promise<void>;
1714
1379
  };
@@ -1731,23 +1396,38 @@ type PaginatorHandlerCtor<Prefix extends string> = new (event: ButtonInteraction
1731
1396
  * export class BansNav extends Bans.Handler {}
1732
1397
  * ```
1733
1398
  */
1734
- declare class Paginator<Item, const Prefix extends string> {
1735
- /** The page cursor, pass it to your `@ButtonRoute`. */
1736
- readonly cursor: PageCursor<Prefix>;
1399
+ declare class Paginator<Item, const Prefix extends string> extends PaginatorBase<Item, Prefix, PageContext> {
1737
1400
  /** The nav handler base. Extend it with an empty body and decorate it, `@ButtonRoute(p.cursor)`. */
1738
1401
  readonly Handler: PaginatorHandlerCtor<Prefix>;
1739
- private readonly config;
1740
- constructor(config: PaginatorConfig<Item, Prefix>);
1402
+ constructor(config: PaginatorConfig<Item, Prefix, PageContext>);
1741
1403
  /**
1742
- * Render page 0 and send it through the handler's sender, picking reply or followUp from its ack state.
1404
+ * Render page 0 and send it through the handler's sender, which picks reply, edit, or followUp from its
1405
+ * ack state.
1743
1406
  *
1744
1407
  * @param handler - The handler starting the paginator, normally `this`.
1745
1408
  */
1746
1409
  start(handler: RepliableHandler<Repliables>): Promise<Message>;
1747
- /** Render a page as a {@link ReplyResponse}. To post it elsewhere, add `flags: MessageFlags.IsComponentsV2`. */
1748
- page(ctx: PageContext, n: number): Promise<ReplyResponse>;
1749
1410
  }
1750
1411
  //#endregion
1412
+ //#region src/pagination/sources.d.ts
1413
+ /**
1414
+ * A source for a bounded list you can load whole. It loads the full list on every click, then slices the
1415
+ * page, so the real total is known (a real last button, "Page X of Y"). Cache inside your loader if the
1416
+ * load is expensive.
1417
+ *
1418
+ * @typeParam Item - The item type, inferred from the loader's return.
1419
+ */
1420
+ declare class ArraySource<Item> extends ArraySource$1<Item, PageContext> {}
1421
+ /**
1422
+ * A source for a large or unknown-length set you fetch one page at a time (SQL LIMIT/OFFSET, a paged API).
1423
+ * The fetcher receives the page index and the page size and reports whether a next page exists. A cursor
1424
+ * source has no cheap total, so `totalPages` is undefined, the last button is omitted, and the indicator
1425
+ * reads "Page X".
1426
+ *
1427
+ * @typeParam Item - The item type, inferred from the fetcher's slice.
1428
+ */
1429
+ declare class CursorSource<Item> extends CursorSource$1<Item, PageContext> {}
1430
+ //#endregion
1751
1431
  //#region src/subscribers/index.d.ts
1752
1432
  /**
1753
1433
  * Base class for a gateway subscriber, binding `this.core` to the gateway {@link Core}.
@@ -1772,9 +1452,9 @@ type GatewayPluginOptions = TypedOmit<PluginOptions$1, 'transport'> & {
1772
1452
  * Base class for a gateway plugin, binding `this.core` to the gateway {@link Core}.
1773
1453
  *
1774
1454
  * A plugin that runs on either transport extends the base from `@seedcord/core/plugin`, whose
1775
- * `this.core` carries the shared members only.
1455
+ * `this.core` is typed to the shared members only.
1776
1456
  *
1777
- * @typeParam Opts - The transport, runtime, and capabilities the plugin declares.
1457
+ * @typeParam Opts - The transport and runtime the plugin declares.
1778
1458
  */
1779
1459
  declare abstract class Plugin<Opts extends GatewayPluginOptions = {}> extends Plugin$1<Opts, Core> {}
1780
1460
  //#endregion
@@ -1798,6 +1478,8 @@ declare class Seedcord extends Pluggable<'gateway', 'server'> implements Core, S
1798
1478
  private readonly subscribers;
1799
1479
  /** @see {@link Bot} */
1800
1480
  readonly bot: Bot;
1481
+ /** The discord.js client's REST client. Its token is set during the Login phase. */
1482
+ readonly rest: REST;
1801
1483
  /** @see {@link IRateLimiter} */
1802
1484
  readonly rateLimiter: IRateLimiter;
1803
1485
  /**
@@ -1807,7 +1489,6 @@ declare class Seedcord extends Pluggable<'gateway', 'server'> implements Core, S
1807
1489
  constructor(config: GatewayConfig);
1808
1490
  /** The bot's discord username, populated after login. */
1809
1491
  get username(): string | undefined;
1810
- protected pluginCapabilities(): PluginCapabilities;
1811
1492
  protected static reset(): void;
1812
1493
  private registerStartupTasks;
1813
1494
  /**
@@ -1823,5 +1504,5 @@ declare class Seedcord extends Pluggable<'gateway', 'server'> implements Core, S
1823
1504
  /** Package version */
1824
1505
  declare const version: string;
1825
1506
  //#endregion
1826
- export { ArraySource, AssignRoleNoticeOverrides, AutocompleteHandler, ButtonHandler, type CheckPermissionOptions, CommandMentions, type ConfirmOptions, ContextMenuHandler, type Core, CursorSource, type DefaultConfirmOptions, Emojis, type EventGateContext, EventHandler, EventMiddleware, type EventSpec, type EventsConfig, FetchUserOptions, type GateContext, Gated, type GatewayBotConfig, type GatewayConfig, type GatewayPluginOptions, HasPermsToAssignOptions, IgnoreBots, type InjectedEmojiMap, type InjectedMentionMap, type InteractionGateContext, InteractionHandler, InteractionMiddleware, Middleware, type MiddlewareOptions, MiddlewareType, ModalHandler, Nsfw, Paginator, type PaginatorControls, type PermissionErrorNoticeOverrides, Plugin, type PluginContext, type PluginLifecycleSpec, type PluginOptions, RegisterEvent, type RegisterEventOptions, RepliableHandler, type Repliables, Seedcord, SelectMenuHandler, SlashHandler, type SlashOptions, Subscriber, type ValidEventTypes, type ValidInteractionTypes, type ValidNonInteractionKeys, WebhookLog, checkBotPermissions, checkPermissions, fetchGuildMember, fetchManyGuildMembers, fetchManyUsers, fetchRole, fetchText, fetchUser, getBotRole, getConfirmation, hasPermsToAssign, updateMemberRoles, version };
1507
+ export { ArraySource, AssignRoleNoticeOverrides, AutocompleteHandler, ButtonHandler, type CheckPermissionOptions, type ConfirmOptions, ContextMenuHandler, type Core, CursorSource, type DefaultConfirmOptions, Emojis, type EventGateContext, EventHandler, EventMiddleware, type EventSpec, type EventsConfig, type GateContext, Gated, type GatewayBotConfig, type GatewayConfig, type GatewayPluginOptions, HasPermsToAssignOptions, IgnoreBots, type InjectedEmojiMap, type InteractionGateContext, InteractionHandler, InteractionMiddleware, Middleware, type MiddlewareOptions, MiddlewareType, ModalHandler, Nsfw, type PageContext, Paginator, Plugin, type PluginLifecycleSpec, type PluginOptions, RegisterEvent, type RegisterEventOptions, RepliableHandler, type Repliables, Seedcord, SelectMenuHandler, SlashHandler, type SlashOptions, Subscriber, type ValidEventTypes, type ValidInteractionTypes, type ValidNonInteractionKeys, WebhookLog, checkBotPermissions, checkPermissions, getConfirmation, hasPermsToAssign, version };
1827
1508
  //# sourceMappingURL=index.d.mts.map