seedcord 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,16 +1,79 @@
1
1
  import 'reflect-metadata';
2
- import chalk6 from 'chalk';
3
- import { SlashCommandSubcommandGroupBuilder, SlashCommandSubcommandBuilder, ContextMenuCommandBuilder, ModalBuilder, RoleSelectMenuBuilder, MentionableSelectMenuBuilder, ChannelSelectMenuBuilder, UserSelectMenuBuilder, StringSelectMenuOptionBuilder, StringSelectMenuBuilder, ButtonBuilder, EmbedBuilder, SlashCommandBuilder, InteractionContextType, ActionRowBuilder, TextInputBuilder, MessageFlags, Events, Client, WebhookClient, DiscordAPIError, SnowflakeUtil, Message } from 'discord.js';
4
- import { Envapter, Envapt } from 'envapt';
5
- import { readdir } from 'fs/promises';
6
- import * as path from 'path';
7
- import { format, transports, createLogger } from 'winston';
2
+ import { Logger, ShutdownPhase, CoordinatedShutdown, CoordinatedStartup, HealthCheck, StartupPhase } from '@seedcord/services';
3
+ export * from '@seedcord/services';
4
+ import chalk2 from 'chalk';
5
+ import { SeparatorBuilder, SectionBuilder, MediaGalleryBuilder, FileBuilder, TextDisplayBuilder, ContainerBuilder, SlashCommandSubcommandGroupBuilder, SlashCommandSubcommandBuilder, ContextMenuCommandBuilder, ModalBuilder, RoleSelectMenuBuilder, MentionableSelectMenuBuilder, ChannelSelectMenuBuilder, UserSelectMenuBuilder, StringSelectMenuOptionBuilder, StringSelectMenuBuilder, ButtonBuilder, EmbedBuilder, SlashCommandBuilder, InteractionContextType, ActionRowBuilder, TextInputBuilder, MessageFlags, Events, Client, WebhookClient, DiscordAPIError, SnowflakeUtil, Message } from 'discord.js';
6
+ import { Envapt } from 'envapt';
7
+ import { traverseDirectory } from '@seedcord/utils';
8
+ export * from '@seedcord/utils';
8
9
  import * as crypto2 from 'crypto';
9
10
  import { EventEmitter } from 'events';
10
- import { createServer } from 'http';
11
11
 
12
12
  var __defProp = Object.defineProperty;
