@seedcord/gateway 0.1.0-next.0 → 0.1.0-next.2

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.mjs CHANGED
@@ -1,20 +1,24 @@
1
1
  import "reflect-metadata";
2
- import { BuilderComponent, CustomId, Fault, Notice, RegisterCommand, RowComponent, Silence, defineGate, paginate } from "@seedcord/core";
3
- import { CommandMetadataKey, ComponentDefsKey, EventMetadataKey, GateNotice, GatedMetadataKey, InteractionMetadataKey, InteractionRouteKeys, InteractionRoutes, MiddlewareMetadataKey, NotInGuild, NoticeCard, PAGE_MAX, SubscribeMetadataKey, decodeFor, pageCursor, pickNotice, prefixOf, runHandlerGates, setBotColor } from "@seedcord/core/internal";
2
+ import { installNodeDefaults } from "@seedcord/logger/node";
3
+ import { BuilderComponent, CustomId, DispatchContext, Fault, Notice, RegisterCommand, RowComponent, Silence, defineGate, paginate } from "@seedcord/core";
4
+ import { CommandMetadataKey, ComponentDefsKey, EventMetadataKey, GateNotice, GatedMetadataKey, HmrManager, InteractionMetadataKey, InteractionRouteKeys, InteractionRoutes, MiddlewareMetadataKey, NotInGuild, NoticeCard, PAGE_MAX, SubscribeMetadataKey, decodeFor, getDevChannel, pageCursor, pickNotice, prefixOf, routeIdOf, runHandlerGates, setBotColor } from "@seedcord/core/internal";
4
5
  import { ApplicationCommandType, AttachmentBuilder, ButtonStyle, Client, Collection, ComponentType, DiscordAPIError, Events, Guild, GuildMember, Message, MessageFlags, PermissionFlagsBits, RESTJSONErrorCodes, Role, SeparatorSpacingSize, SnowflakeUtil, TextChannel, User, WebhookClient, chatInputApplicationCommandMention } from "discord.js";
5
6
  import { SeedcordErrorCode } from "@seedcord/errors";
6
7
  import { SeedcordError, SeedcordRangeError, SeedcordTypeError, validateDiscordToken } from "@seedcord/errors/internal";
7
- import { filterCirculars, formatFilePath, hasKeys, prettify, traverseDirectory } from "@seedcord/utils";
8
- import { CoordinatedShutdown, CoordinatedStartup, HealthCheck, Logger, ShutdownPhase, StartupPhase, StrictEventEmitter } from "@seedcord/services";
9
- import chalk from "chalk";
8
+ import { filterCirculars, formatFilePath, hasKeys, prettify } from "@seedcord/utils";
9
+ import { Logger, LoggerChannelRegistry, paint } from "@seedcord/logger";
10
10
  import { ActionRowBuilder, ButtonBuilder, ContextMenuCommandBuilder, SlashCommandBuilder, TextDisplayBuilder } from "@discordjs/builders";
11
11
  import { buildSlashRoute, routeLeavesOf } from "@seedcord/utils/internal";
12
- import { existsSync } from "node:fs";
13
- import { resolve } from "node:path";
14
- import { pathToFileURL } from "node:url";
12
+ import { TypedEventEmitter } from "@seedcord/event-emitter";
15
13
  import { MemoryRateLimiter } from "@seedcord/rate-limiter";
16
- import { SeedcordBrand, wrapHot } from "@seedcord/types/internal";
17
- import { Envapt, Envapter } from "envapt";
14
+ import { CoordinatedShutdown, CoordinatedStartup, HealthCheck, ShutdownPhase, StartupPhase } from "@seedcord/services";
15
+ import { SeedcordBrand } from "@seedcord/types/internal";
16
+ import { Envapter } from "envapt";
17
+ import chalk from "chalk";
18
+ import { Envapt } from "envapt/legacy";
19
+ import { resolve } from "node:path";
20
+ import { HmrModuleHandler } from "@seedcord/core/hmr";
21
+ import { traverseDirectory } from "@seedcord/utils/node";
18
22
  import * as crypto from "node:crypto";
19
23
 
20
24
  export * from "@seedcord/core"
@@ -23,10 +27,18 @@ export * from "@seedcord/errors"
23
27
 
24
28
  export * from "@seedcord/utils"
25
29
 
26
- export * from "@seedcord/services"
30
+ export * from "@seedcord/logger"
31
+
32
+ export * from "@seedcord/event-emitter"
27
33
 
28
34
  export * from "@seedcord/rate-limiter"
29
35
 
36
+ export * from "@seedcord/services"
37
+
38
+ //#region src/logger-bootstrap.ts
39
+ installNodeDefaults();
40
+
41
+ //#endregion
30
42
  //#region src/bot/decorators/Events.ts
31
43
  /**
32
44
  * Registers an event handler class with one or more Discord.js events.
@@ -670,7 +682,7 @@ var EmojiInjector = class {
670
682
  async init() {
671
683
  this.clearEmojis();
672
684
  if (!this.core.config.bot.emojis || Object.keys(this.core.config.bot.emojis).length === 0) {
673
- this.logger.debug(chalk.bold.yellow("No emojis configured, skipping emoji injection."));
685
+ this.logger.debug("No emojis configured, skipping emoji injection.");
674
686
  return;
675
687
  }
676
688
  const configEmojis = this.core.config.bot.emojis;
@@ -1227,16 +1239,6 @@ async function getConfirmation(interaction, prompt, options) {
1227
1239
  return confirmed;
1228
1240
  }
1229
1241
 
1230
- //#endregion
1231
- //#region src/hmr/devChannel.ts
1232
- let channel;
1233
- function setDevChannel(next) {
1234
- channel = next;
1235
- }
1236
- function getDevChannel() {
1237
- return channel;
1238
- }
1239
-
1240
1242
  //#endregion
1241
1243
  //#region src/interfaces/Plugin.ts
1242
1244
  /**
@@ -1245,7 +1247,7 @@ function getDevChannel() {
1245
1247
  * Extend this class to create plugins that integrate with the Seedcord lifecycle.
1246
1248
  * Plugins have access to the core instance and must implement initialization logic.
1247
1249
  */