13
13
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
14
+ var Plugin = class {
15
+ static {
16
+ __name(this, "Plugin");
17
+ }
18
+ pluggable;
19
+ constructor(pluggable) {
20
+ this.pluggable = pluggable;
21
+ }
22
+ };
23
+ var Pluggable = class _Pluggable {
24
+ static {
25
+ __name(this, "Pluggable");
26
+ }
27
+ isInitialized = false;
28
+ shutdown;
29
+ startup;
30
+ static PLUGIN_INIT_TIMEOUT_MS = 15e3;
31
+ constructor(shutdown, startup) {
32
+ this.shutdown = shutdown;
33
+ this.startup = startup;
34
+ }
35
+ async init() {
36
+ if (this.isInitialized) return this;
37
+ await this.startup.run();
38
+ this.isInitialized = true;
39
+ return this;
40
+ }
41
+ /**
42
+ * Attaches a plugin to this instance
43
+ *
44
+ * Plugins provide external functionality and are initialized during the specified startup phase.
45
+ * The plugin instance becomes available as a property in `core` wherever it's available.
46
+ *
47
+ * Make sure to augment the {@link Core} interface with the plugin type to ensure TypeScript recognizes it and provides intellisense.
48
+ *
49
+ * @typeParam Key - The property name for accessing the plugin
50
+ * @typeParam Ctor - The plugin constructor type
51
+ * @param key - Property name to access the plugin instance
52
+ * @param Plugin - Plugin constructor class
53
+ * @param startupPhase - When during startup to initialize this plugin ({@link StartupPhase})
54
+ * @param args - Additional arguments to pass to the plugin constructor
55
+ * @returns This instance with the plugin attached as a typed property
56
+ * @throws An {@link Error} When called after initialization or if key already exists
57
+ * @example
58
+ * ```typescript
59
+ * seedcord.attach('db', Mongo, StartupPhase.Configuration, { uri: 'mongodb://...', name: 'seedcord', dir: ... })
60
+ * ```
61
+ */
62
+ attach(key, Plugin2, startupPhase, ...args) {
63
+ if (this.isInitialized) throw new Error("Cannot attach a plugin after initialization.");
64
+ if (this[key]) throw new Error(`Plugin with key "${key}" already exists.`);
65
+ const instance = new Plugin2(this, ...args);
66
+ const entry = {
67
+ [key]: instance
68
+ };
69
+ this.startup.addTask(startupPhase, `Plugin:${key}`, async () => {
70
+ instance.logger.info(chalk2.bold("Initializing"));
71
+ await instance.init();
72
+ instance.logger.info(chalk2.bold("Initialized"));
73
+ }, _Pluggable.PLUGIN_INIT_TIMEOUT_MS);
74
+ return Object.assign(this, entry);
75
+ }
76
+ };
14
77
  function _ts_decorate(decorators, target, key, desc) {
15
78
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
79
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -22,54 +85,6 @@ function _ts_metadata(k, v) {
22
85
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
23
86
  }
24
87
  __name(_ts_metadata, "_ts_metadata");
25
- var Globals = class extends Envapter {
26
- static {
27
- __name(this, "Globals");
28
- }
29
- static botToken;
30
- // Healthcheck
31
- static healthCheckPort;
32
- static healthCheckPath;
33
- // Coordinated Shutdown
34
- static shutdownIsEnabled;
35
- // Unknown Exception Webhook URL
36
- static unknownExceptionWebhookUrl;
37
- // Variables
38
- /** Default color for bot embeds - can be overridden by setting Globals.botColor */
39
- static botColor = this.isProduction ? "#fe565a" : "#3fa045";
40
- };
41
- _ts_decorate([
42
- Envapt("DISCORD_BOT_TOKEN", {
43
- fallback: void 0
44
- }),
45
- _ts_metadata("design:type", String)
46
- ], Globals, "botToken", void 0);
47
- _ts_decorate([
48
- Envapt("HEALTH_CHECK_PORT", {
49
- fallback: 6956
50
- }),
51
- _ts_metadata("design:type", Number)
52
- ], Globals, "healthCheckPort", void 0);
53
- _ts_decorate([
54
- Envapt("HEALTH_CHECK_PATH", {
55
- fallback: "/healthcheck"
56
- }),
57
- _ts_metadata("design:type", String)
58
- ], Globals, "healthCheckPath", void 0);
59
- _ts_decorate([
60
- Envapt("SHUTDOWN_IS_ENABLED", {
61
- fallback: false
62
- }),
63
- _ts_metadata("design:type", Boolean)
64
- ], Globals, "shutdownIsEnabled", void 0);
65
- _ts_decorate([
66
- Envapt("UNKNOWN_EXCEPTION_WEBHOOK_URL", {
67
- fallback: void 0
68
- }),
69
- _ts_metadata("design:type", String)
70
- ], Globals, "unknownExceptionWebhookUrl", void 0);
71
-
72
- // src/interfaces/Components.ts
73
88
  var BuilderTypes = {
74
89
  command: SlashCommandBuilder,
75
90
  embed: EmbedBuilder,
@@ -83,7 +98,13 @@ var BuilderTypes = {
83
98
  modal: ModalBuilder,
84
99
  context_menu: ContextMenuCommandBuilder,
85
100
  subcommand: SlashCommandSubcommandBuilder,
86
- group: SlashCommandSubcommandGroupBuilder
101
+ group: SlashCommandSubcommandGroupBuilder,
102
+ container: ContainerBuilder,
103
+ text_display: TextDisplayBuilder,
104
+ file: FileBuilder,
105
+ media: MediaGalleryBuilder,
106
+ section: SectionBuilder,
107
+ separator: SeparatorBuilder
87
108
  };
88
109
  var RowTypes = {
89
110
  button: ActionRowBuilder,
@@ -139,7 +160,7 @@ var BuilderComponent = class extends BaseComponent {
139
160
  constructor(type) {
140
161
  const ComponentClass = BuilderTypes[type];
141
162
  super(ComponentClass);
142
- if (this.instance instanceof EmbedBuilder) this.instance.setColor(Globals.botColor);
163
+ if (this.instance instanceof EmbedBuilder) this.instance.setColor(this.botColor);
143
164
  if (this.instance instanceof SlashCommandBuilder || this.instance instanceof ContextMenuCommandBuilder) {
144
165
  this.instance.setContexts(InteractionContextType.Guild);
145
166
  }
@@ -148,6 +169,12 @@ var BuilderComponent = class extends BaseComponent {
148
169
  return this.instance;
149
170
  }
150
171
  };
172
+ _ts_decorate([
173
+ Envapt("DEFAULT_BOT_COLOR", {
174
+ fallback: "Default"
175
+ }),
176
+ _ts_metadata("design:type", typeof ColorResolvable === "undefined" ? Object : ColorResolvable)
177
+ ], BuilderComponent.prototype, "botColor", void 0);
151
178
  var RowComponent = class extends BaseComponent {
152
179
  static {
153
180
  __name(this, "RowComponent");
@@ -222,387 +249,6 @@ var CustomError = class extends Error {
222
249
  }
223
250
  };
224
251
 
225
- // src/bot/errors/Database.ts
226
- var DatabaseError = class extends CustomError {
227
- static {
228
- __name(this, "DatabaseError");
229
- }
230
- uuid;
231
- _emit = true;
232
- /**
233
- * Creates a new DatabaseError.
234
- *
235
- * @param message - The error message describing what went wrong
236
- * @param uuid - A unique identifier for this specific error instance
237
- */
238
- constructor(message, uuid) {
239
- super(message), this.uuid = uuid;
240
- this.name = "DatabaseError";
241
- this.response.setTitle("Database Error").setDescription(`An error occurred while interacting with the database.
242
- ### UUID: \`${this.uuid}\``);
243
- }
244
- };
245
- var Logger = class _Logger {
246
- static {
247
- __name(this, "Logger");
248
- }
249
- static instances = /* @__PURE__ */ new Map();
250
- static instance(prefix) {
251
- let instance = this.instances.get(prefix);
252
- if (!instance) {
253
- instance = new _Logger(prefix);
254
- this.instances.set(prefix, instance);
255
- }
256
- return instance;
257
- }
258
- constructor(transportName) {
259
- const consoleTransport = this.createConsoleTransport(transportName);
260
- this.initializeLogger(consoleTransport);
261
- }
262
- getFormatCustomizations() {
263
- const padding = 7;
264
- return [
265
- format.errors({
266
- stack: true
267
- }),
268
- format.splat(),
269
- format.colorize({
270
- level: true
271
- }),
272
- format.timestamp({
273
- format: "D MMM, hh:mm:ss a"
274
- }),
275
- format.printf((info) => {
276
- const ts = String(info.timestamp ?? "");
277
- const lvl = String(info.level).padEnd(padding);
278
- const lbl = String(info.label ?? "");
279
- const msg = String(info.message ?? "");
280
- const base = `${ts} [${lvl}]: ${lbl} - ${msg}`;
281
- const splatSym = Symbol.for("splat");
282
- const raw = info[splatSym];
283
- const extras = Array.isArray(raw) ? raw : [];
284
- const cleaned = extras.filter((x) => !(x instanceof Error)).filter((x) => {
285
- if (!x) return false;
286
- if (typeof x !== "object") return true;
287
- return Object.keys(x).length > 0;
288
- });
289
- let rendered = base;
290
- if (typeof info.stack === "string") {
291
- rendered += `
292
- ${String(info.stack)}`;
293
- }
294
- if (cleaned.length) {
295
- const parts = [];
296
- for (const x of cleaned) {
297
- if (typeof x === "string") parts.push(x);
298
- else {
299
- try {
300
- parts.push(JSON.stringify(x, null, 2));
301
- } catch {
302
- parts.push(String(x));
303
- }
304
- }
305
- }
306
- rendered += `
307
- ${parts.join(" ")}`;
308
- }
309
- return rendered;
310
- })
311
- ];
312
- }
313
- createConsoleTransport(transportName) {
314
- return new transports.Console({
315
- format: format.combine(format.label({
316
- label: transportName
317
- }), ...this.getFormatCustomizations()),
318
- level: Globals.isDevelopment ? "silly" : Globals.isStaging ? "debug" : "info"
319
- });
320
- }
321
- initializeLogger(consoleTransport) {
322
- const transportsArray = [
323
- consoleTransport
324
- ];
325
- if (Globals.isDevelopment) {
326
- const maxSizeInMB = 10;
327
- transportsArray.push(new transports.File({
328
- filename: "logs/application.log",
329
- level: "debug",
330
- format: format.combine(format.uncolorize(), format.errors({
331
- stack: true
332
- }), format.timestamp(), format.json({
333
- bigint: true,
334
- space: 2
335
- })),
336
- maxsize: maxSizeInMB * 1024 * 1024,
337
- maxFiles: 5,
338
- tailable: true
339
- }));
340
- }
341
- this.logger = createLogger({
342
- transports: transportsArray
343
- });
344
- }
345
- /**
346
- * Logs an error message with optional additional data.
347
- *
348
- * @param msg - The error message to log
349
- * @param args - Additional data to include in the log entry
350
- */
351
- error(msg, ...args) {
352
- this.logger.error(msg, ...args);
353
- }
354
- /**
355
- * Logs a warning message with optional additional data.
356
- *
357
- * @param msg - The warning message to log
358
- * @param args - Additional data to include in the log entry
359
- */
360
- warn(msg, ...args) {
361
- this.logger.warn(msg, ...args);
362
- }
363
- /**
364
- * Logs an informational message with optional additional data.
365
- *
366
- * @param msg - The informational message to log
367
- * @param args - Additional data to include in the log entry
368
- */
369
- info(msg, ...args) {
370
- this.logger.info(msg, ...args);
371
- }
372
- /**
373
- * Logs an HTTP-related message with optional additional data.
374
- *
375
- * @param msg - The HTTP message to log
376
- * @param args - Additional data to include in the log entry
377
- */
378
- http(msg, ...args) {
379
- this.logger.http(msg, ...args);
380
- }
381
- /**
382
- * Logs a verbose message with optional additional data.
383
- *
384
- * @param msg - The verbose message to log
385
- * @param args - Additional data to include in the log entry
386
- */
387
- verbose(msg, ...args) {
388
- this.logger.verbose(msg, ...args);
389
- }
390
- /**
391
- * Logs a debug message with optional additional data.
392
- *
393
- * @param msg - The debug message to log
394
- * @param args - Additional data to include in the log entry
395
- */
396
- debug(msg, ...args) {
397
- this.logger.debug(msg, ...args);
398
- }
399
- /**
400
- * Logs a silly/trace level message with optional additional data.
401
- *
402
- * @param msg - The silly message to log
403
- * @param args - Additional data to include in the log entry
404
- */
405
- silly(msg, ...args) {
406
- this.logger.silly(msg, ...args);
407
- }
408
- /**
409
- * Static method to log an error message with a specific prefix.
410
- * Creates or retrieves a logger instance for the given prefix.
411
- *
412
- * @param prefix - The logger prefix/label to use
413
- * @param msg - The error message to log
414
- * @param args - Additional data to include in the log entry
415
- */
416
- static Error(prefix, msg, ...args) {
417
- const logger = this.instance(prefix);
418
- logger.error(msg, ...args);
419
- }
420
- /**
421
- * Static method to log an informational message with a specific prefix.
422
- * Creates or retrieves a logger instance for the given prefix.
423
- *
424
- * @param prefix - The logger prefix/label to use
425
- * @param msg - The informational message to log
426
- * @param args - Additional data to include in the log entry
427
- */
428
- static Info(prefix, msg, ...args) {
429
- const logger = this.instance(prefix);
430
- logger.info(msg, ...args);
431
- }
432
- /**
433
- * Static method to log a warning message with a specific prefix.
434
- * Creates or retrieves a logger instance for the given prefix.
435
- *
436
- * @param prefix - The logger prefix/label to use
437
- * @param msg - The warning message to log
438
- * @param args - Additional data to include in the log entry
439
- */
440
- static Warn(prefix, msg, ...args) {
441
- const logger = this.instance(prefix);
442
- logger.warn(msg, ...args);
443
- }
444
- /**
445
- * Static method to log a debug message with a specific prefix.
446
- * Creates or retrieves a logger instance for the given prefix.
447
- *
448
- * @param prefix - The logger prefix/label to use
449
- * @param msg - The debug message to log
450
- * @param args - Additional data to include in the log entry
451
- */
452
- static Debug(prefix, msg, ...args) {
453
- const logger = this.instance(prefix);
454
- logger.debug(msg, ...args);
455
- }
456
- /**
457
- * Static method to log a silly/trace level message with a specific prefix.
458
- * Creates or retrieves a logger instance for the given prefix.
459
- *
460
- * @param prefix - The logger prefix/label to use
461
- * @param msg - The silly message to log
462
- * @param args - Additional data to include in the log entry
463
- */
464
- static Silly(prefix, msg, ...args) {
465
- const logger = this.instance(prefix);
466
- logger.silly(msg, ...args);
467
- }
468
- };
469
-
470
- // src/library/Helpers.ts
471
- function numberFixer(num, decimalPlaces) {
472
- const factor = Math.pow(10, decimalPlaces);
473
- return Math.round((num + Number.EPSILON) * factor) / factor;
474
- }
475
- __name(numberFixer, "numberFixer");
476
- function percentage(num1, num2) {
477
- return Number((num1 / num2 * 100).toFixed(2));
478
- }
479
- __name(percentage, "percentage");
480
- function generateAsciiTable(data) {
481
- if (data.length === 0) return "";
482
- const firstRow = data[0];
483
- if (!firstRow || firstRow.length === 0) return "";
484
- let table = "";
485
- const columnWidths = [];
486
- for (let i = 0; i < firstRow.length; i++) {
487
- let maxWidth = 0;
488
- for (const row of data) {
489
- const cell = row[i];
490
- if (cell !== void 0) maxWidth = Math.max(maxWidth, cell.length);
491
- }
492
- columnWidths.push(maxWidth);
493
- }
494
- const createLine = /* @__PURE__ */ __name((char, left, intersect, right) => {
495
- let line = left;
496
- columnWidths.forEach((width, index) => {
497
- line += char.repeat(width + 2);
498
- if (index < columnWidths.length - 1) line += intersect;
499
- else line += right;
500
- });
501
- line += "\n";
502
- return line;
503
- }, "createLine");
504
- table += createLine("\u2550", "\u2554", "\u2566", "\u2557");
505
- data.forEach((row, rowIndex) => {
506
- table += "\u2551";
507
- row.forEach((cell, columnIndex) => {
508
- const columnWidth = columnWidths[columnIndex];
509
- if (columnWidth !== void 0) table += ` ${cell.padEnd(columnWidth)} \u2551`;
510
- });
511
- table += "\n";
512
- if (rowIndex < data.length - 1) table += createLine("\u2500", "\u2560", "\u256C", "\u2563");
513
- else table += createLine("\u2550", "\u255A", "\u2569", "\u255D");
514
- });
515
- return table;
516
- }
517
- __name(generateAsciiTable, "generateAsciiTable");
518
- function formatWord(word) {
519
- return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
520
- }
521
- __name(formatWord, "formatWord");
522
- function longestStringLength(arr) {
523
- return Math.max(...arr.map((el) => el.toString().length));
524
- }
525
- __name(longestStringLength, "longestStringLength");
526
- function currentTime() {
527
- return Math.floor(Date.now() / 1e3);
528
- }
529
- __name(currentTime, "currentTime");
530
- function ordinal(n) {
531
- const s = [
532
- "th",
533
- "st",
534
- "nd",
535
- "rd"
536
- ];
537
- const v = n % 100;
538
- const index = (v - 20) % 10;
539
- const suffix = s[index] ?? s[v] ?? s[0];
540
- if (!suffix) return `${n}th`;
541
- return `${n}${suffix}`;
542
- }
543
- __name(ordinal, "ordinal");
544
- function prettyDifference(numBefore, numAfter) {
545
- return (numAfter - numBefore > 0 ? `+${numAfter - numBefore}` : numAfter - numBefore).toString();
546
- }
547
- __name(prettyDifference, "prettyDifference");
548
- function isTsOrJsFile(entry) {
549
- return entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".js")) && !entry.name.endsWith(".d.ts") && !entry.name.endsWith(".map");
550
- }
551
- __name(isTsOrJsFile, "isTsOrJsFile");
552
- async function traverseDirectory(dir, callback) {
553
- let entries;
554
- try {
555
- entries = await readdir(dir, {
556
- withFileTypes: true
557
- });
558
- } catch {
559
- Logger.Error("Failed to read directory", dir);
560
- entries = [];
561
- }
562
- for (const entry of entries) {
563
- const fullPath = path.join(dir, entry.name);
564
- const relativePath = path.relative(process.cwd(), fullPath);
565
- if (entry.isDirectory()) {
566
- await traverseDirectory(fullPath, callback);
567
- } else if (isTsOrJsFile(entry)) {
568
- const imported = await import(fullPath);
569
- await callback(fullPath, relativePath, imported);
570
- }
571
- }
572
- }
573
- __name(traverseDirectory, "traverseDirectory");
574
- function throwCustomError(error, message, CustomError2) {
575
- const uuid = crypto.randomUUID();
576
- Logger.Error("Throwing Custom Error", error.name);
577
- if (typeof CustomError2 === typeof DatabaseError) {
578
- const errorMessage = error instanceof Error ? error.message : message;
579
- throw new CustomError2(errorMessage, uuid);
580
- } else {
581
- if (error instanceof Error) {
582
- throw new CustomError2(`${message}: ${error.message ? error.message : error.toString()}`);
583
- } else {
584
- throw new CustomError2(message);
585
- }
586
- }
587
- }
588
- __name(throwCustomError, "throwCustomError");
589
- function prettify(key) {
590
- return key.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/_/g, " ").trim();
591
- }
592
- __name(prettify, "prettify");
593
- function fyShuffle(items) {
594
- const array = items.slice();
595
- for (let i = array.length - 1; i > 0; i--) {
596
- const j = Math.floor(Math.random() * (i + 1));
597
- [array[i], array[j]] = [
598
- array[j],
599
- array[i]
600
- ];
601
- }
602
- return array;
603
- }
604
- __name(fyShuffle, "fyShuffle");
605
-
606
252
  // src/bot/decorators/CommandRegisterable.ts
607
253
  var CommandMetadataKey = Symbol("command:metadata");
608
254
  function RegisterCommand(scope, guilds = []) {
@@ -634,14 +280,14 @@ var CommandRegistry = class {
634
280
  async init() {
635
281
  if (this.isInitialised) return;
636
282
  this.isInitialised = true;
637
- this.logger.info(chalk6.bold(this.core.config.bot.commands.path));
283
+ this.logger.info(chalk2.bold(this.core.config.bot.commands.path));
638
284
  await this.loadCommands(this.core.config.bot.commands.path);
639
- this.logger.info(`${chalk6.bold.green("Loaded")}: ${chalk6.magenta.bold(this.globalCommands.length)} global, ${chalk6.magenta.bold(this.guildCommands.size)} guild groups`);
285
+ this.logger.info(`${chalk2.bold.green("Loaded")}: ${chalk2.magenta.bold(this.globalCommands.length)} global, ${chalk2.magenta.bold(this.guildCommands.size)} guild groups`);
640
286
  }
641
287
  async loadCommands(dir) {
642
288
  await traverseDirectory(dir, (_full, rel, mod) => {
643
289
  for (const exported of Object.values(mod)) if (this.isCommandClass(exported)) this.registerCommand(exported, rel);
644
- });
290
+ }, this.logger);
645
291
  }
646
292
  isCommandClass(obj) {
647
293
  if (typeof obj !== "function") return false;
@@ -655,24 +301,24 @@ var CommandRegistry = class {
655
301
  const commandType = comp instanceof SlashCommandBuilder ? "slash command" : "context menu command";
656
302
  if (meta.scope === "global") {
657
303
  this.globalCommands.push(comp);
658
- this.logger.info(`${chalk6.italic("Registered")} ${chalk6.bold.yellow(ctor.name)} from ${chalk6.gray(rel)}`);
659
- this.logger.info(` \u2192 Global ${commandType}: ${chalk6.bold.cyan(comp.name)}`);
304
+ this.logger.info(`${chalk2.italic("Registered")} ${chalk2.bold.yellow(ctor.name)} from ${chalk2.gray(rel)}`);
305
+ this.logger.info(` \u2192 Global ${commandType}: ${chalk2.bold.cyan(comp.name)}`);
660
306
  } else {
661
307
  for (const g of meta.guilds) {
662
308
  const arr = this.guildCommands.get(g) ?? [];
663
309
  arr.push(comp);
664
310
  this.guildCommands.set(g, arr);
665
311
  }
666
- this.logger.info(`${chalk6.italic("Registered")} ${chalk6.bold.yellow(ctor.name)} from ${chalk6.gray(rel)}`);
667
- this.logger.info(` \u2192 Guild ${commandType}: ${chalk6.bold.cyan(comp.name)} for ${chalk6.magenta.bold(meta.guilds.length)} guild(s)`);
312
+ this.logger.info(`${chalk2.italic("Registered")} ${chalk2.bold.yellow(ctor.name)} from ${chalk2.gray(rel)}`);
313
+ this.logger.info(` \u2192 Guild ${commandType}: ${chalk2.bold.cyan(comp.name)} for ${chalk2.magenta.bold(meta.guilds.length)} guild(s)`);
668
314
  }
669
315
  }
670
316
  async setCommands() {
671
317
  if (this.globalCommands.length > 0) {
672
318
  await this.core.bot.client.application?.commands.set(this.globalCommands);
673
319
  const tag = this.globalCommands.length === 1 ? "command" : "commands";
674
- this.logger.info(`${chalk6.bold.green("Configured")} ${chalk6.magenta.bold(this.globalCommands.length)} global ${tag}`);
675
- this.logger.info(` \u2192 ${this.globalCommands.map((command) => chalk6.bold.cyan(command.name)).join(", ")}`);
320
+ this.logger.info(`${chalk2.bold.green("Configured")} ${chalk2.magenta.bold(this.globalCommands.length)} global ${tag}`);
321
+ this.logger.info(` \u2192 ${this.globalCommands.map((command) => chalk2.bold.cyan(command.name)).join(", ")}`);
676
322
  }
677
323
  for (const [guildId, commands] of this.guildCommands.entries()) {
678
324
  const guild = this.core.bot.client.guilds.cache.get(guildId);
@@ -682,8 +328,8 @@ var CommandRegistry = class {
682
328
  }
683
329
  await guild.commands.set(commands);
684
330
  const tag = commands.length === 1 ? "command" : "commands";
685
- this.logger.info(`${chalk6.bold.green("Configured")} ${chalk6.magenta.bold(commands.length)} ${tag} for guild ${chalk6.bold.yellow(guild.name)}`);
686
- this.logger.info(` \u2192 ${commands.map((command) => chalk6.bold.cyan(command.name)).join(", ")}`);
331
+ this.logger.info(`${chalk2.bold.green("Configured")} ${chalk2.magenta.bold(commands.length)} ${tag} for guild ${chalk2.bold.yellow(guild.name)}`);
332
+ this.logger.info(` \u2192 ${commands.map((command) => chalk2.bold.cyan(command.name)).join(", ")}`);
687
333
  }
688
334
  }
689
335
  };
@@ -800,24 +446,24 @@ var EventController = class {
800
446
  }
801
447
  this.isInitialized = true;
802
448
  const handlersDir = this.core.config.bot.events.path;
803
- this.logger.info(chalk6.bold(handlersDir));
449
+ this.logger.info(chalk2.bold(handlersDir));
804
450
  await this.loadHandlers(handlersDir);
805
451
  this.attachToClient();
806
452
  const loadedEventsArray = [];
807
453
  this.eventMap.forEach((handlers, eventName) => {
808
- loadedEventsArray.push(`${chalk6.magenta.bold(handlers.length)} ${eventName}`);
454
+ loadedEventsArray.push(`${chalk2.magenta.bold(handlers.length)} ${eventName}`);
809
455
  });
810
- this.logger.info(`${chalk6.bold.green("Loaded")}: ${this.eventMap.size > 0 ? loadedEventsArray.join(", ") : "none"}`);
456
+ this.logger.info(`${chalk2.bold.green("Loaded")}: ${this.eventMap.size > 0 ? loadedEventsArray.join(", ") : "none"}`);
811
457
  }
812
458
  async loadHandlers(dir) {
813
459
  await traverseDirectory(dir, (_fullPath, relativePath, imported) => {
814
460
  for (const val of Object.values(imported)) {
815
461
  if (this.isEventHandlerClass(val)) {
816
462
  this.registerHandler(val);
817
- this.logger.info(`${chalk6.italic("Registered")} ${chalk6.bold.yellow(val.name)} from ${chalk6.gray(relativePath)}`);
463
+ this.logger.info(`${chalk2.italic("Registered")} ${chalk2.bold.yellow(val.name)} from ${chalk2.gray(relativePath)}`);
818
464
  }
819
465
  }
820
- });
466
+ }, this.logger);
821
467
  }
822
468
  isEventHandlerClass(obj) {
823
469
  if (typeof obj !== "function") return false;
@@ -835,7 +481,7 @@ var EventController = class {
835
481
  }
836
482
  attachToClient() {
837
483
  for (const [eventName] of this.eventMap) {
838
- this.logger.debug(`Attaching ${chalk6.bold.green(eventName)} to ${chalk6.bold.yellow(this.core.bot.client.user?.username)}`);
484
+ this.logger.debug(`Attaching ${chalk2.bold.green(eventName)} to ${chalk2.bold.yellow(this.core.bot.client.user?.username)}`);
839
485
  this.core.bot.client.on(eventName, (...args) => {
840
486
  void (async () => {
841
487
  await this.processEvent(eventName, args);
@@ -848,7 +494,7 @@ var EventController = class {
848
494
  if (!handlerCtors || handlerCtors.length === 0) return;
849
495
  for (const HandlerCtor of handlerCtors) {
850
496
  try {
851
- this.logger.debug(`Processing ${chalk6.bold.green(eventName)} with ${chalk6.gray(HandlerCtor.name)}`);
497
+ this.logger.debug(`Processing ${chalk2.bold.green(eventName)} with ${chalk2.gray(HandlerCtor.name)}`);
852
498
  const handler = new HandlerCtor(args, this.core);
853
499
  if (handler.hasChecks()) {
854
500
  await handler.runChecks();
@@ -959,6 +605,29 @@ function storeMetadata(symbol, routes, constructor) {
959
605
  Reflect.defineMetadata(InteractionMetadataKey, true, constructor);
960
606
  }
961
607
  __name(storeMetadata, "storeMetadata");
608
+
609
+ // src/bot/errors/Database.ts
610
+ var DatabaseError = class extends CustomError {
611
+ static {
612
+ __name(this, "DatabaseError");
613
+ }
614
+ uuid;
615
+ _emit = true;
616
+ /**
617
+ * Creates a new DatabaseError.
618
+ *
619
+ * @param message - The error message describing what went wrong
620
+ * @param uuid - A unique identifier for this specific error instance
621
+ */
622
+ constructor(message, uuid) {
623
+ super(message), this.uuid = uuid;
624
+ this.name = "DatabaseError";
625
+ this.response.setTitle("Database Error").setDescription(`An error occurred while interacting with the database.
626
+ ### UUID: \`${this.uuid}\``);
627
+ }
628
+ };
629
+
630
+ // src/bot/utilities/ErrorHandlingUtils.ts
962
631
  var ErrorHandlingUtils = class {
963
632
  static {
964
633
  __name(this, "ErrorHandlingUtils");
@@ -1129,31 +798,31 @@ var InteractionController = class {
1129
798
  if (this.isInitialized) return;
1130
799
  this.isInitialized = true;
1131
800
  const handlersDir = this.core.config.bot.interactions.path;
1132
- this.logger.info(chalk6.bold(handlersDir));
801
+ this.logger.info(chalk2.bold(handlersDir));
1133
802
  await this.loadHandlers(handlersDir);
1134
803
  this.attachToClient();
1135
- this.logger.info(`${chalk6.bold.green("Loaded interaction handlers:")}`);
1136
- this.logger.info(`\u2192 ${chalk6.magenta.bold(this.slashMap.size)} slash commands`);
1137
- this.logger.info(`\u2192 ${chalk6.magenta.bold(this.buttonMap.size)} buttons`);
1138
- this.logger.info(`\u2192 ${chalk6.magenta.bold(this.modalMap.size)} modals`);
1139
- this.logger.info(`\u2192 ${chalk6.magenta.bold(this.stringSelectMap.size)} string selects`);
1140
- this.logger.info(`\u2192 ${chalk6.magenta.bold(this.userSelectMap.size)} user selects`);
1141
- this.logger.info(`\u2192 ${chalk6.magenta.bold(this.roleSelectMap.size)} role selects`);
1142
- this.logger.info(`\u2192 ${chalk6.magenta.bold(this.channelSelectMap.size)} channel selects`);
1143
- this.logger.info(`\u2192 ${chalk6.magenta.bold(this.mentionableSelectMap.size)} mentionable selects`);
1144
- this.logger.info(`\u2192 ${chalk6.magenta.bold(this.messageContextMenuMap.size)} message context menus`);
1145
- this.logger.info(`\u2192 ${chalk6.magenta.bold(this.userContextMenuMap.size)} user context menus`);
1146
- this.logger.info(`\u2192 ${chalk6.magenta.bold(this.autocompleteMap.size)} autocomplete`);
804
+ this.logger.info(`${chalk2.bold.green("Loaded interaction handlers:")}`);
805
+ this.logger.info(`\u2192 ${chalk2.magenta.bold(this.slashMap.size)} slash commands`);
806
+ this.logger.info(`\u2192 ${chalk2.magenta.bold(this.buttonMap.size)} buttons`);
807
+ this.logger.info(`\u2192 ${chalk2.magenta.bold(this.modalMap.size)} modals`);
808
+ this.logger.info(`\u2192 ${chalk2.magenta.bold(this.stringSelectMap.size)} string selects`);
809
+ this.logger.info(`\u2192 ${chalk2.magenta.bold(this.userSelectMap.size)} user selects`);
810
+ this.logger.info(`\u2192 ${chalk2.magenta.bold(this.roleSelectMap.size)} role selects`);
811
+ this.logger.info(`\u2192 ${chalk2.magenta.bold(this.channelSelectMap.size)} channel selects`);
812
+ this.logger.info(`\u2192 ${chalk2.magenta.bold(this.mentionableSelectMap.size)} mentionable selects`);
813
+ this.logger.info(`\u2192 ${chalk2.magenta.bold(this.messageContextMenuMap.size)} message context menus`);
814
+ this.logger.info(`\u2192 ${chalk2.magenta.bold(this.userContextMenuMap.size)} user context menus`);
815
+ this.logger.info(`\u2192 ${chalk2.magenta.bold(this.autocompleteMap.size)} autocomplete`);
1147
816
  }
1148
817
  async loadHandlers(dir) {
1149
818
  await traverseDirectory(dir, (_fullPath, relativePath, imported) => {
1150
819
  for (const val of Object.values(imported)) {
1151
820
  if (this.isHandlerClass(val)) {
1152
821
  this.registerHandler(val);
1153
- this.logger.info(`${chalk6.italic("Registered")} ${chalk6.bold.yellow(val.name)} from ${chalk6.gray(relativePath)}`);
822
+ this.logger.info(`${chalk2.italic("Registered")} ${chalk2.bold.yellow(val.name)} from ${chalk2.gray(relativePath)}`);
1154
823
  }
1155
824
  }
1156
- });
825
+ }, this.logger);
1157
826
  }
1158
827
  isHandlerClass(obj) {
1159
828
  if (typeof obj !== "function") return false;
@@ -1219,7 +888,7 @@ var InteractionController = class {
1219
888
  attachToClient() {
1220
889
  this.core.bot.client.on(Events.InteractionCreate, (interaction) => {
1221
890
  this.handleInteraction(interaction).catch((err) => {
1222
- this.logger.error(`[${chalk6.bold.red("UNHANDLED ERROR AT ROOT")}] ${err.name}`, err.stack);
891
+ this.logger.error(`[${chalk2.bold.red("UNHANDLED ERROR AT ROOT")}] ${err.name}`, err.stack);
1223
892
  });
1224
893
  });
1225
894
  }
@@ -1248,10 +917,10 @@ var InteractionController = class {
1248
917
  }
1249
918
  let HandlerCtor = getHandler(key);
1250
919
  if (!HandlerCtor) {
1251
- this.logger.warn(`No handler found for key ${chalk6.bold.cyan(key)}. Falling back to UnhandledEvent.`);
920
+ this.logger.warn(`No handler found for key ${chalk2.bold.cyan(key)}. Falling back to UnhandledEvent.`);
1252
921
  HandlerCtor = UnhandledEvent;
1253
922
  }
1254
- this.logger.debug(`Processing ${chalk6.bold.green(key)} with ${chalk6.gray(HandlerCtor.name)}`);
923
+ this.logger.debug(`Processing ${chalk2.bold.green(key)} with ${chalk2.gray(HandlerCtor.name)}`);
1255
924
  const handler = new HandlerCtor(interaction, this.core, args);
1256
925
  if (handler.hasChecks()) await handler.runChecks();
1257
926
  if (handler.shouldBreak()) return;
@@ -1361,7 +1030,7 @@ var EmojiInjector = class {
1361
1030
  }
1362
1031
  async init() {
1363
1032
  if (!this.core.config.bot.emojis || Object.keys(this.core.config.bot.emojis).length === 0) {
1364
- this.logger.info(`${chalk6.bold.green("Loaded")}: ${chalk6.magenta.bold("0")} emojis`);
1033
+ this.logger.info(`${chalk2.bold.green("Loaded")}: ${chalk2.magenta.bold("0")} emojis`);
1365
1034
  return;
1366
1035
  }
1367
1036
  const configEmojis = this.core.config.bot.emojis;
@@ -1372,335 +1041,25 @@ var EmojiInjector = class {
1372
1041
  if (emoji) {
1373
1042
  configEmojis[key] = `<${emoji.identifier}>`;
1374
1043
  foundCount++;
1044
+ this.logger.debug(`${chalk2.bold.green("Found")}: ${chalk2.magenta.bold(emojiName)} (${emoji.id})`);
1375
1045
  }
1376
1046
  });
1377
- this.logger.info(`${chalk6.bold.green("Loaded")}: ${chalk6.magenta.bold(foundCount)} emojis`);
1378
- }
1379
- };
1380
- var Plugin = class {
1381
- static {
1382
- __name(this, "Plugin");
1383
- }
1384
- pluggable;
1385
- constructor(pluggable) {
1386
- this.pluggable = pluggable;
1387
- }
1388
- };
1389
- var Pluggable = class _Pluggable {
1390
- static {
1391
- __name(this, "Pluggable");
1392
- }
1393
- isInitialized = false;
1394
- shutdown;
1395
- startup;
1396
- static PLUGIN_INIT_TIMEOUT_MS = 15e3;
1397
- constructor(shutdown, startup) {
1398
- this.shutdown = shutdown;
1399
- this.startup = startup;
1400
- }
1401
- async init() {
1402
- if (this.isInitialized) return this;
1403
- await this.startup.run();
1404
- this.isInitialized = true;
1405
- return this;
1406
- }
1407
- /**
1408
- * Attaches a plugin to this instance
1409
- *
1410
- * Plugins provide external functionality and are initialized during the specified startup phase.
1411
- * The plugin instance becomes available as a property in `core` wherever it's available.
1412
- *
1413
- * Make sure to augment the {@link Core} interface with the plugin type to ensure TypeScript recognizes it and provides intellisense.
1414
- *
1415
- * @typeParam Key - The property name for accessing the plugin
1416
- * @typeParam Ctor - The plugin constructor type
1417
- * @param key - Property name to access the plugin instance
1418
- * @param Plugin - Plugin constructor class
1419
- * @param startupPhase - When during startup to initialize this plugin ({@link StartupPhase})
1420
- * @param args - Additional arguments to pass to the plugin constructor
1421
- * @returns This instance with the plugin attached as a typed property
1422
- * @throws An {@link Error} When called after initialization or if key already exists
1423
- * @example
1424
- * ```typescript
1425
- * seedcord.attach('db', Mongo, StartupPhase.Configuration, { uri: 'mongodb://...', dbName: 'seedcord' })
1426
- * ```
1427
- */
1428
- attach(key, Plugin2, startupPhase, ...args) {
1429
- if (this.isInitialized) throw new Error("Cannot attach a plugin after initialization.");
1430
- if (this[key]) throw new Error(`Plugin with key "${key}" already exists.`);
1431
- const instance = new Plugin2(this, ...args);
1432
- const entry = {
1433
- [key]: instance
1434
- };
1435
- this.startup.addTask(startupPhase, `Plugin:${key}`, async () => {
1436
- instance.logger.info(chalk6.bold("Initializing"));
1437
- await instance.init();
1438
- instance.logger.info(chalk6.bold("Initialized"));
1439
- }, _Pluggable.PLUGIN_INIT_TIMEOUT_MS);
1440
- return Object.assign(this, entry);
1441
- }
1442
- };
1443
- var CoordinatedLifecycle = class {
1444
- static {
1445
- __name(this, "CoordinatedLifecycle");
1446
- }
1447
- phaseOrder;
1448
- phaseEnum;
1449
- logger;
1450
- events = new EventEmitter();
1451
- tasksMap = /* @__PURE__ */ new Map();
1452
- constructor(loggerName, phaseOrder, phaseEnum) {
1453
- this.phaseOrder = phaseOrder;
1454
- this.phaseEnum = phaseEnum;
1455
- this.logger = new Logger(loggerName);
1456
- this.phaseOrder.forEach((phase) => this.tasksMap.set(phase, []));
1457
- }
1458
- /**
1459
- * Adds a lifecycle task to a specific phase.
1460
- *
1461
- * Tasks are executed in phase order during lifecycle operations.
1462
- * Each task has a timeout to prevent hanging operations.
1463
- *
1464
- * @param phase - The lifecycle phase to add the task to
1465
- * @param taskName - Unique name for the task (used for logging and removal)
1466
- * @param task - Async function to execute during the phase
1467
- * @param timeoutMs - Maximum time allowed for task execution in milliseconds
1468
- * @example
1469
- * ```typescript
1470
- * lifecycle.addTask(StartupPhase.Services, 'start-database', async () => {
1471
- * await database.connect();
1472
- * }, 10000);
1473
- * ```
1474
- */
1475
- addTask(phase, taskName, task, timeoutMs) {
1476
- if (!this.canAddTask()) return;
1477
- const tasks = this.tasksMap.get(phase);
1478
- if (!tasks) throw new Error(`Unknown phase: ${phase}`);
1479
- tasks.push({
1480
- name: taskName,
1481
- task,
1482
- timeout: timeoutMs
1483
- });
1484
- this.logger.debug(`${chalk6.italic("Added")} ${this.getTaskType()} task ${chalk6.bold.cyan(taskName)} to phase ${chalk6.bold.magenta(this.phaseEnum[phase])}`);
1485
- }
1486
- /**
1487
- * Removes a lifecycle task from a specific phase.
1488
- *
1489
- * @param phase - The lifecycle phase to remove the task from
1490
- * @param taskName - Name of the task to remove
1491
- * @returns True if the task was found and removed, false otherwise
1492
- */
1493
- removeTask(phase, taskName) {
1494
- if (!this.canRemoveTask()) return false;
1495
- const tasks = this.tasksMap.get(phase);
1496
- if (!tasks) return false;
1497
- const initialLength = tasks.length;
1498
- const filteredTasks = tasks.filter((task) => task.name !== taskName);
1499
- this.tasksMap.set(phase, filteredTasks);
1500
- const removed = initialLength !== filteredTasks.length;
1501
- if (removed) {
1502
- this.logger.debug(`${chalk6.italic("Removed")} ${this.getTaskType()} task ${chalk6.bold.cyan(taskName)} from phase ${chalk6.bold.magenta(this.phaseEnum[phase])}`);
1503
- }
1504
- return removed;
1505
- }
1506
- /**
1507
- * Run all tasks in a specific phase
1508
- */
1509
- async runPhase(phase) {
1510
- const tasks = this.tasksMap.get(phase) ?? [];
1511
- if (tasks.length === 0) {
1512
- this.logger.warn(`No tasks to run in phase ${chalk6.bold.magenta(this.phaseEnum[phase])}`);
1513
- return;
1514
- }
1515
- this.logger.info(`${chalk6.bold.yellow("Running")} ${this.getTaskType()} phase ${chalk6.bold.magenta(this.phaseEnum[phase])} with ${chalk6.bold.cyan(tasks.length)} tasks`);
1516
- this.emit(`phase:${phase}:start`);
1517
- const results = await this.executeTasksInPhase(phase, tasks);
1518
- const failures = results.filter((r) => r.status === "rejected").length;
1519
- if (failures > 0) {
1520
- const errorMessage = `Phase ${chalk6.bold.magenta(this.phaseEnum[phase])} completed with ${chalk6.bold.red(failures)} failed tasks`;
1521
- throw new Error(errorMessage);
1522
- } else {
1523
- this.logger.info(`Phase ${chalk6.bold.magenta(this.phaseEnum[phase])} ${chalk6.bold.green("completed successfully")}`);
1524
- }
1525
- this.emit(`phase:${phase}:complete`);
1526
- }
1527
- /**
1528
- * Run a single task with timeout
1529
- */
1530
- async runTaskWithTimeout(phase, task) {
1531
- this.logger.info(`${chalk6.italic("Starting")} task ${chalk6.bold.cyan(task.name)} in phase ${chalk6.bold.magenta(this.phaseEnum[phase])}`);
1532
- try {
1533
- await Promise.race([
1534
- task.task(),
1535
- new Promise((_, reject) => {
1536
- setTimeout(() => {
1537
- reject(new Error(`Task '${task.name}' timed out after ${task.timeout}ms`));
1538
- }, task.timeout);
1539
- })
1540
- ]);
1541
- this.logger.info(`${chalk6.italic("Completed")} task ${chalk6.bold.cyan(task.name)} in phase ${chalk6.bold.magenta(this.phaseEnum[phase])}`);
1542
- } catch (error) {
1543
- this.logger.error(`${chalk6.italic("Failed")} task ${chalk6.bold.cyan(task.name)} in phase ${chalk6.bold.magenta(this.phaseEnum[phase])}:`, error);
1544
- throw error;
1545
- }
1546
- }
1547
- /**
1548
- * Subscribe to lifecycle events
1549
- */
1550
- on(event, listener) {
1551
- this.events.on(event, listener);
1552
- }
1553
- /**
1554
- * Unsubscribe from lifecycle events
1555
- */
1556
- off(event, listener) {
1557
- this.events.off(event, listener);
1558
- }
1559
- emit(event, ...args) {
1560
- return this.events.emit(event, ...args);
1561
- }
1562
- };
1563
-
1564
- // src/services/Lifecycle/CoordinatedShutdown.ts
1565
- var ShutdownPhase = /* @__PURE__ */ (function(ShutdownPhase2) {
1566
- ShutdownPhase2[ShutdownPhase2["StopAcceptingRequests"] = 1] = "StopAcceptingRequests";
1567
- ShutdownPhase2[ShutdownPhase2["StopServices"] = 2] = "StopServices";
1568
- ShutdownPhase2[ShutdownPhase2["ExternalResources"] = 3] = "ExternalResources";
1569
- ShutdownPhase2[ShutdownPhase2["DiscordCleanup"] = 4] = "DiscordCleanup";
1570
- ShutdownPhase2[ShutdownPhase2["FinalCleanup"] = 5] = "FinalCleanup";
1571
- return ShutdownPhase2;
1572
- })({});
1573
- var PHASE_ORDER = [
1574
- 1,
1575
- 2,
1576
- 3,
1577
- 4,
1578
- 5
1579
- ];
1580
- var LOG_FLUSH_DELAY_MS = 500;
1581
- var CoordinatedShutdown = class extends CoordinatedLifecycle {
1582
- static {
1583
- __name(this, "CoordinatedShutdown");
1584
- }
1585
- isShuttingDown = false;
1586
- exitCode = 0;
1587
- constructor() {
1588
- super("CoordinatedShutdown", PHASE_ORDER, ShutdownPhase);
1589
- this.registerSignalHandlers();
1590
- }
1591
- canAddTask() {
1592
- return Globals.shutdownIsEnabled;
1593
- }
1594
- canRemoveTask() {
1595
- return true;
1596
- }
1597
- getTaskType() {
1598
- return "shutdown";
1599
- }
1600
- async executeTasksInPhase(phase, tasks) {
1601
- const results = [];
1602
- for (const task of tasks) {
1603
- results.push(await Promise.resolve().then(() => this.runTaskWithTimeout(phase, task)).then(
1604
- () => ({
1605
- status: "fulfilled",
1606
- value: void 0
1607
- }),
1608
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
1609
- (reason) => ({
1610
- status: "rejected",
1611
- reason
1612
- })
1613
- ));
1614
- }
1615
- return results;
1616
- }
1617
- registerSignalHandlers() {
1618
- if (!Globals.shutdownIsEnabled) return;
1619
- process.on("SIGTERM", () => {
1620
- this.logger.info(`Received ${chalk6.yellow.bold("SIGTERM")} signal`);
1621
- void this.run(0);
1622
- });
1623
- process.on("SIGINT", () => {
1624
- this.logger.info(`Received ${chalk6.yellow.bold("SIGINT")} signal`);
1625
- void this.run(0);
1626
- });
1627
- }
1628
- /**
1629
- * Adds a task to a specific shutdown phase with timeout.
1630
- *
1631
- * @param phase - The shutdown phase from {@link ShutdownPhase}
1632
- * @param taskName - Unique identifier for the task
1633
- * @param task - Async function to execute
1634
- * @param timeoutMs - Task timeout in milliseconds (default: 5000)
1635
- */
1636
- addTask(phase, taskName, task, timeoutMs = 5e3) {
1637
- super.addTask(phase, taskName, task, timeoutMs);
1638
- }
1639
- /**
1640
- * Removes a task from a specific shutdown phase.
1641
- *
1642
- * @param phase - The shutdown phase to remove from
1643
- * @param taskName - Name of the task to remove
1644
- * @returns True if task was found and removed
1645
- */
1646
- removeTask(phase, taskName) {
1647
- return super.removeTask(phase, taskName);
1648
- }
1649
- /**
1650
- * Executes the coordinated shutdown sequence.
1651
- *
1652
- * Runs all registered tasks across shutdown phases in reverse order.
1653
- * Tasks within each phase are executed in parallel for faster shutdown.
1654
- * Process exits with the specified code when complete.
1655
- *
1656
- * @param exitCode - Process exit code (default: 0)
1657
- * @returns Promise that resolves when shutdown is complete
1658
- * @example
1659
- * ```typescript
1660
- * shutdown.addTask(ShutdownPhase.Services, 'database', () => db.disconnect(), 5000);
1661
- * await shutdown.run(0); // Graceful shutdown
1662
- * ```
1663
- */
1664
- async run(exitCode = 0) {
1665
- if (this.isShuttingDown) {
1666
- this.logger.warn("Shutdown sequence already in progress");
1667
- return;
1668
- }
1669
- this.isShuttingDown = true;
1670
- this.exitCode = exitCode;
1671
- this.logger.info(`${chalk6.bold.yellow("Starting")} coordinated shutdown with exit code ${chalk6.bold.cyan(exitCode)}`);
1672
- this.emit("shutdown:start");
1673
- try {
1674
- for (const phase of PHASE_ORDER) {
1675
- await this.runPhase(phase);
1676
- }
1677
- this.logger.info(`${chalk6.bold.green("Coordinated shutdown completed")} successfully`);
1678
- this.emit("shutdown:complete");
1679
- } catch (error) {
1680
- this.logger.error(`${chalk6.bold.red("Coordinated shutdown failed")}`);
1681
- this.emit("shutdown:error", error);
1682
- } finally {
1683
- this.logger.info(`${chalk6.bold.red("Exiting")} process with code ${chalk6.bold.cyan(this.exitCode)}`);
1684
- setTimeout(() => {
1685
- process.exit(this.exitCode);
1686
- }, LOG_FLUSH_DELAY_MS);
1687
- }
1688
- }
1689
- /**
1690
- * Subscribe to shutdown events
1691
- */
1692
- on(event, listener) {
1693
- super.on(event, listener);
1694
- }
1695
- /**
1696
- * Unsubscribe from shutdown events
1697
- */
1698
- off(event, listener) {
1699
- super.off(event, listener);
1047
+ this.logger.info(`${chalk2.bold.green("Loaded")}: ${chalk2.magenta.bold(foundCount)} emojis`);
1700
1048
  }
1701
1049
  };
1702
1050
 
1703
1051
  // src/bot/Bot.ts
1052
+ function _ts_decorate3(decorators, target, key, desc) {
1053
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1054
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1055
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1056
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1057
+ }
1058
+ __name(_ts_decorate3, "_ts_decorate");
1059
+ function _ts_metadata3(k, v) {
1060
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1061
+ }
1062
+ __name(_ts_metadata3, "_ts_metadata");
1704
1063
  var Bot = class extends Plugin {
1705
1064
  static {
1706
1065
  __name(this, "Bot");
@@ -1754,8 +1113,8 @@ var Bot = class extends Plugin {
1754
1113
  * Logs the bot into Discord using the configured token
1755
1114
  */
1756
1115
  async login() {
1757
- await this._client.login(Globals.botToken);
1758
- this.logger.info(`Logged in as ${chalk6.bold.magenta(this._client.user?.username)}!`);
1116
+ await this._client.login(this.botToken);
1117
+ this.logger.info(`Logged in as ${chalk2.bold.magenta(this._client.user?.username)}!`);
1759
1118
  return this;
1760
1119
  }
1761
1120
  /**
@@ -1763,12 +1122,21 @@ var Bot = class extends Plugin {
1763
1122
  */
1764
1123
  async logout() {
1765
1124
  await this._client.destroy();
1766
- this.logger.info(chalk6.bold.red("Logged out of Discord!"));
1125
+ this.logger.info(chalk2.bold.red("Logged out of Discord!"));
1767
1126
  }
1768
1127
  get client() {
1769
1128
  return this._client;
1770
1129
  }
1771
1130
  };
1131
+ _ts_decorate3([
1132
+ Envapt("DISCORD_BOT_TOKEN", {
1133
+ converter(raw, _fallback) {
1134
+ if (typeof raw !== "string") throw new Error("Missing DISCORD_BOT_TOKEN");
1135
+ return raw;
1136
+ }
1137
+ }),
1138
+ _ts_metadata3("design:type", String)
1139
+ ], Bot.prototype, "botToken", void 0);
1772
1140
 
1773
1141
  // src/effects/decorators/RegisterEffect.ts
1774
1142
  var EffectMetadataKey = Symbol("effect:metadata");
@@ -1811,19 +1179,23 @@ var WebhookLog = class extends EffectsHandler {
1811
1179
  };
1812
1180
 
1813
1181
  // src/effects/default/UnknownException.ts
1814
- function _ts_decorate3(decorators, target, key, desc) {
1182
+ function _ts_decorate4(decorators, target, key, desc) {
1815
1183
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1816
1184
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1817
1185
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1818
1186
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1819
1187
  }
1820
- __name(_ts_decorate3, "_ts_decorate");
1821
- var UnknownException = class extends WebhookLog {
1188
+ __name(_ts_decorate4, "_ts_decorate");
1189
+ function _ts_metadata4(k, v) {
1190
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1191
+ }
1192
+ __name(_ts_metadata4, "_ts_metadata");
1193
+ var UnknownException = class _UnknownException extends WebhookLog {
1822
1194
  static {
1823
1195
  __name(this, "UnknownException");
1824
1196
  }
1825
1197
  webhook = new WebhookClient({
1826
- url: Globals.unknownExceptionWebhookUrl
1198
+ url: _UnknownException.unknownExceptionWebhookUrl
1827
1199
  });
1828
1200
  async execute() {
1829
1201
  await this.webhook.send({
@@ -1835,7 +1207,16 @@ var UnknownException = class extends WebhookLog {
1835
1207
  });
1836
1208
  }
1837
1209
  };
1838
- UnknownException = _ts_decorate3([
1210
+ _ts_decorate4([
1211
+ Envapt("UNKNOWN_EXCEPTION_WEBHOOK_URL", {
1212
+ converter(raw, _fallback) {
1213
+ if (!raw) throw new Error("Missing UNKNOWN_EXCEPTION_WEBHOOK_URL");
1214
+ return raw;
1215
+ }
1216
+ }),
1217
+ _ts_metadata4("design:type", String)
1218
+ ], UnknownException, "unknownExceptionWebhookUrl", void 0);
1219
+ UnknownException = _ts_decorate4([
1839
1220
  RegisterEffect("unknownException")
1840
1221
  ], UnknownException);
1841
1222
  var UnhandledErrorEmbed = class UnhandledErrorEmbed2 extends BuilderComponent {
@@ -1932,12 +1313,12 @@ var EffectsRegistry = class extends Plugin {
1932
1313
  if (this.isInitialized) return;
1933
1314
  this.isInitialized = true;
1934
1315
  const effectsDir = this.core.config.effects.path;
1935
- this.logger.info(chalk6.bold(effectsDir));
1316
+ this.logger.info(chalk2.bold(effectsDir));
1936
1317
  this.registerEffect("unknownException", UnknownException);
1937
1318
  await this.loadEffects(effectsDir);
1938
1319
  this.attachEffects();
1939
1320
  const totalEffects = Array.from(this.effectsMap.values()).reduce((acc, handlers) => acc + handlers.length, 0);
1940
- this.logger.info(`${chalk6.bold.green("Loaded")}: ${chalk6.bold.magenta(totalEffects)} side effects`);
1321
+ this.logger.info(`${chalk2.bold.green("Loaded")}: ${chalk2.bold.magenta(totalEffects)} side effects`);
1941
1322
  }
1942
1323
  async loadEffects(dir) {
1943
1324
  await traverseDirectory(dir, (_fullPath, relativePath, imported) => {
@@ -1947,11 +1328,11 @@ var EffectsRegistry = class extends Plugin {
1947
1328
  const effectName = Reflect.getMetadata(EffectMetadataKey, val);
1948
1329
  if (effectName) {
1949
1330
  this.registerEffect(effectName, val);
1950
- this.logger.info(`${chalk6.italic("Registered")} ${chalk6.bold.yellow(val.name)} from ${chalk6.gray(relativePath)}`);
1331
+ this.logger.info(`${chalk2.italic("Registered")} ${chalk2.bold.yellow(val.name)} from ${chalk2.gray(relativePath)}`);
1951
1332
  }
1952
1333
  }
1953
1334
  }
1954
- });
1335
+ }, this.logger);
1955
1336
  }
1956
1337
  registerEffect(effectName, handler) {
1957
1338
  let handlers = this.effectsMap.get(effectName);
@@ -1983,206 +1364,6 @@ var EffectsRegistry = class extends Plugin {
1983
1364
  return this.emitter.emit(event, data);
1984
1365
  }
1985
1366
  };
1986
- var HTTP_OK = 200;
1987
- var HTTP_NOT_FOUND = 404;
1988
- var HealthCheck = class extends Plugin {
1989
- static {
1990
- __name(this, "HealthCheck");
1991
- }
1992
- core;
1993
- logger = new Logger("HealthCheck");
1994
- port = Globals.healthCheckPort;
1995
- path = Globals.healthCheckPath;
1996
- server;
1997
- constructor(core) {
1998
- super(core), this.core = core;
1999
- this.core.shutdown.addTask(ShutdownPhase.StopServices, "stop-healthcheck-server", async () => await this.stop());
2000
- }
2001
- /**
2002
- * Starts the health check server.
2003
- * @returns Promise that resolves when the server is listening
2004
- */
2005
- async init() {
2006
- return new Promise((resolve, reject) => {
2007
- this.server = createServer((req, res) => {
2008
- if (req.method === "GET" && req.url === this.path) {
2009
- res.writeHead(HTTP_OK, {
2010
- "Content-Type": "application/json"
2011
- });
2012
- res.end(JSON.stringify({
2013
- status: "ok",
2014
- timestamp: Date.now()
2015
- }));
2016
- } else {
2017
- res.writeHead(HTTP_NOT_FOUND, {
2018
- "Content-Type": "application/json"
2019
- });
2020
- res.end(JSON.stringify({
2021
- status: "not found"
2022
- }));
2023
- }
2024
- });
2025
- this.server.on("error", reject);
2026
- this.server.listen(this.port, () => {
2027
- this.logger.info(`${chalk6.green.bold("\u2713")} Health check server listening on ${chalk6.cyan(`http://localhost:${this.port}${this.path}`)}`);
2028
- resolve();
2029
- });
2030
- });
2031
- }
2032
- /**
2033
- * Stops the health check server.
2034
- *
2035
- * @returns Promise that resolves when the server is closed
2036
- */
2037
- stop() {
2038
- return new Promise((shutdownResolve) => {
2039
- this.server?.close(() => {
2040
- this.logger.info(chalk6.bold.red("Health check server stopped"));
2041
- shutdownResolve();
2042
- });
2043
- });
2044
- }
2045
- };
2046
- var StartupPhase = /* @__PURE__ */ (function(StartupPhase2) {
2047
- StartupPhase2[StartupPhase2["Validation"] = 1] = "Validation";
2048
- StartupPhase2[StartupPhase2["Discovery"] = 2] = "Discovery";
2049
- StartupPhase2[StartupPhase2["Registration"] = 3] = "Registration";
2050
- StartupPhase2[StartupPhase2["Configuration"] = 4] = "Configuration";
2051
- StartupPhase2[StartupPhase2["Instantiation"] = 5] = "Instantiation";
2052
- StartupPhase2[StartupPhase2["Activation"] = 6] = "Activation";
2053
- StartupPhase2[StartupPhase2["Ready"] = 7] = "Ready";
2054
- return StartupPhase2;
2055
- })({});
2056
- var PHASE_ORDER2 = [
2057
- 1,
2058
- 2,
2059
- 3,
2060
- 4,
2061
- 5,
2062
- 6,
2063
- 7
2064
- ];
2065
- var CoordinatedStartup = class extends CoordinatedLifecycle {
2066
- static {
2067
- __name(this, "CoordinatedStartup");
2068
- }
2069
- isStartingUp = false;
2070
- hasStarted = false;
2071
- constructor() {
2072
- super("CoordinatedStartup", PHASE_ORDER2, StartupPhase);
2073
- }
2074
- /**
2075
- * Adds a task to a specific startup phase with timeout.
2076
- *
2077
- * @param phase - The startup phase from {@link StartupPhase}
2078
- * @param taskName - Unique identifier for the task
2079
- * @param task - Async function to execute
2080
- * @param timeoutMs - Task timeout in milliseconds (default: 10000)
2081
- */
2082
- addTask(phase, taskName, task, timeoutMs = 1e4) {
2083
- super.addTask(phase, taskName, task, timeoutMs);
2084
- }
2085
- canAddTask() {
2086
- if (this.hasStarted) {
2087
- throw new Error("Cannot add tasks after startup sequence has already completed");
2088
- }
2089
- if (this.isStartingUp) {
2090
- throw new Error("Cannot add tasks while startup sequence is in progress");
2091
- }
2092
- return true;
2093
- }
2094
- canRemoveTask() {
2095
- if (this.isStartingUp) {
2096
- throw new Error("Cannot remove tasks while startup sequence is in progress");
2097
- }
2098
- return true;
2099
- }
2100
- getTaskType() {
2101
- return "startup";
2102
- }
2103
- async executeTasksInPhase(phase, tasks) {
2104
- const results = [];
2105
- for (const task of tasks) {
2106
- results.push(await Promise.resolve().then(() => this.runTaskWithTimeout(phase, task)).then(
2107
- () => ({
2108
- status: "fulfilled",
2109
- value: void 0
2110
- }),
2111
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
2112
- (reason) => ({
2113
- status: "rejected",
2114
- reason
2115
- })
2116
- ));
2117
- }
2118
- return results;
2119
- }
2120
- /**
2121
- * Executes the coordinated startup sequence.
2122
- *
2123
- * Runs all registered tasks across startup phases in the correct order.
2124
- * Each phase completes before the next phase begins. Tasks within a phase
2125
- * are executed sequentially to maintain predictable initialization.
2126
- *
2127
- * @returns Promise that resolves when startup is complete
2128
- * @throws An {@link Error} If startup fails or is called multiple times
2129
- * @example
2130
- * ```typescript
2131
- * const startup = new CoordinatedStartup();
2132
- * startup.addTask(StartupPhase.Services, 'database', () => db.connect(), 10000);
2133
- * await startup.run();
2134
- * ```
2135
- */
2136
- async run() {
2137
- if (this.hasStarted) {
2138
- this.logger.warn("Startup sequence has already completed");
2139
- return;
2140
- }
2141
- if (this.isStartingUp) {
2142
- this.logger.warn("Startup sequence already in progress");
2143
- return;
2144
- }
2145
- this.isStartingUp = true;
2146
- this.logger.info(`${chalk6.bold.green("Starting")} coordinated startup sequence`);
2147
- this.emit("startup:start");
2148
- try {
2149
- for (const phase of PHASE_ORDER2) await this.runPhase(phase);
2150
- this.hasStarted = true;
2151
- this.logger.info(`${chalk6.bold.green("Coordinated startup completed")} successfully`);
2152
- this.emit("startup:complete");
2153
- } catch (error) {
2154
- this.logger.error(`${chalk6.bold.red("Coordinated startup failed")}`);
2155
- this.emit("startup:error", error);
2156
- throw error;
2157
- } finally {
2158
- this.isStartingUp = false;
2159
- }
2160
- }
2161
- /**
2162
- * Subscribe to startup events
2163
- */
2164
- on(event, listener) {
2165
- super.on(event, listener);
2166
- }
2167
- /**
2168
- * Unsubscribe from startup events
2169
- */
2170
- off(event, listener) {
2171
- super.off(event, listener);
2172
- }
2173
- /**
2174
- * Check if startup has completed
2175
- */
2176
- get isReady() {
2177
- return this.hasStarted;
2178
- }
2179
- /**
2180
- * Check if startup is currently running
2181
- */
2182
- get isRunning() {
2183
- return this.isStartingUp;
2184
- }
2185
- };
2186
1367
 
2187
1368
  // src/Seedcord.ts
2188
1369
  var Seedcord = class _Seedcord extends Pluggable {
@@ -2219,7 +1400,7 @@ var Seedcord = class _Seedcord extends Pluggable {
2219
1400
  _Seedcord.isInstantiated = true;
2220
1401
  this.effects = new EffectsRegistry(this);
2221
1402
  this.bot = new Bot(this);
2222
- this.healthCheck = new HealthCheck(this);
1403
+ this.healthCheck = new HealthCheck(this.shutdown);
2223
1404
  this.registerStartupTasks();
2224
1405
  }
2225
1406
  /**
@@ -2228,19 +1409,19 @@ var Seedcord = class _Seedcord extends Pluggable {
2228
1409
  */
2229
1410
  registerStartupTasks() {
2230
1411
  this.startup.addTask(StartupPhase.Configuration, "Effect Initialization", async () => {
2231
- this.effects.logger.info(chalk6.bold("Initializing"));
1412
+ this.effects.logger.info(chalk2.bold("Initializing"));
2232
1413
  await this.effects.init();
2233
- this.effects.logger.info(chalk6.bold("Initialized"));
1414
+ this.effects.logger.info(chalk2.bold("Initialized"));
2234
1415
  });
2235
1416
  this.startup.addTask(StartupPhase.Instantiation, "Bot Initialization", async () => {
2236
- this.bot.logger.info(chalk6.bold("Initializing"));
1417
+ this.bot.logger.info(chalk2.bold("Initializing"));
2237
1418
  await this.bot.init();
2238
- this.bot.logger.info(chalk6.bold("Initialized"));
1419
+ this.bot.logger.info(chalk2.bold("Initialized"));
2239
1420
  });
2240
1421
  this.startup.addTask(StartupPhase.Ready, "Health Check", async () => {
2241
- this.healthCheck.logger.info(chalk6.bold("Initializing"));
1422
+ this.healthCheck.logger.info(chalk2.bold("Initializing"));
2242
1423
  await this.healthCheck.init();
2243
- this.healthCheck.logger.info(chalk6.bold("Initialized"));
1424
+ this.healthCheck.logger.info(chalk2.bold("Initialized"));
2244
1425
  });
2245
1426
  }
2246
1427
  /**
@@ -2290,75 +1471,22 @@ function EventCatchable(log) {
2290
1471
  };
2291
1472
  }
2292
1473
  __name(EventCatchable, "EventCatchable");
2293
-
2294
- // src/services/CooldownManager.ts
2295
- var CooldownManager = class {
2296
- static {
2297
- __name(this, "CooldownManager");
2298
- }
2299
- window;
2300
- Err;
2301
- msg;
2302
- map = /* @__PURE__ */ new Map();
2303
- /**
2304
- * Creates a new CooldownManager instance.
2305
- *
2306
- * @param opts - Configuration options for the cooldown behavior
2307
- */
2308
- constructor(opts = {}) {
2309
- this.window = opts.cooldown ?? 1e3;
2310
- this.Err = opts.err ?? Error;
2311
- this.msg = opts.message ?? "Cooldown active";
2312
- }
2313
- /**
2314
- * Records usage timestamp for a key without any cooldown checks.
2315
- *
2316
- * @param key - The unique identifier for the cooldown entry
2317
- */
2318
- set(key) {
2319
- this.map.set(key, Date.now());
2320
- }
2321
- /**
2322
- * Verifies cooldown status for a key and updates timestamp if not active.
2323
- *
2324
- * If the cooldown is still active, throws the configured error.
2325
- * If not active, updates the timestamp and returns successfully.
2326
- *
2327
- * @param key - The unique identifier to check cooldown for
2328
- * @throws An {@link Err} When the cooldown is still active for the given key
2329
- */
2330
- check(key) {
2331
- const now = Date.now();
2332
- const last = this.map.get(key);
2333
- const remaining = this.window - (now - (last ?? 0));
2334
- if (Globals.isDevelopment && remaining > 0) {
2335
- Logger.Debug("CooldownManager", `${key} - ${remaining}ms remaining`);
2336
- }
2337
- if (last !== void 0 && remaining > 0) {
2338
- throw new this.Err(this.msg, remaining);
1474
+ function throwCustomError(error, message, CustomError2) {
1475
+ const uuid = crypto.randomUUID();
1476
+ Logger.Error("Throwing Custom Error", error.name);
1477
+ if (typeof CustomError2 === typeof DatabaseError) {
1478
+ const errorMessage = error instanceof Error ? error.message : message;
1479
+ throw new CustomError2(errorMessage, uuid);
1480
+ } else {
1481
+ if (error instanceof Error) {
1482
+ throw new CustomError2(`${message}: ${error.message ? error.message : error.toString()}`);
1483
+ } else {
1484
+ throw new CustomError2(message);
2339
1485
  }
2340
- this.map.set(key, now);
2341
- }
2342
- /**
2343
- * Checks if a key is currently cooling down without updating timestamp.
2344
- *
2345
- * @param key - The unique identifier to check
2346
- * @returns True if the key is still cooling down, false otherwise
2347
- */
2348
- isActive(key) {
2349
- const last = this.map.get(key);
2350
- return last !== void 0 && Date.now() - last < this.window;
2351
1486
  }
2352
- /**
2353
- * Removes a key from the cooldown map.
2354
- *
2355
- * @param key - The unique identifier to remove (useful for manual resets)
2356
- */
2357
- clear(key) {
2358
- this.map.delete(key);
2359
- }
2360
- };
1487
+ }
1488
+ __name(throwCustomError, "throwCustomError");
2361
1489
 
2362
- export { AutocompleteHandler, AutocompleteRoute, BaseErrorEmbed, Bot, BuilderComponent, ButtonRoute, Catchable, Checkable, CommandMetadataKey, ContextMenuRoute, CooldownManager, CoordinatedShutdown, CoordinatedStartup, CustomError, DatabaseError, EffectMetadataKey, EffectsEmitter, EffectsHandler, EffectsRegistry, EventCatchable, EventHandler, EventMetadataKey, Globals, HealthCheck, InteractionHandler, InteractionMetadataKey, InteractionMiddleware, InteractionRoutes, Logger, ModalComponent, ModalRoute, Pluggable, Plugin, RegisterCommand, RegisterEffect, RegisterEvent, RowComponent, Seedcord, SelectMenuRoute, SelectMenuType, ShutdownPhase, SlashRoute, StartupPhase, WebhookLog, currentTime, formatWord, fyShuffle, generateAsciiTable, isTsOrJsFile, longestStringLength, numberFixer, ordinal, percentage, prettify, prettyDifference, throwCustomError, traverseDirectory };
1490
+ export { AutocompleteHandler, AutocompleteRoute, BaseErrorEmbed, Bot, BuilderComponent, ButtonRoute, Catchable, Checkable, CommandMetadataKey, ContextMenuRoute, CustomError, DatabaseError, EffectMetadataKey, EffectsEmitter, EffectsHandler, EffectsRegistry, EventCatchable, EventHandler, EventMetadataKey, InteractionHandler, InteractionMetadataKey, InteractionMiddleware, InteractionRoutes, ModalComponent, ModalRoute, Pluggable, Plugin, RegisterCommand, RegisterEffect, RegisterEvent, RowComponent, Seedcord, SelectMenuRoute, SelectMenuType, SlashRoute, WebhookLog, throwCustomError };
2363
1491
  //# sourceMappingURL=index.mjs.map
2364
1492
  //# sourceMappingURL=index.mjs.map