1248
- var Plugin = class extends StrictEventEmitter {
1250
+ var Plugin = class extends TypedEventEmitter {
1249
1251
  pluggable;
1250
1252
  name = this.constructor.name;
1251
1253
  constructor(pluggable) {
@@ -1267,16 +1269,12 @@ var Plugin = class extends StrictEventEmitter {
1267
1269
  getDevChannel()?.send("seedcord:register-critical-files", { patterns });
1268
1270
  }
1269
1271
  /** @internal */
1270
- setMaxListeners(n) {
1271
- return super.setMaxListeners(n);
1272
- }
1273
- /** @internal */
1274
1272
  removeListener(event, listener) {
1275
1273
  return super.removeListener(event, listener);
1276
1274
  }
1277
1275
  /** @internal */
1278
- removeAllListeners(eventName) {
1279
- return super.removeAllListeners(eventName);
1276
+ removeAllListeners(event) {
1277
+ return super.removeAllListeners(event);
1280
1278
  }
1281
1279
  };
1282
1280
  /**
@@ -1285,7 +1283,7 @@ var Plugin = class extends StrictEventEmitter {
1285
1283
  * Provides plugin attachment capabilities and lifecycle management. Plugins are attached during
1286
1284
  * configuration and initialized during startup. Not constructed directly, the host is a {@link Seedcord}.
1287
1285
  */
1288
- var Pluggable = class Pluggable extends StrictEventEmitter {
1286
+ var Pluggable = class Pluggable extends TypedEventEmitter {
1289
1287
  isInitialized = false;
1290
1288
  shutdown;
1291
1289
  startup;
@@ -1338,16 +1336,12 @@ var Pluggable = class Pluggable extends StrictEventEmitter {
1338
1336
  return Object.assign(this, entry);
1339
1337
  }
1340
1338
  /** @internal */
1341
- setMaxListeners(n) {
1342
- return super.setMaxListeners(n);
1343
- }
1344
- /** @internal */
1345
1339
  removeListener(event, listener) {
1346
1340
  return super.removeListener(event, listener);
1347
1341
  }
1348
1342
  /** @internal */
1349
- removeAllListeners(eventName) {
1350
- return super.removeAllListeners(eventName);
1343
+ removeAllListeners(event) {
1344
+ return super.removeAllListeners(event);
1351
1345
  }
1352
1346
  };
1353
1347
 
@@ -1360,10 +1354,12 @@ var BaseHandler = class {
1360
1354
  core;
1361
1355
  event;
1362
1356
  logger;
1363
- constructor(event, core) {
1357
+ dispatch;
1358
+ constructor(event, core, dispatch) {
1364
1359
  this.core = core;
1365
1360
  this.event = event;
1366
1361
  this.logger = new Logger(this.constructor.name);
1362
+ this.dispatch = dispatch;
1367
1363
  }
1368
1364
  /** @internal */
1369
1365
  getEvent() {
@@ -1399,8 +1395,8 @@ var InteractionMiddleware = class extends BaseHandler {
1399
1395
  * @typeParam Repliable - The interaction type this handler processes
1400
1396
  */
1401
1397
  var InteractionHandler = class extends BaseHandler {
1402
- constructor(event, core) {
1403
- super(event, core);
1398
+ constructor(event, core, dispatch) {
1399
+ super(event, core, dispatch);
1404
1400
  }
1405
1401
  };
1406
1402
 
@@ -1545,8 +1541,8 @@ var ContextMenuHandler = class extends InteractionHandler {
1545
1541
  * ```
1546
1542
  */
1547
1543
  var AutocompleteHandler = class extends BaseHandler {
1548
- constructor(event, core) {
1549
- super(event, core);
1544
+ constructor(event, core, dispatch) {
1545
+ super(event, core, dispatch);
1550
1546
  }
1551
1547
  /**
1552
1548
  * The focused option for this interaction. `value` is always the raw partial string the user is typing,
@@ -2163,171 +2159,6 @@ var WebhookLog = class extends Subscriber {
2163
2159
  }
2164
2160
  };
2165
2161
 
2166
- //#endregion
2167
- //#region src/hmr/HmrModuleHandler.ts
2168
- /**
2169
- * Reloads THandler and optional TMiddleware modules on HMR updates.
2170
- *
2171
- * You can either implement a custom `onHmr()` method in your class by extending `HmrAware`, or if it's a plugin, override the existing `onHmr()` with fully custom logic. Or, use this class's `handle()` method inside your `onHmr()` to get standard HMR handling for your modules based on the provided options you give to the constructor.
2172
- *
2173
- * This is only useful during development.
2174
- */
2175
- var HmrModuleHandler = class {
2176
- store;
2177
- options;
2178
- constructor(options) {
2179
- this.options = {
2180
- ...options,
2181
- logger: options.logger.inChannel("hmr")
2182
- };
2183
- this.store = {
2184
- fileToHandlers: /* @__PURE__ */ new Map(),
2185
- fileToMiddlewares: /* @__PURE__ */ new Map(),
2186
- handlerArtifacts: /* @__PURE__ */ new Map()
2187
- };
2188
- }
2189
- /**
2190
- * Handles an HMR update event by reloading affected modules based on the event details and config. It receives an {@link HmrUpdateEvent}, then checks the type of update.
2191
- *
2192
- * - If it's a deletion, it unloads the module.
2193
- * - If it's an update/creation, it checks if the file is tracked, unloads it if so, then reloads the file if it is in the handlers or middlewares directory and is a valid handler/middleware.
2194
- */
2195
- async handle(event) {
2196
- const { file, affectedModules, type } = event;
2197
- const { logger, handlersDir, middlewaresDir } = this.options;
2198
- if (type === "delete" || type === "deleteDir") {
2199
- this.unload(file);
2200
- return;
2201
- }
2202
- if (type === "update" && !existsSync(file)) {
2203
- if (this.isTracked(file)) {
2204
- logger.info(`Received update for non-existent file: ${formatFilePath(file)}, treating as delete`);
2205
- this.unload(file);
2206
- }
2207
- return;
2208
- }
2209
- const rollbackEnabled = event.rollback ?? true;
2210
- const filesToReload = affectedModules && affectedModules.length > 0 ? affectedModules : [file];
2211
- const absHandlersDir = resolve(process.cwd(), handlersDir);
2212
- const absMiddlewaresDir = middlewaresDir ? resolve(process.cwd(), middlewaresDir) : null;
2213
- for (const fileToReload of filesToReload) {
2214
- const isHandler = fileToReload.startsWith(absHandlersDir);
2215
- const isMiddleware = absMiddlewaresDir ? fileToReload.startsWith(absMiddlewaresDir) : false;
2216
- if (!isHandler && !isMiddleware) continue;
2217
- await this.reloadWithRollback(fileToReload, rollbackEnabled);
2218
- }
2219
- }
2220
- async reloadWithRollback(file, rollbackEnabled) {
2221
- const { logger } = this.options;
2222
- const snapshot = this.snapshotUnits(file);
2223
- this.unload(file);
2224
- if (await this.reloadFile(file)) return;
2225
- this.unload(file);
2226
- if (!rollbackEnabled) return;
2227
- this.restoreUnits(file, snapshot);
2228
- logger.warn(`${chalk.yellow.bold("Rolled back")} ${chalk.gray(formatFilePath(file))} to the last-good version`);
2229
- }
2230
- /**
2231
- * Tracks a handler module as being loaded from a specific file.
2232
- * @param file - The file path the handler was loaded from.
2233
- * @param handler - The handler module instance.
2234
- */
2235
- trackHandler(file, handler) {
2236
- let set = this.store.fileToHandlers.get(file);
2237
- if (!set) {
2238
- set = /* @__PURE__ */ new Set();
2239
- this.store.fileToHandlers.set(file, set);
2240
- }
2241
- set.add(handler);
2242
- if (this.options.getArtifacts) {
2243
- const artifacts = this.options.getArtifacts(handler);
2244
- this.store.handlerArtifacts.set(handler, artifacts);
2245
- }
2246
- }
2247
- /**
2248
- * Tracks a middleware module as being loaded from a specific file.
2249
- * @param file - The file path the middleware was loaded from.
2250
- * @param middleware - The middleware module instance.
2251
- */
2252
- trackMiddleware(file, middleware) {
2253
- let set = this.store.fileToMiddlewares.get(file);
2254
- if (!set) {
2255
- set = /* @__PURE__ */ new Set();
2256
- this.store.fileToMiddlewares.set(file, set);
2257
- }
2258
- set.add(middleware);
2259
- }
2260
- isTracked(file) {
2261
- return this.store.fileToHandlers.has(file) || this.store.fileToMiddlewares.has(file);
2262
- }
2263
- unload(file) {
2264
- const { logger } = this.options;
2265
- const handlers = this.store.fileToHandlers.get(file);
2266
- if (handlers) {
2267
- for (const handler of handlers) {
2268
- const artifacts = this.store.handlerArtifacts.get(handler);
2269
- this.options.unregisterHandler(handler, artifacts);
2270
- this.store.handlerArtifacts.delete(handler);
2271
- const name = handler.name ?? "Handler";
2272
- logger.info(`${chalk.red.bold("Unloaded")} ${chalk.cyan.bold(name)} from ${chalk.gray(formatFilePath(file))}`);
2273
- }
2274
- this.store.fileToHandlers.delete(file);
2275
- }
2276
- const middlewares = this.store.fileToMiddlewares.get(file);
2277
- if (middlewares) {
2278
- for (const middleware of middlewares) {
2279
- this.options.unregisterMiddleware?.(middleware);
2280
- const name = middleware.name ?? "Middleware";
2281
- logger.info(`${chalk.red.bold("Unloaded")} ${chalk.cyan.bold(name)} from ${chalk.gray(formatFilePath(file))}`);
2282
- }
2283
- this.store.fileToMiddlewares.delete(file);
2284
- }
2285
- }
2286
- async reloadFile(file) {
2287
- const { logger, isHandler, isMiddleware, registerHandler, registerMiddleware } = this.options;
2288
- if (!existsSync(file)) {
2289
- logger.info(`File does not exist, skipping reload: ${formatFilePath(file)}`);
2290
- return false;
2291
- }
2292
- try {
2293
- let fileUrl = pathToFileURL(file).href;
2294
- if (process.env.VITEST === "true") fileUrl += `?update=${Date.now()}`;
2295
- const imported = await import(fileUrl);
2296
- for (const val of Object.values(imported)) if (isHandler(val)) {
2297
- registerHandler(val, file);
2298
- this.trackHandler(file, val);
2299
- const name = val.name ?? "Handler";
2300
- logger.info(`${chalk.blue.bold("Reloaded")} ${chalk.cyan.bold(name)} from ${chalk.gray(formatFilePath(file))}`);
2301
- } else if (isMiddleware && registerMiddleware && isMiddleware(val)) {
2302
- registerMiddleware(val, file);
2303
- this.trackMiddleware(file, val);
2304
- const name = val.name ?? "Middleware";
2305
- logger.info(`${chalk.blue.bold("Reloaded")} ${chalk.cyan.bold(name)} from ${chalk.gray(formatFilePath(file))}`);
2306
- }
2307
- return true;
2308
- } catch (error) {
2309
- logger.error(`Failed to reload file: ${file}`, error);
2310
- return false;
2311
- }
2312
- }
2313
- snapshotUnits(file) {
2314
- return {
2315
- handlers: [...this.store.fileToHandlers.get(file) ?? []],
2316
- middlewares: [...this.store.fileToMiddlewares.get(file) ?? []]
2317
- };
2318
- }
2319
- restoreUnits(file, snapshot) {
2320
- for (const handler of snapshot.handlers) {
2321
- this.options.registerHandler(handler, file);
2322
- this.trackHandler(file, handler);
2323
- }
2324
- if (this.options.registerMiddleware) for (const middleware of snapshot.middlewares) {
2325
- this.options.registerMiddleware(middleware, file);
2326
- this.trackMiddleware(file, middleware);
2327
- }
2328
- }
2329
- };
2330
-
2331
2162
  //#endregion
2332
2163
  //#region src/bot/utilities/miscellaneous/contextMenuLeaves.ts
2333
2164
  /**
@@ -2388,6 +2219,8 @@ var CommandRegistry = class {
2388
2219
  globalCommands = [];
2389
2220
  guildCommands = new Collection();
2390
2221
  ctorToCommand = /* @__PURE__ */ new Map();
2222
+ loading = false;
2223
+ loadedCommands = [];
2391
2224
  hmrHandler;
2392
2225
  pendingEvents = /* @__PURE__ */ new Map();
2393
2226
  constructor(core, onDeployed) {
@@ -2414,16 +2247,33 @@ var CommandRegistry = class {
2414
2247
  this.isInitialised = true;
2415
2248
  const commandsDir = this.core.config.bot.commands.path;
2416
2249
  if (!commandsDir) return;
2417
- this.logger.info(chalk.bold(commandsDir));
2418
- await this.loadCommands(commandsDir);
2419
- this.logger.utils.summary("Loaded commands", {
2420
- global: this.globalCommands.length,
2421
- "guild groups": this.guildCommands.size
2422
- });
2250
+ this.loading = true;
2251
+ this.loadedCommands.length = 0;
2252
+ try {
2253
+ await this.loadCommands(commandsDir);
2254
+ } finally {
2255
+ this.loading = false;
2256
+ }
2257
+ this.reportLoad();
2423
2258
  getDevChannel()?.on("seedcord:refresh-commands", (data) => {
2424
2259
  this.refresh(data.shouldRefresh);
2425
2260
  });
2426
2261
  }
2262
+ reportLoad() {
2263
+ const { utils } = this.logger;
2264
+ utils.summary("Loaded commands", {
2265
+ global: this.globalCommands.length,
2266
+ "guild groups": this.guildCommands.size
2267
+ });
2268
+ let slash = 0;
2269
+ let menu = 0;
2270
+ for (const command of this.loadedCommands) if (command.kind === "slash command") slash++;
2271
+ else menu++;
2272
+ utils.block("Loaded commands", [...utils.entries(this.loadedCommands), ...utils.counts({
2273
+ "slash commands": slash,
2274
+ "context menus": menu
2275
+ })]);
2276
+ }
2427
2277
  /** @internal */
2428
2278
  async refresh(shouldRefresh = true) {
2429
2279
  if (!shouldRefresh) {
@@ -2461,25 +2311,27 @@ var CommandRegistry = class {
2461
2311
  const meta = Reflect.getMetadata(CommandMetadataKey, ctor);
2462
2312
  if (!meta) return;
2463
2313
  const comp = new ctor().component;
2464
- const commandType = comp instanceof SlashCommandBuilder ? "slash command" : "context menu command";
2465
- if (meta.scope === "global") {
2466
- this.globalCommands.push(comp);
2467
- this.logger.utils.registration(ctor.name, rel);
2468
- this.logger.utils.item(`Global ${commandType}: ${chalk.bold.cyan(comp.name)}`);
2469
- } else {
2470
- for (const g of meta.guilds) {
2471
- const arr = this.guildCommands.get(g) ?? [];
2472
- arr.push(comp);
2473
- this.guildCommands.set(g, arr);
2474
- }
2475
- this.logger.utils.registration(ctor.name, rel);
2476
- this.logger.utils.item(`Guild ${commandType}: ${chalk.bold.cyan(comp.name)} for ${chalk.magenta.bold(meta.guilds.length)} guild(s)`);
2314
+ const kind = comp instanceof SlashCommandBuilder ? "slash command" : "context menu";
2315
+ if (meta.scope === "global") this.globalCommands.push(comp);
2316
+ else for (const g of meta.guilds) {
2317
+ const arr = this.guildCommands.get(g) ?? [];
2318
+ arr.push(comp);
2319
+ this.guildCommands.set(g, arr);
2477
2320
  }
2478
2321
  this.ctorToCommand.set(ctor, {
2479
2322
  name: comp.name,
2480
2323
  scope: meta.scope,
2481
2324
  ...meta.scope === "guild" && { guilds: meta.guilds }
2482
2325
  });
2326
+ if (this.loading) {
2327
+ this.loadedCommands.push({
2328
+ name: comp.name,
2329
+ from: formatFilePath(rel),
2330
+ kind
2331
+ });
2332
+ return;
2333
+ }
2334
+ this.logger.utils.registration(comp.name, rel, `${meta.scope} ${kind}`);
2483
2335
  }
2484
2336
  unregisterCommand(ctor, artifacts) {
2485
2337
  const info = artifacts ?? this.ctorToCommand.get(ctor);
@@ -2506,8 +2358,7 @@ var CommandRegistry = class {
2506
2358
  const deployed = await this.core.bot.client.application?.commands.set(this.globalCommands);
2507
2359
  if (deployed) result.global = deployed;
2508
2360
  const tag = this.globalCommands.length === 1 ? "command" : "commands";
2509
- this.logger.utils.summary("Configured global", { [tag]: this.globalCommands.length });
2510
- this.logger.utils.item(`${this.globalCommands.map((command) => chalk.bold.cyan(command.name)).join(", ")}`);
2361
+ this.logger.utils.block(`Deployed ${this.globalCommands.length} global ${tag}`, this.logger.utils.wrap(this.globalCommands.map((command) => command.name)), "info");
2511
2362
  }
2512
2363
  for (const [guildId, commands] of this.guildCommands.entries()) {
2513
2364
  const guild = this.core.bot.client.guilds.cache.get(guildId);
@@ -2518,8 +2369,7 @@ var CommandRegistry = class {
2518
2369
  const deployed = await guild.commands.set(commands);
2519
2370
  result.guilds.set(guildId, deployed);
2520
2371
  const tag = commands.length === 1 ? "command" : "commands";
2521
- this.logger.utils.summary(`Configured commands for ${chalk.bold.yellow(guild.name)}`, { [tag]: commands.length });
2522
- this.logger.utils.item(`${commands.map((command) => chalk.bold.cyan(command.name)).join(", ")}`);
2372
+ this.logger.utils.block(`Deployed ${commands.length} ${tag} to ${paint.amber.bold(guild.name)}`, this.logger.utils.wrap(commands.map((command) => command.name)), "info");
2523
2373
  }
2524
2374
  this.onDeployed?.(result);
2525
2375
  return result;
@@ -2582,7 +2432,8 @@ function interactionGateContext(interaction, core) {
2582
2432
  guildId: interaction.guildId,
2583
2433
  channelId: interaction.channelId,
2584
2434
  memberRoleIds,
2585
- memberPermissions: interaction.memberPermissions?.bitfield ?? null
2435
+ memberPermissions: interaction.memberPermissions?.bitfield ?? null,
2436
+ routeId: null
2586
2437
  };
2587
2438
  }
2588
2439
  function eventGateContext(eventName, args, core) {
@@ -2599,7 +2450,8 @@ function eventGateContext(eventName, args, core) {
2599
2450
  guildId: actor.guild?.id ?? null,
2600
2451
  channelId: actor.channelId,
2601
2452
  memberRoleIds: actor.member ? [...actor.member.roles.cache.keys()].filter((id) => id !== actor.guild?.id) : [],
2602
- memberPermissions: actor.member?.permissions.bitfield ?? null
2453
+ memberPermissions: actor.member?.permissions.bitfield ?? null,
2454
+ routeId: null
2603
2455
  };
2604
2456
  }
2605
2457
 
@@ -2829,6 +2681,9 @@ var EventDispatcher = class {
2829
2681
  middlewares = [];
2830
2682
  executedOnceHandlers = /* @__PURE__ */ new Set();
2831
2683
  attachedEvents = /* @__PURE__ */ new Set();
2684
+ loading = false;
2685
+ loadedHandlers = [];
2686
+ loadedMiddlewares = [];
2832
2687
  hmrHandler;
2833
2688
  constructor(core) {
2834
2689
  this.core = core;
@@ -2858,20 +2713,29 @@ var EventDispatcher = class {
2858
2713
  this.isInitialized = true;
2859
2714
  const handlersDir = this.core.config.bot.events.path;
2860
2715
  if (!handlersDir) return;
2861
- this.logger.info(chalk.bold(handlersDir));
2862
2716
  const middlewareDir = hasKeys(this.core.config.bot.events, ["middlewares"]) ? this.core.config.bot.events.middlewares : void 0;
2863
- if (middlewareDir) {
2864
- this.logger.info(`${chalk.bold(middlewareDir)} ${chalk.gray("(middlewares)")}`);
2865
- await this.loadMiddlewares(middlewareDir);
2717
+ this.loading = true;
2718
+ this.loadedHandlers.length = 0;
2719
+ this.loadedMiddlewares.length = 0;
2720
+ try {
2721
+ if (middlewareDir) await this.loadMiddlewares(middlewareDir);
2722
+ await this.loadHandlers(handlersDir);
2723
+ } finally {
2724
+ this.loading = false;
2866
2725
  }
2867
- await this.loadHandlers(handlersDir);
2868
2726
  this.attachToClient();
2869
- this.logger.info(`${chalk.bold.green("Loaded event handlers:")}`);
2870
- const eventList = [`${chalk.magenta.bold(this.middlewares.length)} middlewares`];
2871
- this.eventMap.forEach((handlers, eventName) => {
2872
- eventList.push(`${chalk.magenta.bold(handlers.length)} ${eventName}`);
2727
+ this.reportLoad();
2728
+ }
2729
+ reportLoad() {
2730
+ const { utils } = this.logger;
2731
+ utils.summary("Loaded", {
2732
+ "event handlers": this.loadedHandlers.length,
2733
+ middlewares: this.loadedMiddlewares.length
2873
2734
  });
2874
- this.logger.utils.list(eventList);
2735
+ if (this.loadedMiddlewares.length > 0) utils.block("Loaded event middlewares", utils.entries(this.loadedMiddlewares));
2736
+ const perEvent = {};
2737
+ for (const [event, handlers] of this.eventMap) perEvent[event] = handlers.length;
2738
+ utils.block("Loaded event handlers", [...utils.entries(this.loadedHandlers), ...utils.counts(perEvent)]);
2875
2739
  }
2876
2740
  async loadHandlers(dir) {
2877
2741
  await traverseDirectory(dir, (fullPath, relativePath, imported) => {
@@ -2921,7 +2785,14 @@ var EventDispatcher = class {
2921
2785
  ...metadata.events && { events: metadata.events }
2922
2786
  });
2923
2787
  this.middlewares.sort((a, b) => a.priority - b.priority);
2924
- this.logger.utils.registration(`${middlewareCtor.name} ${chalk.gray(`(${metadata.priority})`)}`, relativePath, "event middleware");
2788
+ if (this.loading) {
2789
+ this.loadedMiddlewares.push({
2790
+ name: `${middlewareCtor.name} (${metadata.priority})`,
2791
+ from: formatFilePath(relativePath)
2792
+ });
2793
+ return;
2794
+ }
2795
+ this.logger.utils.registration(`${middlewareCtor.name} ${paint.mute(`(${metadata.priority})`)}`, relativePath, "event middleware");
2925
2796
  }
2926
2797
  async runMiddlewares(eventName, args) {
2927
2798
  for (const { ctor, events } of this.middlewares) {
@@ -2962,7 +2833,12 @@ var EventDispatcher = class {
2962
2833
  const names = areRoutes(raw) ? raw : typeof raw === "string" ? [raw] : [];
2963
2834
  for (const name of names) register(name, "on");
2964
2835
  }
2965
- this.logger.utils.registration(handlerClass.name, relativePath);
2836
+ const from = formatFilePath(relativePath);
2837
+ if (this.loading) this.loadedHandlers.push({
2838
+ name: handlerClass.name,
2839
+ from
2840
+ });
2841
+ else this.logger.utils.registration(handlerClass.name, from);
2966
2842
  }
2967
2843
  attachToClient() {
2968
2844
  for (const [eventName] of this.eventMap) this.attachListener(eventName);
@@ -2971,12 +2847,12 @@ var EventDispatcher = class {
2971
2847
  if (this.attachedEvents.has(eventName)) return;
2972
2848
  this.attachedEvents.add(eventName);
2973
2849
  const handlerEntries = this.eventMap.get(eventName);
2974
- this.logger.debug(`Attaching ${chalk.bold.green(eventName)} to the client with ${chalk.gray(handlerEntries?.length ?? 0)} handler(s)`);
2850
+ this.logger.debug(`Attaching ${paint.mint.bold(eventName)} to the client with ${paint.mute(handlerEntries?.length ?? 0)} handler(s)`);
2975
2851
  this.core.bot.client.on(eventName, (...args) => {
2976
- this.core.bot.emit("any:event", eventName, ...args);
2852
+ this.core.bot.emitSafe("any:event", eventName, ...args);
2977
2853
  (async () => {
2978
2854
  await this.processEvent(eventName, args).catch((err) => {
2979
- this.logger.error(`[${chalk.bold.red("UNHANDLED ERROR AT ROOT")}] ${err.name}`, err.stack);
2855
+ this.logger.error(`[${paint.coral.bold("UNHANDLED ERROR AT ROOT")}] ${err.name}`, err.stack);
2980
2856
  this.core.bot.emit("error:unhandled:event", err);
2981
2857
  });
2982
2858
  })();
@@ -2998,7 +2874,7 @@ var EventDispatcher = class {
2998
2874
  }
2999
2875
  async processHandler(eventName, ctor, args) {
3000
2876
  try {
3001
- this.logger.debug(`Processing ${chalk.bold.green(eventName)} with ${chalk.gray(ctor.name)}`);
2877
+ this.logger.debug(`Processing ${paint.mint.bold(eventName)} with ${paint.mute(ctor.name)}`);
3002
2878
  const handler = new ctor(args, this.core, eventName);
3003
2879
  await runHandlerGates(ctor, eventGateContext(eventName, args, this.core));
3004
2880
  await handler.execute();
@@ -3090,6 +2966,9 @@ var InteractionDispatcher = class {
3090
2966
  autocompleteMap = /* @__PURE__ */ new Map();
3091
2967
  keysToIgnore = /* @__PURE__ */ new Set();
3092
2968
  middlewares = [];
2969
+ loading = false;
2970
+ loadedHandlers = [];
2971
+ loadedMiddlewares = [];
3093
2972
  hmrHandler;
3094
2973
  routeTypes = [
3095
2974
  [InteractionRoutes.Slash, this.slashMap],
@@ -3132,7 +3011,7 @@ var InteractionDispatcher = class {
3132
3011
  * @internal
3133
3012
  */
3134
3013
  warnUnhandledRoutes(commandLeaves) {
3135
- for (const route of commandLeaves) if (!this.slashMap.has(route)) this.logger.warn(`Slash route ${chalk.bold.cyan(route)} has no registered ${chalk.bold("@SlashRoute")} handler.`);
3014
+ for (const route of commandLeaves) if (!this.slashMap.has(route)) this.logger.warn(`Slash route ${paint.sky.bold(route)} has no registered ${chalk.bold("@SlashRoute")} handler.`);
3136
3015
  }
3137
3016
  /**
3138
3017
  * Warns for each context-menu command with no matching handler, which would fall through to UnhandledEvent
@@ -3141,8 +3020,8 @@ var InteractionDispatcher = class {
3141
3020
  * @internal
3142
3021
  */
3143
3022
  warnUnhandledContextMenuRoutes(leaves) {
3144
- for (const name of leaves.user) if (!this.userContextMenuMap.has(name)) this.logger.warn(`User context menu ${chalk.bold.cyan(name)} has no registered ${chalk.bold("@ContextMenuRoute")} handler.`);
3145
- for (const name of leaves.message) if (!this.messageContextMenuMap.has(name)) this.logger.warn(`Message context menu ${chalk.bold.cyan(name)} has no registered ${chalk.bold("@ContextMenuRoute")} handler.`);
3023
+ for (const name of leaves.user) if (!this.userContextMenuMap.has(name)) this.logger.warn(`User context menu ${paint.sky.bold(name)} has no registered ${chalk.bold("@ContextMenuRoute")} handler.`);
3024
+ for (const name of leaves.message) if (!this.messageContextMenuMap.has(name)) this.logger.warn(`Message context menu ${paint.sky.bold(name)} has no registered ${chalk.bold("@ContextMenuRoute")} handler.`);
3146
3025
  }
3147
3026
  getArtifacts(handlerClass) {
3148
3027
  const artifacts = [];
@@ -3160,29 +3039,39 @@ var InteractionDispatcher = class {
3160
3039
  this.isInitialized = true;
3161
3040
  const handlersDir = this.core.config.bot.interactions.path;
3162
3041
  if (!handlersDir) return;
3163
- this.logger.info(chalk.bold(handlersDir));
3164
3042
  const middlewareDir = hasKeys(this.core.config.bot.interactions, ["middlewares"]) ? this.core.config.bot.interactions.middlewares : void 0;
3165
- if (middlewareDir) {
3166
- this.logger.info(`${chalk.bold(middlewareDir)} ${chalk.gray("(middlewares)")}`);
3167
- await this.loadMiddlewares(middlewareDir);
3043
+ this.loading = true;
3044
+ this.loadedHandlers.length = 0;
3045
+ this.loadedMiddlewares.length = 0;
3046
+ try {
3047
+ if (middlewareDir) await this.loadMiddlewares(middlewareDir);
3048
+ await this.loadHandlers(handlersDir);
3049
+ } finally {
3050
+ this.loading = false;
3168
3051
  }
3169
- await this.loadHandlers(handlersDir);
3170
3052
  this.attachToClient();
3171
- this.logger.info(`${chalk.bold.green("Loaded interaction handlers:")}`);
3172
- this.logger.utils.list([
3173
- `${chalk.magenta.bold(this.middlewares.length)} middlewares`,
3174
- `${chalk.magenta.bold(this.slashMap.size)} slash commands`,
3175
- `${chalk.magenta.bold(this.buttonMap.size)} buttons`,
3176
- `${chalk.magenta.bold(this.modalMap.size)} modals`,
3177
- `${chalk.magenta.bold(this.stringSelectMap.size)} string selects`,
3178
- `${chalk.magenta.bold(this.userSelectMap.size)} user selects`,
3179
- `${chalk.magenta.bold(this.roleSelectMap.size)} role selects`,
3180
- `${chalk.magenta.bold(this.channelSelectMap.size)} channel selects`,
3181
- `${chalk.magenta.bold(this.mentionableSelectMap.size)} mentionable selects`,
3182
- `${chalk.magenta.bold(this.messageContextMenuMap.size)} message context menus`,
3183
- `${chalk.magenta.bold(this.userContextMenuMap.size)} user context menus`,
3184
- `${chalk.magenta.bold(this.autocompleteMap.size)} autocomplete`
3185
- ]);
3053
+ this.reportLoad();
3054
+ }
3055
+ reportLoad() {
3056
+ const { utils } = this.logger;
3057
+ utils.summary("Loaded", {
3058
+ "interaction handlers": this.loadedHandlers.length,
3059
+ middlewares: this.loadedMiddlewares.length
3060
+ });
3061
+ if (this.loadedMiddlewares.length > 0) utils.block("Loaded middlewares", utils.entries(this.loadedMiddlewares));
3062
+ utils.block("Loaded interaction handlers", [...utils.entries(this.loadedHandlers), ...utils.counts({
3063
+ slash: this.slashMap.size,
3064
+ buttons: this.buttonMap.size,
3065
+ modals: this.modalMap.size,
3066
+ "string selects": this.stringSelectMap.size,
3067
+ "user selects": this.userSelectMap.size,
3068
+ "role selects": this.roleSelectMap.size,
3069
+ "channel selects": this.channelSelectMap.size,
3070
+ "mentionable selects": this.mentionableSelectMap.size,
3071
+ "message menus": this.messageContextMenuMap.size,
3072
+ "user menus": this.userContextMenuMap.size,
3073
+ autocomplete: this.autocompleteMap.size
3074
+ })]);
3186
3075
  }
3187
3076
  async loadHandlers(dir) {
3188
3077
  await traverseDirectory(dir, (fullPath, relativePath, imported) => {
@@ -3212,7 +3101,14 @@ var InteractionDispatcher = class {
3212
3101
  priority: metadata.priority
3213
3102
  });
3214
3103
  this.middlewares.sort((a, b) => a.priority - b.priority);
3215
- this.logger.utils.registration(`${middlewareCtor.name} ${chalk.gray(`(${metadata.priority})`)}`, relativePath, "middleware");
3104
+ if (this.loading) {
3105
+ this.loadedMiddlewares.push({
3106
+ name: `${middlewareCtor.name} (${metadata.priority})`,
3107
+ from: formatFilePath(relativePath)
3108
+ });
3109
+ return;
3110
+ }
3111
+ this.logger.utils.registration(`${middlewareCtor.name} ${paint.mute(`(${metadata.priority})`)}`, relativePath, "middleware");
3216
3112
  }
3217
3113
  isHandlerClass(obj) {
3218
3114
  if (typeof obj !== "function") return false;
@@ -3236,9 +3132,15 @@ var InteractionDispatcher = class {
3236
3132
  ]);
3237
3133
  writes.push([map, route]);
3238
3134
  }
3239
- this.logger.utils.registration(handlerClass.name, formatFilePath(relativePath));
3240
3135
  }
3136
+ if (writes.length === 0) return;
3241
3137
  for (const [map, route] of writes) map.set(route, handlerClass);
3138
+ const from = formatFilePath(relativePath);
3139
+ if (this.loading) this.loadedHandlers.push({
3140
+ name: handlerClass.name,
3141
+ from
3142
+ });
3143
+ else this.logger.utils.registration(handlerClass.name, from);
3242
3144
  }
3243
3145
  /** @internal For use in dev mode */
3244
3146
  async onHmr(event) {
@@ -3264,9 +3166,9 @@ var InteractionDispatcher = class {
3264
3166
  }
3265
3167
  attachToClient() {
3266
3168
  this.core.bot.client.on(Events.InteractionCreate, (interaction) => {
3267
- this.core.bot.emit("any:interaction", interaction);
3169
+ this.core.bot.emitSafe("any:interaction", interaction);
3268
3170
  this.handleInteraction(interaction).catch((err) => {
3269
- this.logger.error(`[${chalk.bold.red("UNHANDLED ERROR AT ROOT")}] ${err.name}`, err.stack);
3171
+ this.logger.error(`[${paint.coral.bold("UNHANDLED ERROR AT ROOT")}] ${err.name}`, err.stack);
3270
3172
  this.core.bot.emit("error:unhandled:interaction", err);
3271
3173
  });
3272
3174
  });
@@ -3283,11 +3185,12 @@ var InteractionDispatcher = class {
3283
3185
  if (!interaction.isAutocomplete()) for (const { ctor } of this.middlewares) await new ctor(interaction, this.core).execute();
3284
3186
  let HandlerCtor = getHandler(key);
3285
3187
  if (!HandlerCtor) {
3286
- this.logger.warn(`No handler found for key ${chalk.bold.cyan(key)}. Falling back to UnhandledEvent.`);
3188
+ this.logger.warn(`No handler found for key ${paint.sky.bold(key)}. Falling back to UnhandledEvent.`);
3287
3189
  HandlerCtor = UnhandledEvent;
3288
3190
  }
3289
- this.logger.debug(`Processing ${chalk.bold.green(key)} with ${chalk.gray(HandlerCtor.name)}`);
3290
- const handler = new HandlerCtor(interaction, this.core);
3191
+ this.logger.debug(`Processing ${paint.mint.bold(key)} with ${paint.mute(HandlerCtor.name)}`);
3192
+ const dispatch = new DispatchContext(routeIdOf(HandlerCtor));
3193
+ const handler = new HandlerCtor(interaction, this.core, dispatch);
3291
3194
  if (!interaction.isAutocomplete()) await runHandlerGates(HandlerCtor, interactionGateContext(interaction, this.core));
3292
3195
  await handler.execute();
3293
3196
  } catch (caught) {
@@ -3368,7 +3271,7 @@ var InteractionDispatcher = class {
3368
3271
  async handleAutocomplete(interaction) {
3369
3272
  const route = slashRouteOf(interaction);
3370
3273
  if (!this.autocompleteMap.has(route)) {
3371
- this.logger.warn(`No autocomplete handler for ${chalk.bold.cyan(route)}.`);
3274
+ this.logger.warn(`No autocomplete handler for ${paint.sky.bold(route)}.`);
3372
3275
  await interaction.respond([]);
3373
3276
  return;
3374
3277
  }
@@ -3478,48 +3381,14 @@ var Bot = class extends Plugin {
3478
3381
  emit(event, ...args) {
3479
3382
  return super.emit(event, ...args);
3480
3383
  }
3481
- };
3482
- __decorate([Envapt("DISCORD_BOT_TOKEN", { converter: (raw) => validateDiscordToken(raw) }), __decorateMetadata("design:type", String)], Bot.prototype, "botToken", void 0);
3483
-
3484
- //#endregion
3485
- //#region src/hmr/HmrManager.ts
3486
- var HmrManager = class {
3487
- logger = new Logger("HMR", { channel: "hmr" });
3488
- listeners = /* @__PURE__ */ new Set();
3489
- constructor() {}
3490
- /** @internal */
3491
- init() {
3492
- if (!import.meta.hot) return;
3493
- setDevChannel(wrapHot(import.meta.hot));
3494
- if (Envapter.isDevelopment || Envapter.isTest) {
3495
- this.logger.info("Enabled");
3496
- getDevChannel()?.on("seedcord:hmr", (payload) => {
3497
- const affected = payload.affectedModules?.length ?? 0;
3498
- this.logger.info(`${chalk.bold("1")} module changed, ${chalk.bold(affected)} affected modules`);
3499
- if (payload.affectedModules) this.logger.utils.list(payload.affectedModules.map((mod) => formatFilePath(mod)), "Affected modules: ");
3500
- this.handleUpdate(payload);
3501
- });
3502
- }
3503
- }
3504
- /** @internal */
3505
- register(listener) {
3506
- this.listeners.add(listener);
3507
- }
3508
- /** @internal */
3509
- unregister(listener) {
3510
- this.listeners.delete(listener);
3384
+ emitSafe(event, ...args) {
3385
+ return super.emitSafe(event, ...args);
3511
3386
  }
3512
- async handleUpdate(event) {
3513
- const promises = [...this.listeners].map(async (listener) => {
3514
- try {
3515
- await listener.onHmr(event);
3516
- } catch (error) {
3517
- this.logger.error(`Error handling HMR update in ${chalk.bold(listener.name)}: `, error);
3518
- }
3519
- });
3520
- await Promise.all(promises);
3387
+ onListenerError(error, event) {
3388
+ this.logger.error(`listener for ${String(event)} threw`, error);
3521
3389
  }
3522
3390
  };
3391
+ __decorate([Envapt("DISCORD_BOT_TOKEN", { converter: (raw) => validateDiscordToken(raw) }), __decorateMetadata("design:type", String)], Bot.prototype, "botToken", void 0);
3523
3392
 
3524
3393
  //#endregion
3525
3394
  //#region src/subscribers/bases/webhookHelpers.ts
@@ -3811,7 +3680,7 @@ var Bus = class extends Plugin {
3811
3680
  //#endregion
3812
3681
  //#region src/version.ts
3813
3682
  /** Package version */
3814
- const version = "0.1.0-next.0";
3683
+ const version = "0.1.0-next.2";
3815
3684
 
3816
3685
  //#endregion
3817
3686
  //#region src/Seedcord.ts
@@ -3830,6 +3699,8 @@ var Seedcord = class Seedcord extends Pluggable {
3830
3699
  /** @internal */
3831
3700
  version = version;
3832
3701
  static isInstantiated = false;
3702
+ healthCheck;
3703
+ hmrManager;
3833
3704
  /** @see {@link CoordinatedShutdown} */
3834
3705
  shutdown;
3835
3706
  /** @see {@link CoordinatedStartup} */
@@ -3840,10 +3711,6 @@ var Seedcord = class Seedcord extends Pluggable {
3840
3711
  bot;
3841
3712
  /** @see {@link IRateLimiter} */
3842
3713
  rateLimiter;
3843
- /** @see {@link HealthCheck} */
3844
- healthCheck;
3845
- /** @see {@link HmrManager} */
3846
- hmrManager;
3847
3714
  /**
3848
3715
  * Creates a new Seedcord instance
3849
3716
  *
@@ -3857,6 +3724,7 @@ var Seedcord = class Seedcord extends Pluggable {
3857
3724
  const startup = new CoordinatedStartup();
3858
3725
  super(shutdown, startup);
3859
3726
  this.config = config;
3727
+ installNodeDefaults(config.logger);
3860
3728
  setBotColor(config.botColor);
3861
3729
  this.shutdown = shutdown;
3862
3730
  this.startup = startup;
@@ -3864,18 +3732,18 @@ var Seedcord = class Seedcord extends Pluggable {
3864
3732
  this.hmrManager.init();
3865
3733
  this.bus = new Bus(this);
3866
3734
  this.bot = new Bot(this);
3867
- this.rateLimiter = new MemoryRateLimiter();
3735
+ this.rateLimiter = config.store ?? new MemoryRateLimiter();
3868
3736
  this.healthCheck = new HealthCheck(this.shutdown, config.healthCheck);
3869
3737
  this.registerStartupTasks();
3870
3738
  }
3871
- /** @internal */
3739
+ /** The bot's discord username, populated after login. */
3740
+ get username() {
3741
+ return this.bot.client.user?.username;
3742
+ }
3872
3743
  static reset() {
3873
3744
  Seedcord.isInstantiated = false;
3745
+ LoggerChannelRegistry.instance.reset();
3874
3746
  }
3875
- /**
3876
- * Registers default startup tasks
3877
- * @internal
3878
- */
3879
3747
  registerStartupTasks() {
3880
3748
  if (Envapter.isDevelopment || Envapter.isTest) this.registerHmrAwareModules();
3881
3749
  this.startup.addTask(StartupPhase.Configuration, "Bus Initialization", async () => {
@@ -3914,5 +3782,5 @@ var Seedcord = class Seedcord extends Pluggable {
3914
3782
  };
3915
3783
 
3916
3784
  //#endregion
3917
- export { ArraySource, AutocompleteHandler, AutocompleteRoute, ButtonHandler, ButtonRoute, CommandMentions, ContextMenuHandler, ContextMenuRoute, CursorSource, Emojis, EventHandler, EventMiddleware, Gated, HmrModuleHandler, IgnoreBots, InteractionHandler, InteractionMiddleware, Middleware, MiddlewareType, ModalHandler, ModalRoute, Nsfw, Paginator, Pluggable, Plugin, RegisterCommand, RegisterEvent, ReplySender, RequireBotPermissions, RequirePermissions, RequireRole, Seedcord, SelectMenuHandler, SelectMenuKind, SelectMenuRoute, SlashHandler, SlashRoute, Subscribe, Subscriber, WebhookLog, checkBotPermissions, checkPermissions, fetchGuildMember, fetchManyGuildMembers, fetchManyUsers, fetchRole, fetchText, fetchUser, getBotRole, getConfirmation, hasPermsToAssign, updateMemberRoles, version };
3785
+ export { ArraySource, AutocompleteHandler, AutocompleteRoute, ButtonHandler, ButtonRoute, CommandMentions, ContextMenuHandler, ContextMenuRoute, CursorSource, Emojis, EventHandler, EventMiddleware, Gated, IgnoreBots, InteractionHandler, InteractionMiddleware, Middleware, MiddlewareType, ModalHandler, ModalRoute, Nsfw, Paginator, Pluggable, Plugin, RegisterCommand, RegisterEvent, ReplySender, RequireBotPermissions, RequirePermissions, RequireRole, Seedcord, SelectMenuHandler, SelectMenuKind, SelectMenuRoute, SlashHandler, SlashRoute, Subscribe, Subscriber, WebhookLog, checkBotPermissions, checkPermissions, fetchGuildMember, fetchManyGuildMembers, fetchManyUsers, fetchRole, fetchText, fetchUser, getBotRole, getConfirmation, hasPermsToAssign, updateMemberRoles, version };
3918
3786
  //# sourceMappingURL=index.mjs.map