seedcord 0.4.3 → 0.5.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.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require('reflect-metadata');
4
4
  var services = require('@seedcord/services');
5
- var chalk2 = require('chalk');
5
+ var chalk4 = require('chalk');
6
6
  var discord_js = require('discord.js');
7
7
  var envapt = require('envapt');
8
8
  var utils = require('@seedcord/utils');
@@ -29,7 +29,7 @@ function _interopNamespace(e) {
29
29
  return Object.freeze(n);
30
30
  }
31
31
 
32
- var chalk2__default = /*#__PURE__*/_interopDefault(chalk2);
32
+ var chalk4__default = /*#__PURE__*/_interopDefault(chalk4);
33
33
  var crypto2__namespace = /*#__PURE__*/_interopNamespace(crypto2);
34
34
 
35
35
  var __defProp = Object.defineProperty;
@@ -62,26 +62,26 @@ var Pluggable = class _Pluggable {
62
62
  return this;
63
63
  }
64
64
  /**
65
- * Attaches a plugin to this instance
66
- *
67
- * Plugins provide external functionality and are initialized during the specified startup phase.
68
- * The plugin instance becomes available as a property in `core` wherever it's available.
69
- *
70
- * Make sure to augment the {@link Core} interface with the plugin type to ensure TypeScript recognizes it and provides intellisense.
71
- *
72
- * @typeParam Key - The property name for accessing the plugin
73
- * @typeParam Ctor - The plugin constructor type
74
- * @param key - Property name to access the plugin instance
75
- * @param Plugin - Plugin constructor class
76
- * @param startupPhase - When during startup to initialize this plugin ({@link StartupPhase})
77
- * @param args - Additional arguments to pass to the plugin constructor
78
- * @returns This instance with the plugin attached as a typed property
79
- * @throws An {@link Error} When called after initialization or if key already exists
80
- * @example
81
- * ```typescript
82
- * seedcord.attach('db', Mongo, StartupPhase.Configuration, { uri: 'mongodb://...', name: 'seedcord', dir: ... })
83
- * ```
84
- */
65
+ * Attaches a plugin to this instance
66
+ *
67
+ * Plugins provide external functionality and are initialized during the specified startup phase.
68
+ * The plugin instance becomes available as a property in `core` wherever it's available.
69
+ *
70
+ * Make sure to augment the {@link Core} interface with the plugin type to ensure TypeScript recognizes it and provides intellisense.
71
+ *
72
+ * @typeParam Key - The property name for accessing the plugin
73
+ * @typeParam Ctor - The plugin constructor type
74
+ * @param key - Property name to access the plugin instance
75
+ * @param Plugin - Plugin constructor class
76
+ * @param startupPhase - When during startup to initialize this plugin ({@link StartupPhase})
77
+ * @param args - Additional arguments to pass to the plugin constructor
78
+ * @returns This instance with the plugin attached as a typed property
79
+ * @throws An {@link Error} When called after initialization or if key already exists
80
+ * @example
81
+ * ```typescript
82
+ * seedcord.attach('db', Mongo, StartupPhase.Configuration, { uri: 'mongodb://...', name: 'seedcord', dir: ... })
83
+ * ```
84
+ */
85
85
  attach(key, Plugin2, startupPhase, ...args) {
86
86
  if (this.isInitialized) throw new Error("Cannot attach a plugin after initialization.");
87
87
  if (this[key]) throw new Error(`Plugin with key "${key}" already exists.`);
@@ -90,13 +90,27 @@ var Pluggable = class _Pluggable {
90
90
  [key]: instance
91
91
  };
92
92
  this.startup.addTask(startupPhase, `Plugin:${key}`, async () => {
93
- instance.logger.info(chalk2__default.default.bold("Initializing"));
93
+ instance.logger.info(chalk4__default.default.bold("Initializing"));
94
94
  await instance.init();
95
- instance.logger.info(chalk2__default.default.bold("Initialized"));
95
+ instance.logger.info(chalk4__default.default.bold("Initialized"));
96
96
  }, _Pluggable.PLUGIN_INIT_TIMEOUT_MS);
97
97
  return Object.assign(this, entry);
98
98
  }
99
99
  };
100
+ function parseEnvColor(raw, fallback) {
101
+ if (!raw) return fallback;
102
+ const toHex = /* @__PURE__ */ __name((n) => `#${n.toString(16).padStart(6, "0")}`, "toHex");
103
+ const num = Number(raw);
104
+ if (!Number.isNaN(num) && num >= 0) return toHex(num);
105
+ if (raw.startsWith("#")) return raw;
106
+ if (/^[0-9A-Fa-f]{6}$/.test(raw)) return `#${raw}`;
107
+ const colorKey = Object.keys(discord_js.Colors).find((key) => key.toLowerCase() === raw.toLowerCase());
108
+ if (colorKey) return toHex(discord_js.Colors[colorKey]);
109
+ return fallback;
110
+ }
111
+ __name(parseEnvColor, "parseEnvColor");
112
+
113
+ // src/interfaces/Components.ts
100
114
  function _ts_decorate(decorators, target, key, desc) {
101
115
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
102
116
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -109,8 +123,18 @@ function _ts_metadata(k, v) {
109
123
  }
110
124
  __name(_ts_metadata, "_ts_metadata");
111
125
  var BuilderTypes = {
126
+ // Command Components
112
127
  command: discord_js.SlashCommandBuilder,
128
+ context_menu: discord_js.ContextMenuCommandBuilder,
129
+ subcommand: discord_js.SlashCommandSubcommandBuilder,
130
+ group: discord_js.SlashCommandSubcommandGroupBuilder,
131
+ // Embed Components
113
132
  embed: discord_js.EmbedBuilder,
133
+ // Modal Components
134
+ modal: discord_js.ModalBuilder,
135
+ label: discord_js.LabelBuilder,
136
+ text_input: discord_js.TextInputBuilder,
137
+ // Action Row Components
114
138
  button: discord_js.ButtonBuilder,
115
139
  menu_string: discord_js.StringSelectMenuBuilder,
116
140
  menu_option_string: discord_js.StringSelectMenuOptionBuilder,
@@ -118,10 +142,7 @@ var BuilderTypes = {
118
142
  menu_channel: discord_js.ChannelSelectMenuBuilder,
119
143
  menu_mentionable: discord_js.MentionableSelectMenuBuilder,
120
144
  menu_role: discord_js.RoleSelectMenuBuilder,
121
- modal: discord_js.ModalBuilder,
122
- context_menu: discord_js.ContextMenuCommandBuilder,
123
- subcommand: discord_js.SlashCommandSubcommandBuilder,
124
- group: discord_js.SlashCommandSubcommandGroupBuilder,
145
+ // ComponentsV2
125
146
  container: discord_js.ContainerBuilder,
126
147
  text_display: discord_js.TextDisplayBuilder,
127
148
  file: discord_js.FileBuilder,
@@ -135,13 +156,9 @@ var RowTypes = {
135
156
  menu_user: discord_js.ActionRowBuilder,
136
157
  menu_channel: discord_js.ActionRowBuilder,
137
158
  menu_mentionable: discord_js.ActionRowBuilder,
138
- menu_role: discord_js.ActionRowBuilder,
139
- modal: discord_js.ActionRowBuilder
140
- };
141
- var ModalTypes = {
142
- text: discord_js.TextInputBuilder
159
+ menu_role: discord_js.ActionRowBuilder
143
160
  };
144
- var BaseComponent = class BaseComponent2 {
161
+ var BaseComponent = class {
145
162
  static {
146
163
  __name(this, "BaseComponent");
147
164
  }
@@ -151,26 +168,26 @@ var BaseComponent = class BaseComponent2 {
151
168
  this._component = new ComponentClass();
152
169
  }
153
170
  /**
154
- * Gets the component instance for configuration
155
- *
156
- * Use this to access Discord.js builder methods like setTitle(), setDescription(), etc.
157
- *
158
- * Use this in your component classes to configure the builder
159
- * @example this.instance.setTitle('My Modal')
160
- */
171
+ * Gets the component instance for configuration
172
+ *
173
+ * Use this to access Discord.js builder methods like setTitle(), setDescription(), etc.
174
+ *
175
+ * Use this in your component classes to configure the builder
176
+ * @example this.instance.setTitle('My Modal')
177
+ */
161
178
  get instance() {
162
179
  return this._component;
163
180
  }
164
181
  /**
165
- * Builds a customId string for interactive components
166
- *
167
- * Creates customIds in the format "prefix:arg1-arg2-arg3" for buttons, modals, etc.
168
- * Arguments are joined with hyphens and separated from prefix with a colon.
169
- *
170
- * @param prefix - The route prefix that handlers will match against
171
- * @param args - Additional arguments to encode in the customId
172
- * @returns Formatted customId string
173
- */
182
+ * Builds a customId string for interactive components
183
+ *
184
+ * Creates customIds in the format `prefix:arg1-arg2-arg3` for buttons, modals, etc.
185
+ * Arguments are joined with hyphens and separated from prefix with a colon.
186
+ *
187
+ * @param prefix - The route prefix that handlers will match against
188
+ * @param args - Additional arguments to encode in the customId
189
+ * @returns Formatted customId string
190
+ */
174
191
  buildCustomId(prefix, ...args) {
175
192
  if (args.length === 0) return prefix;
176
193
  return `${prefix}:${args.join("-")}`;
@@ -184,6 +201,9 @@ var BuilderComponent = class extends BaseComponent {
184
201
  const ComponentClass = BuilderTypes[type];
185
202
  super(ComponentClass);
186
203
  if (this.instance instanceof discord_js.EmbedBuilder) this.instance.setColor(this.botColor);
204
+ if (this.instance instanceof discord_js.ContainerBuilder) {
205
+ this.instance.setAccentColor(this.botColor === "Default" ? void 0 : utils.hexToNumber(this.botColor.toString()));
206
+ }
187
207
  if (this.instance instanceof discord_js.SlashCommandBuilder || this.instance instanceof discord_js.ContextMenuCommandBuilder) {
188
208
  this.instance.setContexts(discord_js.InteractionContextType.Guild);
189
209
  }
@@ -194,7 +214,8 @@ var BuilderComponent = class extends BaseComponent {
194
214
  };
195
215
  _ts_decorate([
196
216
  envapt.Envapt("DEFAULT_BOT_COLOR", {
197
- fallback: "Default"
217
+ fallback: "Default",
218
+ converter: /* @__PURE__ */ __name((raw, fallback) => parseEnvColor(raw, fallback), "converter")
198
219
  }),
199
220
  _ts_metadata("design:type", typeof ColorResolvable === "undefined" ? Object : ColorResolvable)
200
221
  ], BuilderComponent.prototype, "botColor", void 0);
@@ -210,39 +231,13 @@ var RowComponent = class extends BaseComponent {
210
231
  return this.instance;
211
232
  }
212
233
  };
213
- var ModalRow = class ModalRow2 extends RowComponent {
214
- static {
215
- __name(this, "ModalRow");
216
- }
217
- /**
218
- * Creates a new modal action row with the specified component.
219
- *
220
- * @param component - The modal field component to wrap in an action row
221
- */
222
- constructor(component) {
223
- super("modal");
224
- this.instance.addComponents(component);
225
- }
226
- };
227
- var ModalComponent = class extends BaseComponent {
228
- static {
229
- __name(this, "ModalComponent");
230
- }
231
- constructor(type) {
232
- const ComponentClass = ModalTypes[type];
233
- super(ComponentClass);
234
- }
235
- get component() {
236
- return new ModalRow(this.instance).component;
237
- }
238
- };
239
234
  var BaseErrorEmbed = class extends BuilderComponent {
240
235
  static {
241
236
  __name(this, "BaseErrorEmbed");
242
237
  }
243
238
  /**
244
- * Creates a new error embed with default configuration.
245
- */
239
+ * Creates a new error embed with default configuration.
240
+ */
246
241
  constructor() {
247
242
  super("embed");
248
243
  this.instance.setTitle("Cannot Proceed");
@@ -260,27 +255,25 @@ var CustomError = class extends Error {
260
255
  Error.captureStackTrace(this, this.constructor);
261
256
  }
262
257
  /**
263
- * Whether this error should be emitted to logs
264
- *
265
- * Controls logging behavior. Errors with emit=true will always be logged,
266
- * while emit=false errors may be suppressed in production.
267
- *
268
- * @returns True if the error should be logged
269
- */
258
+ * Whether this error should be emitted to logs
259
+ *
260
+ * Controls logging behavior. Errors with emit=true will always be logged,
261
+ * while emit=false errors may be suppressed in production.
262
+ *
263
+ * @returns True if the error should be logged
264
+ */
270
265
  get emit() {
271
266
  return this._emit;
272
267
  }
273
268
  /**
274
- * Sets whether this error should be emitted to logs
275
- *
276
- * @see {@link emit}
277
- */
269
+ * Sets whether this error should be emitted to logs
270
+ */
278
271
  set emit(value) {
279
272
  this._emit = value;
280
273
  }
281
274
  };
282
275
 
283
- // src/bot/decorators/CommandRegisterable.ts
276
+ // src/bot/decorators/Command.ts
284
277
  var CommandMetadataKey = Symbol("command:metadata");
285
278
  function RegisterCommand(scope, guilds = []) {
286
279
  return (ctor) => {
@@ -311,9 +304,9 @@ var CommandRegistry = class {
311
304
  async init() {
312
305
  if (this.isInitialised) return;
313
306
  this.isInitialised = true;
314
- this.logger.info(chalk2__default.default.bold(this.core.config.bot.commands.path));
307
+ this.logger.info(chalk4__default.default.bold(this.core.config.bot.commands.path));
315
308
  await this.loadCommands(this.core.config.bot.commands.path);
316
- this.logger.info(`${chalk2__default.default.bold.green("Loaded")}: ${chalk2__default.default.magenta.bold(this.globalCommands.length)} global, ${chalk2__default.default.magenta.bold(this.guildCommands.size)} guild groups`);
309
+ this.logger.info(`${chalk4__default.default.bold.green("Loaded")}: ${chalk4__default.default.magenta.bold(this.globalCommands.length)} global, ${chalk4__default.default.magenta.bold(this.guildCommands.size)} guild groups`);
317
310
  }
318
311
  async loadCommands(dir) {
319
312
  await utils.traverseDirectory(dir, (_full, rel, mod) => {
@@ -332,24 +325,24 @@ var CommandRegistry = class {
332
325
  const commandType = comp instanceof discord_js.SlashCommandBuilder ? "slash command" : "context menu command";
333
326
  if (meta.scope === "global") {
334
327
  this.globalCommands.push(comp);
335
- this.logger.info(`${chalk2__default.default.italic("Registered")} ${chalk2__default.default.bold.yellow(ctor.name)} from ${chalk2__default.default.gray(rel)}`);
336
- this.logger.info(` \u2192 Global ${commandType}: ${chalk2__default.default.bold.cyan(comp.name)}`);
328
+ this.logger.info(`${chalk4__default.default.italic("Registered")} ${chalk4__default.default.bold.yellow(ctor.name)} from ${chalk4__default.default.gray(rel)}`);
329
+ this.logger.info(` \u2192 Global ${commandType}: ${chalk4__default.default.bold.cyan(comp.name)}`);
337
330
  } else {
338
331
  for (const g of meta.guilds) {
339
332
  const arr = this.guildCommands.get(g) ?? [];
340
333
  arr.push(comp);
341
334
  this.guildCommands.set(g, arr);
342
335
  }
343
- this.logger.info(`${chalk2__default.default.italic("Registered")} ${chalk2__default.default.bold.yellow(ctor.name)} from ${chalk2__default.default.gray(rel)}`);
344
- this.logger.info(` \u2192 Guild ${commandType}: ${chalk2__default.default.bold.cyan(comp.name)} for ${chalk2__default.default.magenta.bold(meta.guilds.length)} guild(s)`);
336
+ this.logger.info(`${chalk4__default.default.italic("Registered")} ${chalk4__default.default.bold.yellow(ctor.name)} from ${chalk4__default.default.gray(rel)}`);
337
+ this.logger.info(` \u2192 Guild ${commandType}: ${chalk4__default.default.bold.cyan(comp.name)} for ${chalk4__default.default.magenta.bold(meta.guilds.length)} guild(s)`);
345
338
  }
346
339
  }
347
340
  async setCommands() {
348
341
  if (this.globalCommands.length > 0) {
349
342
  await this.core.bot.client.application?.commands.set(this.globalCommands);
350
343
  const tag = this.globalCommands.length === 1 ? "command" : "commands";
351
- this.logger.info(`${chalk2__default.default.bold.green("Configured")} ${chalk2__default.default.magenta.bold(this.globalCommands.length)} global ${tag}`);
352
- this.logger.info(` \u2192 ${this.globalCommands.map((command) => chalk2__default.default.bold.cyan(command.name)).join(", ")}`);
344
+ this.logger.info(`${chalk4__default.default.bold.green("Configured")} ${chalk4__default.default.magenta.bold(this.globalCommands.length)} global ${tag}`);
345
+ this.logger.info(` \u2192 ${this.globalCommands.map((command) => chalk4__default.default.bold.cyan(command.name)).join(", ")}`);
353
346
  }
354
347
  for (const [guildId, commands] of this.guildCommands.entries()) {
355
348
  const guild = this.core.bot.client.guilds.cache.get(guildId);
@@ -359,14 +352,14 @@ var CommandRegistry = class {
359
352
  }
360
353
  await guild.commands.set(commands);
361
354
  const tag = commands.length === 1 ? "command" : "commands";
362
- this.logger.info(`${chalk2__default.default.bold.green("Configured")} ${chalk2__default.default.magenta.bold(commands.length)} ${tag} for guild ${chalk2__default.default.bold.yellow(guild.name)}`);
363
- this.logger.info(` \u2192 ${commands.map((command) => chalk2__default.default.bold.cyan(command.name)).join(", ")}`);
355
+ this.logger.info(`${chalk4__default.default.bold.green("Configured")} ${chalk4__default.default.magenta.bold(commands.length)} ${tag} for guild ${chalk4__default.default.bold.yellow(guild.name)}`);
356
+ this.logger.info(` \u2192 ${commands.map((command) => chalk4__default.default.bold.cyan(command.name)).join(", ")}`);
364
357
  }
365
358
  }
366
359
  };
367
360
 
368
361
  // src/interfaces/Handler.ts
369
- var BaseHandler = class BaseHandler2 {
362
+ var BaseHandler = class {
370
363
  static {
371
364
  __name(this, "BaseHandler");
372
365
  }
@@ -397,19 +390,19 @@ var BaseHandler = class BaseHandler2 {
397
390
  return this.event;
398
391
  }
399
392
  /**
400
- * Gets arguments parsed from interaction customId
401
- *
402
- * Arguments are extracted from customId using ":" and "-" separators.
403
- * For customId "accept:user123-guild456", returns ["user123", "guild456"]
404
- */
393
+ * Gets arguments parsed from interaction customId
394
+ *
395
+ * Arguments are extracted from customId using `:` and `-` separators.
396
+ * For customId `accept:user123-guild456`, returns `["user123", "guild456"]`
397
+ */
405
398
  getArgs() {
406
399
  return this.args;
407
400
  }
408
401
  /**
409
- * Gets a specific argument by index from parsed customId
410
- * @param index - Zero-based index of the argument to retrieve
411
- * @returns The argument at the specified index, or undefined if not found
412
- */
402
+ * Gets a specific argument by index from parsed customId
403
+ * @param index - Zero-based index of the argument to retrieve
404
+ * @returns The argument at the specified index, or undefined if not found
405
+ */
413
406
  getArg(index) {
414
407
  return this.args[index];
415
408
  }
@@ -430,11 +423,19 @@ var InteractionMiddleware = class extends BaseHandler {
430
423
  super(event, core, args);
431
424
  }
432
425
  };
426
+ var EventMiddleware = class extends BaseHandler {
427
+ static {
428
+ __name(this, "EventMiddleware");
429
+ }
430
+ constructor(event, core, args) {
431
+ super(event, core, args);
432
+ }
433
+ };
433
434
  var AutocompleteHandler = class extends BaseHandler {
434
435
  static {
435
436
  __name(this, "AutocompleteHandler");
436
437
  }
437
- /** The currently focused autocomplete option (Based on what you set in \@AutocompleteRoute) */
438
+ /** The currently focused autocomplete option (Based on what you set in `@AutocompleteRoute`) */
438
439
  focused;
439
440
  constructor(event, core, args) {
440
441
  super(event, core, args);
@@ -450,15 +451,57 @@ var EventHandler = class extends BaseHandler {
450
451
  }
451
452
  };
452
453
 
453
- // src/bot/decorators/EventRegisterable.ts
454
+ // src/miscellaneous/areRoutes.ts
455
+ function areRoutes(routes) {
456
+ return Array.isArray(routes) && routes.every((r) => typeof r === "string");
457
+ }
458
+ __name(areRoutes, "areRoutes");
459
+
460
+ // src/bot/decorators/Events.ts
454
461
  var EventMetadataKey = Symbol("event:metadata");
455
- function RegisterEvent(eventName) {
462
+ function RegisterEvent(events) {
456
463
  return function(constructor) {
457
- Reflect.defineMetadata(EventMetadataKey, eventName, constructor);
464
+ const saved = Reflect.getMetadata(EventMetadataKey, constructor);
465
+ const existing = areRoutes(saved) ? saved : [];
466
+ const toStore = Array.isArray(events) ? events : [
467
+ events
468
+ ];
469
+ Reflect.defineMetadata(EventMetadataKey, [
470
+ ...existing,
471
+ ...toStore
472
+ ], constructor);
458
473
  };
459
474
  }
460
475
  __name(RegisterEvent, "RegisterEvent");
461
476
 
477
+ // src/bot/decorators/Middlewares.ts
478
+ var MiddlewareType = /* @__PURE__ */ (function(MiddlewareType2) {
479
+ MiddlewareType2["Interaction"] = "middleware:interaction";
480
+ MiddlewareType2["Event"] = "middleware:event";
481
+ return MiddlewareType2;
482
+ })({});
483
+ var MiddlewareMetadataKey = Symbol("middleware:metadata");
484
+ function Middleware(type, priority = 0, options = {}) {
485
+ return (ctor) => {
486
+ const normalizedPriority = Number(priority);
487
+ if (!Number.isFinite(normalizedPriority)) {
488
+ throw new TypeError("Middleware priority must be a finite number");
489
+ }
490
+ if (type === "middleware:interaction" && options.events?.length) {
491
+ throw new Error("Interaction middleware cannot specify event filters");
492
+ }
493
+ const metadata = {
494
+ priority: normalizedPriority,
495
+ type,
496
+ ...options.events ? {
497
+ events: options.events
498
+ } : {}
499
+ };
500
+ Reflect.defineMetadata(MiddlewareMetadataKey, metadata, ctor);
501
+ };
502
+ }
503
+ __name(Middleware, "Middleware");
504
+
462
505
  // src/bot/controllers/EventController.ts
463
506
  var EventController = class {
464
507
  static {
@@ -468,6 +511,7 @@ var EventController = class {
468
511
  logger = new services.Logger("Events");
469
512
  isInitialized = false;
470
513
  eventMap = new discord_js.Collection();
514
+ middlewares = [];
471
515
  constructor(core) {
472
516
  this.core = core;
473
517
  }
@@ -477,42 +521,96 @@ var EventController = class {
477
521
  }
478
522
  this.isInitialized = true;
479
523
  const handlersDir = this.core.config.bot.events.path;
480
- this.logger.info(chalk2__default.default.bold(handlersDir));
524
+ this.logger.info(chalk4__default.default.bold(handlersDir));
525
+ const middlewareDir = this.core.config.bot.events.middlewares;
526
+ if (middlewareDir) {
527
+ this.logger.info(`${chalk4__default.default.bold(middlewareDir)} ${chalk4__default.default.gray("(middlewares)")}`);
528
+ await this.loadMiddlewares(middlewareDir);
529
+ }
481
530
  await this.loadHandlers(handlersDir);
482
531
  this.attachToClient();
532
+ this.logger.info(`\u2192 ${chalk4__default.default.magenta.bold(this.middlewares.length)} middlewares`);
483
533
  const loadedEventsArray = [];
484
534
  this.eventMap.forEach((handlers, eventName) => {
485
- loadedEventsArray.push(`${chalk2__default.default.magenta.bold(handlers.length)} ${eventName}`);
535
+ loadedEventsArray.push(`${chalk4__default.default.magenta.bold(handlers.length)} ${eventName}`);
486
536
  });
487
- this.logger.info(`${chalk2__default.default.bold.green("Loaded")}: ${this.eventMap.size > 0 ? loadedEventsArray.join(", ") : "none"}`);
537
+ this.logger.info(`${chalk4__default.default.bold.green("Loaded")}: ${this.eventMap.size > 0 ? loadedEventsArray.join(", ") : "none"}`);
488
538
  }
489
539
  async loadHandlers(dir) {
490
540
  await utils.traverseDirectory(dir, (_fullPath, relativePath, imported) => {
491
541
  for (const val of Object.values(imported)) {
492
- if (this.isEventHandlerClass(val)) {
493
- this.registerHandler(val);
494
- this.logger.info(`${chalk2__default.default.italic("Registered")} ${chalk2__default.default.bold.yellow(val.name)} from ${chalk2__default.default.gray(relativePath)}`);
495
- }
542
+ if (!this.isEventHandlerClass(val)) continue;
543
+ this.registerHandler(val);
544
+ this.logger.info(`${chalk4__default.default.italic("Registered")} ${chalk4__default.default.bold.yellow(val.name)} from ${chalk4__default.default.gray(relativePath)}`);
545
+ }
546
+ }, this.logger);
547
+ }
548
+ async loadMiddlewares(dir) {
549
+ await utils.traverseDirectory(dir, (_fullPath, relativePath, imported) => {
550
+ for (const val of Object.values(imported)) {
551
+ if (!this.isMiddlewareClass(val)) continue;
552
+ const metadata = Reflect.getMetadata(MiddlewareMetadataKey, val);
553
+ if (metadata?.type !== MiddlewareType.Event) continue;
554
+ this.registerMiddleware(val, metadata, relativePath);
496
555
  }
497
556
  }, this.logger);
498
557
  }
558
+ registerMiddleware(middlewareCtor, metadata, relativePath) {
559
+ const alreadyRegistered = this.middlewares.some((entry) => entry.ctor === middlewareCtor);
560
+ if (alreadyRegistered) return;
561
+ this.middlewares.push({
562
+ ctor: middlewareCtor,
563
+ priority: metadata.priority,
564
+ ...metadata.events ? {
565
+ events: metadata.events
566
+ } : {}
567
+ });
568
+ this.middlewares.sort((a, b) => a.priority - b.priority);
569
+ this.logger.info(`${chalk4__default.default.italic("Registered event middleware")} ${chalk4__default.default.bold.yellow(middlewareCtor.name)} ${chalk4__default.default.gray(`(priority ${metadata.priority})`)} from ${chalk4__default.default.gray(relativePath)}`);
570
+ }
571
+ async runMiddlewares(eventName, args) {
572
+ for (const { ctor, events } of this.middlewares) {
573
+ if (events && !events.includes(eventName)) continue;
574
+ try {
575
+ const middleware = new ctor(args, this.core);
576
+ if (middleware.hasChecks()) await middleware.runChecks();
577
+ if (middleware.shouldBreak() || middleware.hasErrors()) return false;
578
+ await middleware.execute();
579
+ if (middleware.shouldBreak() || middleware.hasErrors()) return false;
580
+ } catch (err) {
581
+ this.logger.error(`Error in event middleware ${ctor.name} for event ${String(eventName)}:`, err);
582
+ return false;
583
+ }
584
+ }
585
+ return true;
586
+ }
499
587
  isEventHandlerClass(obj) {
500
588
  if (typeof obj !== "function") return false;
501
589
  return obj.prototype instanceof EventHandler && Reflect.hasMetadata(EventMetadataKey, obj);
502
590
  }
591
+ isMiddlewareClass(obj) {
592
+ if (typeof obj !== "function") return false;
593
+ return obj.prototype instanceof EventMiddleware && Reflect.hasMetadata(MiddlewareMetadataKey, obj);
594
+ }
503
595
  registerHandler(handlerClass) {
504
- const eventName = Reflect.getMetadata(EventMetadataKey, handlerClass);
505
- if (!eventName) return;
506
- let handlers = this.eventMap.get(eventName);
507
- if (!handlers) {
508
- handlers = [];
509
- this.eventMap.set(eventName, handlers);
596
+ const raw = Reflect.getMetadata(EventMetadataKey, handlerClass);
597
+ const names = areRoutes(raw) ? raw : typeof raw === "string" ? [
598
+ raw
599
+ ] : [];
600
+ if (names.length === 0) return;
601
+ for (const name of names) {
602
+ const key = name;
603
+ let handlers = this.eventMap.get(key);
604
+ if (!handlers) {
605
+ handlers = [];
606
+ this.eventMap.set(key, handlers);
607
+ }
608
+ handlers.push(handlerClass);
510
609
  }
511
- handlers.push(handlerClass);
512
610
  }
513
611
  attachToClient() {
514
612
  for (const [eventName] of this.eventMap) {
515
- this.logger.debug(`Attaching ${chalk2__default.default.bold.green(eventName)} to ${chalk2__default.default.bold.yellow(this.core.bot.client.user?.username)}`);
613
+ this.logger.debug(`Attaching ${chalk4__default.default.bold.green(eventName)} to ${chalk4__default.default.bold.yellow(this.core.bot.client.user?.username)}`);
516
614
  this.core.bot.client.on(eventName, (...args) => {
517
615
  void (async () => {
518
616
  await this.processEvent(eventName, args);
@@ -521,11 +619,13 @@ var EventController = class {
521
619
  }
522
620
  }
523
621
  async processEvent(eventName, args) {
622
+ const shouldContinue = await this.runMiddlewares(eventName, args);
623
+ if (!shouldContinue) return;
524
624
  const handlerCtors = this.eventMap.get(eventName);
525
625
  if (!handlerCtors || handlerCtors.length === 0) return;
526
626
  for (const HandlerCtor of handlerCtors) {
527
627
  try {
528
- this.logger.debug(`Processing ${chalk2__default.default.bold.green(eventName)} with ${chalk2__default.default.gray(HandlerCtor.name)}`);
628
+ this.logger.debug(`Processing ${chalk4__default.default.bold.green(eventName)} with ${chalk4__default.default.gray(HandlerCtor.name)}`);
529
629
  const handler = new HandlerCtor(args, this.core);
530
630
  if (handler.hasChecks()) {
531
631
  await handler.runChecks();
@@ -541,7 +641,7 @@ var EventController = class {
541
641
  }
542
642
  };
543
643
 
544
- // src/bot/decorators/InteractionConfigurable.ts
644
+ // src/bot/decorators/Interactions.ts
545
645
  var InteractionRoutes = /* @__PURE__ */ (function(InteractionRoutes2) {
546
646
  InteractionRoutes2["Slash"] = "interaction:slash";
547
647
  InteractionRoutes2["Button"] = "interaction:button";
@@ -621,9 +721,6 @@ function SelectMenuRoute(type, routeOrRoutes) {
621
721
  }
622
722
  __name(SelectMenuRoute, "SelectMenuRoute");
623
723
  function storeMetadata(symbol, routes, constructor) {
624
- const areRoutes = /* @__PURE__ */ __name((routes2) => {
625
- return Array.isArray(routes2) && routes2.every((r) => typeof r === "string");
626
- }, "areRoutes");
627
724
  const savedRoutes = Reflect.getMetadata(symbol, constructor);
628
725
  const existing = areRoutes(savedRoutes) ? savedRoutes : [];
629
726
  const toStore = Array.isArray(routes) ? routes : [
@@ -644,11 +741,11 @@ var DatabaseError = class extends CustomError {
644
741
  }
645
742
  uuid;
646
743
  /**
647
- * Creates a new DatabaseError.
648
- *
649
- * @param message - The error message describing what went wrong
650
- * @param uuid - A unique identifier for this specific error instance
651
- */
744
+ * Creates a new DatabaseError.
745
+ *
746
+ * @param message - The error message describing what went wrong
747
+ * @param uuid - A unique identifier for this specific error instance
748
+ */
652
749
  constructor(message, uuid) {
653
750
  super(message), this.uuid = uuid;
654
751
  this.emit = true;
@@ -658,69 +755,71 @@ var DatabaseError = class extends CustomError {
658
755
  }
659
756
  };
660
757
 
661
- // src/bot/utilities/ErrorHandlingUtils.ts
662
- var ErrorHandlingUtils = class {
663
- static {
664
- __name(this, "ErrorHandlingUtils");
665
- }
666
- static logger = new services.Logger("Errors");
667
- /**
668
- * Processes an error and extracts the standardized response, if available.
669
- *
670
- * Handles different error types (CustomError, DatabaseError) with appropriate
671
- * logging, side effects, and user-facing error messages.
672
- *
673
- * @param error - The error to process
674
- * @param core - The core framework instance
675
- * @param guild - The guild where the error occurred (if any)
676
- * @param user - The user who triggered the error (if any)
677
- * @returns Object containing UUID and formatted error response embed
678
- */
679
- static extractErrorResponse(error, core, guild, user) {
680
- const uuid = crypto2__namespace.randomUUID();
681
- if (error instanceof CustomError) {
682
- if (error instanceof DatabaseError) {
683
- core.effects.emit("unknownException", {
684
- uuid,
685
- error,
686
- guild,
687
- user
688
- });
689
- this.logger.error(`DatabaseError: ${error.uuid}`);
690
- } else if (error.emit) {
691
- this.logger.error(`${error.name}: ${error.message}`, error);
692
- }
693
- return {
758
+ // src/bot/utilities/errors/extractErrorResponse.ts
759
+ function _ts_decorate2(decorators, target, key, desc) {
760
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
761
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
762
+ 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;
763
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
764
+ }
765
+ __name(_ts_decorate2, "_ts_decorate");
766
+ function _ts_metadata2(k, v) {
767
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
768
+ }
769
+ __name(_ts_metadata2, "_ts_metadata");
770
+ var logger = new services.Logger("ErrorsHandling");
771
+ function extractErrorResponse(error, core, guild, user, metadata) {
772
+ const uuid = crypto2__namespace.randomUUID();
773
+ if (error instanceof CustomError) {
774
+ if (error instanceof DatabaseError) {
775
+ core.effects.emit("unknownException", {
694
776
  uuid,
695
- response: error.response
696
- };
777
+ error,
778
+ guild,
779
+ user,
780
+ metadata
781
+ });
782
+ logger.error(`DatabaseError: ${error.uuid}`);
783
+ } else if (error.emit) {
784
+ logger.error(`${error.name}: ${error.message}`, error);
697
785
  }
698
- const showStack = core.config.bot.errorStack;
699
- if (showStack) this.logger.error(uuid, error);
700
- else this.logger.error(`${uuid} | ${error.message}`);
701
- core.effects.emit("unknownException", {
702
- uuid,
703
- error,
704
- guild,
705
- user
706
- });
707
786
  return {
708
787
  uuid,
709
- response: new GenericError(uuid).response
788
+ response: error.response
710
789
  };
711
790
  }
712
- };
713
- var GenericError = class GenericError2 extends CustomError {
791
+ const showStack = core.config.bot.errorStack;
792
+ if (showStack) logger.error(uuid, error);
793
+ else logger.error(`${uuid} | ${error.message}`);
794
+ core.effects.emit("unknownException", {
795
+ uuid,
796
+ error,
797
+ guild,
798
+ user,
799
+ metadata
800
+ });
801
+ return {
802
+ uuid,
803
+ response: new GenericError(uuid).response
804
+ };
805
+ }
806
+ __name(extractErrorResponse, "extractErrorResponse");
807
+ var GenericError = class extends CustomError {
714
808
  static {
715
809
  __name(this, "GenericError");
716
810
  }
717
811
  uuid;
812
+ developerUsername = "the developer";
718
813
  constructor(uuid) {
719
814
  super("An unknown error occurred"), this.uuid = uuid;
720
- this.response.setTitle("Error").setDescription(`An unknown error occurred. Please reach out to the developer with a way to reproduce the error and the following:
815
+ this.response.setTitle("Error").setDescription(`An unknown error occurred. Please reach out to ${this.developerUsername} with a way to reproduce the error and the following:
721
816
  ### UUID: \`${this.uuid}\``);
722
817
  }
723
818
  };
819
+ _ts_decorate2([
820
+ envapt.Envapt("DEVELOPER_DISCORD_USERNAME"),
821
+ _ts_metadata2("design:type", String)
822
+ ], GenericError.prototype, "developerUsername", void 0);
724
823
 
725
824
  // src/bot/decorators/Catchable.ts
726
825
  function Catchable(options) {
@@ -737,7 +836,7 @@ function Catchable(options) {
737
836
  if (!(error instanceof Error)) throw error;
738
837
  this.setErrored();
739
838
  if (log) console.error(error);
740
- const { response } = ErrorHandlingUtils.extractErrorResponse(error, this.core, interaction.guild, interaction.user);
839
+ const { response } = extractErrorResponse(error, this.core, interaction.guild, interaction.user, interaction);
741
840
  const res = {
742
841
  embeds: [
743
842
  response
@@ -771,17 +870,17 @@ function Catchable(options) {
771
870
  __name(Catchable, "Catchable");
772
871
 
773
872
  // src/bot/defaults/UnhandledEvent.ts
774
- function _ts_decorate2(decorators, target, key, desc) {
873
+ function _ts_decorate3(decorators, target, key, desc) {
775
874
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
776
875
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
777
876
  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;
778
877
  return c > 3 && r && Object.defineProperty(target, key, r), r;
779
878
  }
780
- __name(_ts_decorate2, "_ts_decorate");
781
- function _ts_metadata2(k, v) {
879
+ __name(_ts_decorate3, "_ts_decorate");
880
+ function _ts_metadata3(k, v) {
782
881
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
783
882
  }
784
- __name(_ts_metadata2, "_ts_metadata");
883
+ __name(_ts_metadata3, "_ts_metadata");
785
884
  var UnhandledEvent = class extends InteractionHandler {
786
885
  static {
787
886
  __name(this, "UnhandledEvent");
@@ -793,12 +892,32 @@ var UnhandledEvent = class extends InteractionHandler {
793
892
  });
794
893
  }
795
894
  };
796
- _ts_decorate2([
895
+ _ts_decorate3([
797
896
  Catchable(),
798
- _ts_metadata2("design:type", Function),
799
- _ts_metadata2("design:paramtypes", []),
800
- _ts_metadata2("design:returntype", Promise)
897
+ _ts_metadata3("design:type", Function),
898
+ _ts_metadata3("design:paramtypes", []),
899
+ _ts_metadata3("design:returntype", Promise)
801
900
  ], UnhandledEvent.prototype, "execute", null);
901
+ function buildSlashRoute(arg1, arg2, arg3) {
902
+ let command;
903
+ let sub;
904
+ let group;
905
+ if (typeof arg1 === "string") {
906
+ command = arg1;
907
+ sub = arg2;
908
+ group = arg3;
909
+ } else if (arg1 instanceof discord_js.ChatInputCommandInteraction || arg1 instanceof discord_js.AutocompleteInteraction) {
910
+ command = arg1.commandName;
911
+ group = arg1.options.getSubcommandGroup(false) ?? void 0;
912
+ sub = arg1.options.getSubcommand(false) ?? void 0;
913
+ } else {
914
+ throw new TypeError("Invalid argument passed to buildSlashRoute");
915
+ }
916
+ if (sub && group) return `${command}/${group}/${sub}`;
917
+ if (sub) return `${command}/${sub}`;
918
+ return command;
919
+ }
920
+ __name(buildSlashRoute, "buildSlashRoute");
802
921
 
803
922
  // src/bot/controllers/InteractionController.ts
804
923
  var InteractionController = class {
@@ -832,40 +951,66 @@ var InteractionController = class {
832
951
  if (this.isInitialized) return;
833
952
  this.isInitialized = true;
834
953
  const handlersDir = this.core.config.bot.interactions.path;
835
- this.logger.info(chalk2__default.default.bold(handlersDir));
954
+ this.logger.info(chalk4__default.default.bold(handlersDir));
955
+ const middlewareDir = this.core.config.bot.interactions.middlewares;
956
+ if (middlewareDir) {
957
+ this.logger.info(`${chalk4__default.default.bold(middlewareDir)} ${chalk4__default.default.gray("(middlewares)")}`);
958
+ await this.loadMiddlewares(middlewareDir);
959
+ }
836
960
  await this.loadHandlers(handlersDir);
837
961
  this.attachToClient();
838
- this.logger.info(`${chalk2__default.default.bold.green("Loaded interaction handlers:")}`);
839
- this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.slashMap.size)} slash commands`);
840
- this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.buttonMap.size)} buttons`);
841
- this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.modalMap.size)} modals`);
842
- this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.stringSelectMap.size)} string selects`);
843
- this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.userSelectMap.size)} user selects`);
844
- this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.roleSelectMap.size)} role selects`);
845
- this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.channelSelectMap.size)} channel selects`);
846
- this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.mentionableSelectMap.size)} mentionable selects`);
847
- this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.messageContextMenuMap.size)} message context menus`);
848
- this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.userContextMenuMap.size)} user context menus`);
849
- this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.autocompleteMap.size)} autocomplete`);
962
+ this.logger.info(`${chalk4__default.default.bold.green("Loaded interaction handlers:")}`);
963
+ this.logger.info(`\u2192 ${chalk4__default.default.magenta.bold(this.middlewares.length)} middlewares`);
964
+ this.logger.info(`\u2192 ${chalk4__default.default.magenta.bold(this.slashMap.size)} slash commands`);
965
+ this.logger.info(`\u2192 ${chalk4__default.default.magenta.bold(this.buttonMap.size)} buttons`);
966
+ this.logger.info(`\u2192 ${chalk4__default.default.magenta.bold(this.modalMap.size)} modals`);
967
+ this.logger.info(`\u2192 ${chalk4__default.default.magenta.bold(this.stringSelectMap.size)} string selects`);
968
+ this.logger.info(`\u2192 ${chalk4__default.default.magenta.bold(this.userSelectMap.size)} user selects`);
969
+ this.logger.info(`\u2192 ${chalk4__default.default.magenta.bold(this.roleSelectMap.size)} role selects`);
970
+ this.logger.info(`\u2192 ${chalk4__default.default.magenta.bold(this.channelSelectMap.size)} channel selects`);
971
+ this.logger.info(`\u2192 ${chalk4__default.default.magenta.bold(this.mentionableSelectMap.size)} mentionable selects`);
972
+ this.logger.info(`\u2192 ${chalk4__default.default.magenta.bold(this.messageContextMenuMap.size)} message context menus`);
973
+ this.logger.info(`\u2192 ${chalk4__default.default.magenta.bold(this.userContextMenuMap.size)} user context menus`);
974
+ this.logger.info(`\u2192 ${chalk4__default.default.magenta.bold(this.autocompleteMap.size)} autocomplete`);
850
975
  }
851
976
  async loadHandlers(dir) {
852
977
  await utils.traverseDirectory(dir, (_fullPath, relativePath, imported) => {
853
978
  for (const val of Object.values(imported)) {
854
- if (this.isHandlerClass(val)) {
855
- this.registerHandler(val);
856
- this.logger.info(`${chalk2__default.default.italic("Registered")} ${chalk2__default.default.bold.yellow(val.name)} from ${chalk2__default.default.gray(relativePath)}`);
857
- }
979
+ if (!this.isHandlerClass(val)) continue;
980
+ this.registerHandler(val);
981
+ this.logger.info(`${chalk4__default.default.italic("Registered")} ${chalk4__default.default.bold.yellow(val.name)} from ${chalk4__default.default.gray(relativePath)}`);
858
982
  }
859
983
  }, this.logger);
860
984
  }
985
+ async loadMiddlewares(dir) {
986
+ await utils.traverseDirectory(dir, (_fullPath, relativePath, imported) => {
987
+ for (const val of Object.values(imported)) {
988
+ if (!this.isMiddlewareClass(val)) continue;
989
+ const metadata = Reflect.getMetadata(MiddlewareMetadataKey, val);
990
+ if (metadata?.type !== MiddlewareType.Interaction) continue;
991
+ this.registerMiddleware(val, metadata, relativePath);
992
+ }
993
+ }, this.logger);
994
+ }
995
+ registerMiddleware(middlewareCtor, metadata, relativePath) {
996
+ const alreadyRegistered = this.middlewares.some((entry) => entry.ctor === middlewareCtor);
997
+ if (alreadyRegistered) return;
998
+ this.middlewares.push({
999
+ ctor: middlewareCtor,
1000
+ priority: metadata.priority
1001
+ });
1002
+ this.middlewares.sort((a, b) => a.priority - b.priority);
1003
+ this.logger.info(`${chalk4__default.default.italic("Registered middleware")} ${chalk4__default.default.bold.yellow(middlewareCtor.name)} ${chalk4__default.default.gray(`(priority ${metadata.priority})`)} from ${chalk4__default.default.gray(relativePath)}`);
1004
+ }
861
1005
  isHandlerClass(obj) {
862
1006
  if (typeof obj !== "function") return false;
863
1007
  return obj.prototype instanceof InteractionHandler && Reflect.hasMetadata(InteractionMetadataKey, obj) || obj.prototype instanceof AutocompleteHandler && Reflect.hasMetadata(InteractionMetadataKey, obj);
864
1008
  }
1009
+ isMiddlewareClass(obj) {
1010
+ if (typeof obj !== "function") return false;
1011
+ return obj.prototype instanceof InteractionMiddleware && Reflect.hasMetadata(MiddlewareMetadataKey, obj);
1012
+ }
865
1013
  registerHandler(handlerClass) {
866
- const areRoutes = /* @__PURE__ */ __name((routes) => {
867
- return Array.isArray(routes) && routes.every((r) => typeof r === "string");
868
- }, "areRoutes");
869
1014
  const routeTypes = [
870
1015
  [
871
1016
  InteractionRoutes.Slash,
@@ -922,7 +1067,7 @@ var InteractionController = class {
922
1067
  attachToClient() {
923
1068
  this.core.bot.client.on(discord_js.Events.InteractionCreate, (interaction) => {
924
1069
  this.handleInteraction(interaction).catch((err) => {
925
- this.logger.error(`[${chalk2__default.default.bold.red("UNHANDLED ERROR AT ROOT")}] ${err.name}`, err.stack);
1070
+ this.logger.error(`[${chalk4__default.default.bold.red("UNHANDLED ERROR AT ROOT")}] ${err.name}`, err.stack);
926
1071
  });
927
1072
  });
928
1073
  }
@@ -944,17 +1089,19 @@ var InteractionController = class {
944
1089
  async processInteraction(interaction, extractKey, getHandler, args) {
945
1090
  const key = extractKey(interaction);
946
1091
  if (this.keysToIgnore.has(key)) return;
947
- for (const MiddlewareCtor of this.middlewares) {
948
- const middleware = new MiddlewareCtor(interaction, this.core, args);
1092
+ for (const { ctor } of this.middlewares) {
1093
+ const middleware = new ctor(interaction, this.core, args);
1094
+ if (middleware.hasChecks()) await middleware.runChecks();
1095
+ if (middleware.shouldBreak() || middleware.hasErrors()) return;
949
1096
  await middleware.execute();
950
- if (middleware.hasErrors()) return;
1097
+ if (middleware.shouldBreak() || middleware.hasErrors()) return;
951
1098
  }
952
1099
  let HandlerCtor = getHandler(key);
953
1100
  if (!HandlerCtor) {
954
- this.logger.warn(`No handler found for key ${chalk2__default.default.bold.cyan(key)}. Falling back to UnhandledEvent.`);
1101
+ this.logger.warn(`No handler found for key ${chalk4__default.default.bold.cyan(key)}. Falling back to UnhandledEvent.`);
955
1102
  HandlerCtor = UnhandledEvent;
956
1103
  }
957
- this.logger.debug(`Processing ${chalk2__default.default.bold.green(key)} with ${chalk2__default.default.gray(HandlerCtor.name)}`);
1104
+ this.logger.debug(`Processing ${chalk4__default.default.bold.green(key)} with ${chalk4__default.default.gray(HandlerCtor.name)}`);
958
1105
  const handler = new HandlerCtor(interaction, this.core, args);
959
1106
  if (handler.hasChecks()) await handler.runChecks();
960
1107
  if (handler.shouldBreak()) return;
@@ -1001,7 +1148,7 @@ var InteractionController = class {
1001
1148
  }
1002
1149
  }
1003
1150
  async handleSlashCommand(interaction) {
1004
- const route = this.buildSlashRoute(interaction);
1151
+ const route = buildSlashRoute(interaction);
1005
1152
  await this.processInteraction(interaction, () => route, (key) => this.slashMap.get(key));
1006
1153
  }
1007
1154
  async handleButton(interaction) {
@@ -1032,26 +1179,11 @@ var InteractionController = class {
1032
1179
  await this.processInteraction(interaction, () => interaction.commandName, (key) => this.userContextMenuMap.get(key));
1033
1180
  }
1034
1181
  async handleAutocomplete(interaction) {
1035
- const route = this.buildSlashRoute(interaction);
1182
+ const route = buildSlashRoute(interaction);
1036
1183
  const focused = interaction.options.getFocused(true);
1037
1184
  const autocompleteKey = `${route}:${focused.name}`;
1038
1185
  await this.processInteraction(interaction, () => autocompleteKey, (key) => this.autocompleteMap.get(key));
1039
1186
  }
1040
- // Build the route from commandName, subcommandGroup, subcommand
1041
- buildSlashRoute(interaction) {
1042
- const command = interaction.commandName;
1043
- const group = interaction.options.getSubcommandGroup(false);
1044
- const sub = interaction.options.getSubcommand(false);
1045
- let route = command;
1046
- if (group && sub) {
1047
- route = `${route}/${group}/${sub}`;
1048
- } else if (group) {
1049
- route = `${route}/${group}`;
1050
- } else if (sub) {
1051
- route = `${route}/${sub}`;
1052
- }
1053
- return route;
1054
- }
1055
1187
  };
1056
1188
  var EmojiInjector = class {
1057
1189
  static {
@@ -1064,7 +1196,7 @@ var EmojiInjector = class {
1064
1196
  }
1065
1197
  async init() {
1066
1198
  if (!this.core.config.bot.emojis || Object.keys(this.core.config.bot.emojis).length === 0) {
1067
- this.logger.info(`${chalk2__default.default.bold.green("Loaded")}: ${chalk2__default.default.magenta.bold("0")} emojis`);
1199
+ this.logger.info(`${chalk4__default.default.bold.green("Loaded")}: ${chalk4__default.default.magenta.bold("0")} emojis`);
1068
1200
  return;
1069
1201
  }
1070
1202
  const configEmojis = this.core.config.bot.emojis;
@@ -1075,25 +1207,25 @@ var EmojiInjector = class {
1075
1207
  if (emoji) {
1076
1208
  configEmojis[key] = `<${emoji.identifier}>`;
1077
1209
  foundCount++;
1078
- this.logger.debug(`${chalk2__default.default.bold.green("Found")}: ${chalk2__default.default.magenta.bold(emojiName)} (${emoji.id})`);
1210
+ this.logger.debug(`${chalk4__default.default.bold.green("Found")}: ${chalk4__default.default.magenta.bold(emojiName)} (${emoji.id})`);
1079
1211
  }
1080
1212
  });
1081
- this.logger.info(`${chalk2__default.default.bold.green("Loaded")}: ${chalk2__default.default.magenta.bold(foundCount)} emojis`);
1213
+ this.logger.info(`${chalk4__default.default.bold.green("Loaded")}: ${chalk4__default.default.magenta.bold(foundCount)} emojis`);
1082
1214
  }
1083
1215
  };
1084
1216
 
1085
1217
  // src/bot/Bot.ts
1086
- function _ts_decorate3(decorators, target, key, desc) {
1218
+ function _ts_decorate4(decorators, target, key, desc) {
1087
1219
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1088
1220
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1089
1221
  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;
1090
1222
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1091
1223
  }
1092
- __name(_ts_decorate3, "_ts_decorate");
1093
- function _ts_metadata3(k, v) {
1224
+ __name(_ts_decorate4, "_ts_decorate");
1225
+ function _ts_metadata4(k, v) {
1094
1226
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1095
1227
  }
1096
- __name(_ts_metadata3, "_ts_metadata");
1228
+ __name(_ts_metadata4, "_ts_metadata");
1097
1229
  var Bot = class extends Plugin {
1098
1230
  static {
1099
1231
  __name(this, "Bot");
@@ -1106,10 +1238,6 @@ var Bot = class extends Plugin {
1106
1238
  events;
1107
1239
  commands;
1108
1240
  emojiInjector;
1109
- /**
1110
- * @param core - Seedcord core instance
1111
- * @internal
1112
- */
1113
1241
  constructor(core) {
1114
1242
  super(core), this.core = core;
1115
1243
  this._client = new discord_js.Client(core.config.bot.clientOptions);
@@ -1120,9 +1248,9 @@ var Bot = class extends Plugin {
1120
1248
  this.core.shutdown.addTask(services.ShutdownPhase.DiscordCleanup, "stop-bot", async () => await this.stop());
1121
1249
  }
1122
1250
  /**
1123
- * Initializes Discord client and all controllers
1124
- * @internal
1125
- */
1251
+ * Initializes Discord client and all controllers
1252
+ * @internal
1253
+ */
1126
1254
  async init() {
1127
1255
  if (this.isInitialized) {
1128
1256
  return;
@@ -1136,40 +1264,40 @@ var Bot = class extends Plugin {
1136
1264
  await this.emojiInjector.init();
1137
1265
  }
1138
1266
  /**
1139
- * Stops the bot and cleans up connections
1140
- * @internal
1141
- */
1267
+ * Stops the bot and cleans up connections
1268
+ * @internal
1269
+ */
1142
1270
  async stop() {
1143
1271
  this._client.removeAllListeners();
1144
1272
  await this.logout();
1145
1273
  }
1146
1274
  /**
1147
- * Logs the bot into Discord using the configured token
1148
- */
1275
+ * Logs the bot into Discord using the configured token
1276
+ */
1149
1277
  async login() {
1150
1278
  await this._client.login(this.botToken);
1151
- this.logger.info(`Logged in as ${chalk2__default.default.bold.magenta(this._client.user?.username)}!`);
1279
+ this.logger.info(`Logged in as ${chalk4__default.default.bold.magenta(this._client.user?.username)}!`);
1152
1280
  return this;
1153
1281
  }
1154
1282
  /**
1155
- * Logs out and destroys the Discord client connection
1156
- */
1283
+ * Logs out and destroys the Discord client connection
1284
+ */
1157
1285
  async logout() {
1158
1286
  await this._client.destroy();
1159
- this.logger.info(chalk2__default.default.bold.red("Logged out of Discord!"));
1287
+ this.logger.info(chalk4__default.default.bold.red("Logged out of Discord!"));
1160
1288
  }
1161
1289
  get client() {
1162
1290
  return this._client;
1163
1291
  }
1164
1292
  };
1165
- _ts_decorate3([
1293
+ _ts_decorate4([
1166
1294
  envapt.Envapt("DISCORD_BOT_TOKEN", {
1167
1295
  converter(raw, _fallback) {
1168
1296
  if (typeof raw !== "string") throw new Error("Missing DISCORD_BOT_TOKEN");
1169
1297
  return raw;
1170
1298
  }
1171
1299
  }),
1172
- _ts_metadata3("design:type", String)
1300
+ _ts_metadata4("design:type", String)
1173
1301
  ], Bot.prototype, "botToken", void 0);
1174
1302
 
1175
1303
  // src/effects/decorators/RegisterEffect.ts
@@ -1189,11 +1317,11 @@ var EffectsHandler = class {
1189
1317
  data;
1190
1318
  core;
1191
1319
  /**
1192
- * Creates a new effects handler instance.
1193
- *
1194
- * @param data - The effect event data
1195
- * @param core - The core framework instance
1196
- */
1320
+ * Creates a new effects handler instance.
1321
+ *
1322
+ * @param data - The effect event data
1323
+ * @param core - The core framework instance
1324
+ */
1197
1325
  constructor(data, core) {
1198
1326
  this.data = data;
1199
1327
  this.core = core;
@@ -1213,35 +1341,55 @@ var WebhookLog = class extends EffectsHandler {
1213
1341
  };
1214
1342
 
1215
1343
  // src/effects/default/UnknownException.ts
1216
- function _ts_decorate4(decorators, target, key, desc) {
1344
+ function _ts_decorate5(decorators, target, key, desc) {
1217
1345
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1218
1346
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1219
1347
  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;
1220
1348
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1221
1349
  }
1222
- __name(_ts_decorate4, "_ts_decorate");
1223
- function _ts_metadata4(k, v) {
1350
+ __name(_ts_decorate5, "_ts_decorate");
1351
+ function _ts_metadata5(k, v) {
1224
1352
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1225
1353
  }
1226
- __name(_ts_metadata4, "_ts_metadata");
1227
- var UnknownException = class _UnknownException extends WebhookLog {
1354
+ __name(_ts_metadata5, "_ts_metadata");
1355
+ exports.UnknownException = class _UnknownException extends WebhookLog {
1228
1356
  static {
1229
1357
  __name(this, "UnknownException");
1230
1358
  }
1359
+ static logger = new services.Logger("Effect: UnknownException");
1231
1360
  webhook = new discord_js.WebhookClient({
1232
1361
  url: _UnknownException.unknownExceptionWebhookUrl
1233
1362
  });
1234
1363
  async execute() {
1235
- await this.webhook.send({
1236
- username: "Unknown Exception",
1237
- avatarURL: "https://cdn.discordapp.com/attachments/1351446034827579466/1351446912947191830/warning-2.png",
1238
- embeds: [
1239
- new UnhandledErrorEmbed(this.data).component
1240
- ]
1364
+ const metadataFile = this.prepareMetadataFile();
1365
+ try {
1366
+ await this.webhook.send({
1367
+ flags: "IsComponentsV2",
1368
+ withComponents: true,
1369
+ username: "Unknown Exception",
1370
+ avatarURL: "https://cdn.discordapp.com/attachments/1351446034827579466/1351446912947191830/warning-2.png",
1371
+ components: [
1372
+ new UnhandledErrorContainer(this.data).component
1373
+ ],
1374
+ files: metadataFile ? [
1375
+ metadataFile
1376
+ ] : []
1377
+ });
1378
+ } catch (error) {
1379
+ _UnknownException.logger.error("Failed to send unknown exception webhook", error);
1380
+ }
1381
+ }
1382
+ prepareMetadataFile() {
1383
+ const { metadata } = this.data;
1384
+ if (!metadata) return null;
1385
+ const content = utils.filterCirculars(metadata);
1386
+ return new discord_js.AttachmentBuilder(Buffer.from(JSON.stringify(content, void 0, 2), "utf-8"), {
1387
+ name: "metadata.json",
1388
+ description: "Metadata associated with the error"
1241
1389
  });
1242
1390
  }
1243
1391
  };
1244
- _ts_decorate4([
1392
+ _ts_decorate5([
1245
1393
  envapt.Envapt("UNKNOWN_EXCEPTION_WEBHOOK_URL", {
1246
1394
  converter(raw, _fallback) {
1247
1395
  if (!raw) throw new Error("Missing UNKNOWN_EXCEPTION_WEBHOOK_URL");
@@ -1249,27 +1397,38 @@ _ts_decorate4([
1249
1397
  return raw;
1250
1398
  }
1251
1399
  }),
1252
- _ts_metadata4("design:type", String)
1253
- ], UnknownException, "unknownExceptionWebhookUrl", void 0);
1254
- UnknownException = _ts_decorate4([
1400
+ _ts_metadata5("design:type", String)
1401
+ ], exports.UnknownException, "unknownExceptionWebhookUrl", void 0);
1402
+ exports.UnknownException = _ts_decorate5([
1255
1403
  RegisterEffect("unknownException")
1256
- ], UnknownException);
1257
- var UnhandledErrorEmbed = class UnhandledErrorEmbed2 extends BuilderComponent {
1404
+ ], exports.UnknownException);
1405
+ var DefaultSeparator = class DefaultSeparator2 extends BuilderComponent {
1258
1406
  static {
1259
- __name(this, "UnhandledErrorEmbed");
1407
+ __name(this, "DefaultSeparator");
1408
+ }
1409
+ constructor() {
1410
+ super("separator");
1411
+ this.instance.setSpacing(discord_js.SeparatorSpacingSize.Small).setDivider(true);
1412
+ }
1413
+ };
1414
+ var UnhandledErrorContainer = class UnhandledErrorContainer2 extends BuilderComponent {
1415
+ static {
1416
+ __name(this, "UnhandledErrorContainer");
1260
1417
  }
1261
1418
  constructor(data) {
1262
- super("embed");
1263
- const { uuid, error, guild, user } = data;
1264
- this.instance.setTitle(`An unknown exception was thrown`).setColor("#ef4860").setDescription(`**Guild ID:** \`${guild?.id ?? "Not used in a guild"}\`
1419
+ super("container");
1420
+ const { uuid, error, guild, user, metadata } = data;
1421
+ this.instance.addTextDisplayComponents((text) => text.setContent(`### An unknown exception was thrown
1422
+ **Guild ID:** \`${guild?.id ?? "Not used in a guild"}\`
1265
1423
  **Guild Name:** ${guild?.name ?? "Not used in a guild"}
1266
1424
  **User ID:** \`${user?.id ?? "Missing user info"}\`
1267
1425
  **Username:** ${user?.username ?? "Missing user info"}
1268
- ### UUID: \`${uuid}\`
1269
- \`\`\`${error.stack}\`\`\``);
1270
- this.setTimestampsIfAvailable(error);
1426
+ `)).addSeparatorComponents(new DefaultSeparator().component).addTextDisplayComponents((text) => text.setContent(`### UUID \`${uuid}\`
1427
+ \`\`\`${error.stack}\`\`\``));
1428
+ this.addTimestampsIfAvailable(error);
1429
+ this.addMetadataIfAvailable(metadata);
1271
1430
  }
1272
- setTimestampsIfAvailable(error) {
1431
+ addTimestampsIfAvailable(error) {
1273
1432
  if (!(error instanceof discord_js.DiscordAPIError)) return;
1274
1433
  const now = Date.now();
1275
1434
  const snowflake = error.url.match(/\/interactions\/(\d+)\//)?.[1];
@@ -1278,15 +1437,14 @@ var UnhandledErrorEmbed = class UnhandledErrorEmbed2 extends BuilderComponent {
1278
1437
  const diff = now - interactionTs;
1279
1438
  const seconds = Math.floor(diff / 1e3);
1280
1439
  const millis = diff % 1e3;
1281
- this.instance.addFields([
1282
- {
1283
- name: "Timestamps",
1284
- value: `- **\`Interaction sent\` :** ${new Date(interactionTs).toISOString()} (${interactionTs})
1440
+ this.instance.addSeparatorComponents(new DefaultSeparator().component).addTextDisplayComponents((text) => text.setContent(`### Timestamps
1441
+ - **\`Interaction sent\` :** ${new Date(interactionTs).toISOString()} (${interactionTs})
1285
1442
  - **\`Error logged \` :** ${new Date(now).toISOString()} (${now})
1286
- - **\`Offset \` :** ${seconds}s ${millis}ms`,
1287
- inline: true
1288
- }
1289
- ]);
1443
+ - **\`Offset \` :** ${seconds}s ${millis}ms`));
1444
+ }
1445
+ addMetadataIfAvailable(metadata) {
1446
+ if (!metadata) return;
1447
+ this.instance.addSeparatorComponents(new DefaultSeparator().component).addTextDisplayComponents((text) => text.setContent("### Metadata")).addFileComponents((file) => file.setURL("attachment://metadata.json"));
1290
1448
  }
1291
1449
  };
1292
1450
  var EffectsEmitter = class {
@@ -1295,37 +1453,37 @@ var EffectsEmitter = class {
1295
1453
  }
1296
1454
  emitter = new events.EventEmitter();
1297
1455
  /**
1298
- * Registers a listener for the specified side effect.
1299
- *
1300
- * @typeParam KeyOfEffects - The side effect name type
1301
- * @param event - The side effect name to listen for
1302
- * @param listener - Function to call when the event is emitted
1303
- * @returns This EffectsEmitter instance for chaining
1304
- */
1456
+ * Registers a listener for the specified side effect.
1457
+ *
1458
+ * @typeParam KeyOfEffects - The side effect name type
1459
+ * @param event - The side effect name to listen for
1460
+ * @param listener - Function to call when the event is emitted
1461
+ * @returns This EffectsEmitter instance for chaining
1462
+ */
1305
1463
  on(event, listener) {
1306
1464
  this.emitter.on(event, listener);
1307
1465
  return this;
1308
1466
  }
1309
1467
  /**
1310
- * Registers a one-time listener for the specified side effect.
1311
- *
1312
- * @typeParam KeyOfEffects - The side effect name type
1313
- * @param event - The side effect name to listen for once
1314
- * @param listener - Function to call when the event is emitted
1315
- * @returns This EffectsEmitter instance for chaining
1316
- */
1468
+ * Registers a one-time listener for the specified side effect.
1469
+ *
1470
+ * @typeParam KeyOfEffects - The side effect name type
1471
+ * @param event - The side effect name to listen for once
1472
+ * @param listener - Function to call when the event is emitted
1473
+ * @returns This EffectsEmitter instance for chaining
1474
+ */
1317
1475
  once(event, listener) {
1318
1476
  this.emitter.once(event, listener);
1319
1477
  return this;
1320
1478
  }
1321
1479
  /**
1322
- * Emits a side effect with the provided data.
1323
- *
1324
- * @typeParam KeyOfEffects - The side effect name type
1325
- * @param event - The side effect name to emit
1326
- * @param data - The data to pass to registered listeners
1327
- * @returns True if the event had listeners, false otherwise
1328
- */
1480
+ * Emits a side effect with the provided data.
1481
+ *
1482
+ * @typeParam KeyOfEffects - The side effect name type
1483
+ * @param event - The side effect name to emit
1484
+ * @param data - The data to pass to registered listeners
1485
+ * @returns True if the event had listeners, false otherwise
1486
+ */
1329
1487
  emit(event, data) {
1330
1488
  return this.emitter.emit(event, data);
1331
1489
  }
@@ -1348,12 +1506,12 @@ var EffectsRegistry = class extends Plugin {
1348
1506
  if (this.isInitialized) return;
1349
1507
  this.isInitialized = true;
1350
1508
  const effectsDir = this.core.config.effects.path;
1351
- this.logger.info(chalk2__default.default.bold(effectsDir));
1352
- this.registerEffect("unknownException", UnknownException);
1509
+ this.logger.info(chalk4__default.default.bold(effectsDir));
1510
+ this.registerEffect("unknownException", exports.UnknownException);
1353
1511
  await this.loadEffects(effectsDir);
1354
1512
  this.attachEffects();
1355
1513
  const totalEffects = Array.from(this.effectsMap.values()).reduce((acc, handlers) => acc + handlers.length, 0);
1356
- this.logger.info(`${chalk2__default.default.bold.green("Loaded")}: ${chalk2__default.default.bold.magenta(totalEffects)} side effects`);
1514
+ this.logger.info(`${chalk4__default.default.bold.green("Loaded")}: ${chalk4__default.default.bold.magenta(totalEffects)} side effects`);
1357
1515
  }
1358
1516
  async loadEffects(dir) {
1359
1517
  await utils.traverseDirectory(dir, (_fullPath, relativePath, imported) => {
@@ -1363,7 +1521,7 @@ var EffectsRegistry = class extends Plugin {
1363
1521
  const effectName = Reflect.getMetadata(EffectMetadataKey, val);
1364
1522
  if (effectName) {
1365
1523
  this.registerEffect(effectName, val);
1366
- this.logger.info(`${chalk2__default.default.italic("Registered")} ${chalk2__default.default.bold.yellow(val.name)} from ${chalk2__default.default.gray(relativePath)}`);
1524
+ this.logger.info(`${chalk4__default.default.italic("Registered")} ${chalk4__default.default.bold.yellow(val.name)} from ${chalk4__default.default.gray(relativePath)}`);
1367
1525
  }
1368
1526
  }
1369
1527
  }
@@ -1418,11 +1576,11 @@ var Seedcord = class _Seedcord extends Pluggable {
1418
1576
  /** @see {@link HealthCheck} */
1419
1577
  healthCheck;
1420
1578
  /**
1421
- * Creates a new Seedcord instance
1422
- *
1423
- * @param config - Bot configuration including paths and Discord client options
1424
- * @throws An {@link Error} When attempting to create multiple instances (singleton)
1425
- */
1579
+ * Creates a new Seedcord instance
1580
+ *
1581
+ * @param config - Bot configuration including paths and Discord client options
1582
+ * @throws An {@link Error} When attempting to create multiple instances (singleton)
1583
+ */
1426
1584
  constructor(config) {
1427
1585
  const shutdown = new services.CoordinatedShutdown();
1428
1586
  const startup = new services.CoordinatedStartup();
@@ -1439,31 +1597,31 @@ var Seedcord = class _Seedcord extends Pluggable {
1439
1597
  this.registerStartupTasks();
1440
1598
  }
1441
1599
  /**
1442
- * Registers default startup tasks
1443
- * @internal
1444
- */
1600
+ * Registers default startup tasks
1601
+ * @internal
1602
+ */
1445
1603
  registerStartupTasks() {
1446
1604
  this.startup.addTask(services.StartupPhase.Configuration, "Effect Initialization", async () => {
1447
- this.effects.logger.info(chalk2__default.default.bold("Initializing"));
1605
+ this.effects.logger.info(chalk4__default.default.bold("Initializing"));
1448
1606
  await this.effects.init();
1449
- this.effects.logger.info(chalk2__default.default.bold("Initialized"));
1607
+ this.effects.logger.info(chalk4__default.default.bold("Initialized"));
1450
1608
  });
1451
1609
  this.startup.addTask(services.StartupPhase.Instantiation, "Bot Initialization", async () => {
1452
- this.bot.logger.info(chalk2__default.default.bold("Initializing"));
1610
+ this.bot.logger.info(chalk4__default.default.bold("Initializing"));
1453
1611
  await this.bot.init();
1454
- this.bot.logger.info(chalk2__default.default.bold("Initialized"));
1612
+ this.bot.logger.info(chalk4__default.default.bold("Initialized"));
1455
1613
  });
1456
1614
  this.startup.addTask(services.StartupPhase.Ready, "Health Check", async () => {
1457
- this.healthCheck.logger.info(chalk2__default.default.bold("Initializing"));
1615
+ this.healthCheck.logger.info(chalk4__default.default.bold("Initializing"));
1458
1616
  await this.healthCheck.init();
1459
- this.healthCheck.logger.info(chalk2__default.default.bold("Initialized"));
1617
+ this.healthCheck.logger.info(chalk4__default.default.bold("Initialized"));
1460
1618
  });
1461
1619
  }
1462
1620
  /**
1463
- * Starts the bot and runs all initialization tasks
1464
- *
1465
- * @returns This Seedcord instance when fully initialized
1466
- */
1621
+ * Starts the bot and runs all initialization tasks
1622
+ *
1623
+ * @returns This Seedcord instance when fully initialized
1624
+ */
1467
1625
  async start() {
1468
1626
  await super.init();
1469
1627
  return this;
@@ -1493,7 +1651,7 @@ function EventCatchable(log) {
1493
1651
  this.getEvent()
1494
1652
  ];
1495
1653
  const msg = eventArgs.find((x) => x instanceof discord_js.Message);
1496
- const { response } = ErrorHandlingUtils.extractErrorResponse(err, this.core, msg?.guild ?? null, msg?.author ?? null);
1654
+ const { response } = extractErrorResponse(err, this.core, msg?.guild ?? null, msg?.author ?? null, eventArgs);
1497
1655
  if (!msg) return;
1498
1656
  await msg.reply({
1499
1657
  embeds: [
@@ -1506,6 +1664,232 @@ function EventCatchable(log) {
1506
1664
  };
1507
1665
  }
1508
1666
  __name(EventCatchable, "EventCatchable");
1667
+
1668
+ // src/bot/errors/Channels.ts
1669
+ var ChannelNotFoundError = class extends CustomError {
1670
+ static {
1671
+ __name(this, "ChannelNotFoundError");
1672
+ }
1673
+ channelId;
1674
+ /**
1675
+ * Creates a new ChannelNotFoundError.
1676
+ *
1677
+ * @param message - The error message
1678
+ * @param channelId - The ID of the channel that could not be found
1679
+ */
1680
+ constructor(message, channelId) {
1681
+ super(message), this.channelId = channelId;
1682
+ this.response.setDescription(`Channel with ID \`${this.channelId}\` not found.`);
1683
+ }
1684
+ };
1685
+ var CannotSendEmbedsError = class extends CustomError {
1686
+ static {
1687
+ __name(this, "CannotSendEmbedsError");
1688
+ }
1689
+ channelId;
1690
+ /**
1691
+ * Creates a new CannotSendEmbedsError.
1692
+ *
1693
+ * @param message - The error message
1694
+ * @param channelId - The ID of the channel where embeds cannot be sent
1695
+ */
1696
+ constructor(message, channelId) {
1697
+ super(message), this.channelId = channelId;
1698
+ this.response.setDescription(`Cannot send embeds in <#${this.channelId}>.
1699
+
1700
+ Please ensure I have the following permissions:
1701
+ \u2022 View Channel
1702
+ \u2022 Send Messages
1703
+ \u2022 Embed Links
1704
+ \u2022 Attach Files
1705
+ \u2022 Read Message History
1706
+ \u2022 Use External Emojis
1707
+ `);
1708
+ }
1709
+ };
1710
+ var CouldNotFindChannel = class extends CustomError {
1711
+ static {
1712
+ __name(this, "CouldNotFindChannel");
1713
+ }
1714
+ channelId;
1715
+ /**
1716
+ * Creates a new CouldNotFindChannel error.
1717
+ *
1718
+ * @param message - The error message
1719
+ * @param channelId - The ID of the channel that could not be found
1720
+ */
1721
+ constructor(message, channelId) {
1722
+ super(message), this.channelId = channelId;
1723
+ this.response.setDescription(`Could not find channel with ID \`${this.channelId}\`. It could also be that the channel is not a text channel.`);
1724
+ }
1725
+ };
1726
+ var ChannelNotTextChannel = class extends CustomError {
1727
+ static {
1728
+ __name(this, "ChannelNotTextChannel");
1729
+ }
1730
+ channelId;
1731
+ /**
1732
+ * Creates a new ChannelNotTextChannel error.
1733
+ *
1734
+ * @param message - The error message
1735
+ * @param channelId - The ID of the channel that is not a text channel
1736
+ */
1737
+ constructor(message, channelId) {
1738
+ super(message), this.channelId = channelId;
1739
+ this.response.setDescription(`Channel with ID \`${this.channelId}\` is not a text channel.`);
1740
+ }
1741
+ };
1742
+ var MissingPermissions = class extends CustomError {
1743
+ static {
1744
+ __name(this, "MissingPermissions");
1745
+ }
1746
+ missingPerms;
1747
+ roleOrChannel;
1748
+ /**
1749
+ * Creates a new BotMissingPermissionsError.
1750
+ *
1751
+ * @param message - The error message
1752
+ * @param missingPerms - Array of missing permission names
1753
+ * @param roleOrChannel - The role or channel where permissions are missing
1754
+ */
1755
+ constructor(message, missingPerms, roleOrChannel) {
1756
+ super(message), this.missingPerms = missingPerms, this.roleOrChannel = roleOrChannel;
1757
+ const missing = this.missingPerms.map((perm) => `\u2022 ${perm}`).join("\n");
1758
+ const errorSubtext = this.roleOrChannel instanceof discord_js.Role ? `My role, <@&${this.roleOrChannel.id}>, is missing the following permissions:` : `I am missing the following permissions in <#${this.roleOrChannel.id}>:`;
1759
+ this.response.setDescription(`${errorSubtext}
1760
+
1761
+ Please ensure I have the following missing permission(s):
1762
+ ${missing}`);
1763
+ }
1764
+ };
1765
+ var RoleHigherThanMe = class extends CustomError {
1766
+ static {
1767
+ __name(this, "RoleHigherThanMe");
1768
+ }
1769
+ role;
1770
+ botRole;
1771
+ /**
1772
+ * Creates a new RoleHigherThanMe error.
1773
+ *
1774
+ * @param message - The error message
1775
+ */
1776
+ constructor(message, role, botRole) {
1777
+ super(message), this.role = role, this.botRole = botRole;
1778
+ this.response.setDescription(`I cannot assign a role that is higher than me.
1779
+
1780
+ The role <@&${this.role.id}> is higher than my role <@&${this.botRole.id}> in the hierarchy.`);
1781
+ }
1782
+ };
1783
+ var CannotAssignBotRole = class extends CustomError {
1784
+ static {
1785
+ __name(this, "CannotAssignBotRole");
1786
+ }
1787
+ /**
1788
+ * Creates a new CannotAssignBotRole error.
1789
+ *
1790
+ * @param message - The error message
1791
+ */
1792
+ constructor(message = "I cannot assign a managed role.") {
1793
+ super(message);
1794
+ this.response.setDescription("I cannot assign a managed role.");
1795
+ }
1796
+ };
1797
+ var RoleDoesNotExist = class extends CustomError {
1798
+ static {
1799
+ __name(this, "RoleDoesNotExist");
1800
+ }
1801
+ roleId;
1802
+ /**
1803
+ * Creates a new RoleDoesNotExist error.
1804
+ *
1805
+ * @param message - The error message
1806
+ * @param roleId - The ID of the role that doesn't exist
1807
+ */
1808
+ constructor(message, roleId) {
1809
+ super(message), this.roleId = roleId;
1810
+ this.response.setDescription(`The role with ID \`${this.roleId}\` does not exist.`);
1811
+ }
1812
+ };
1813
+ var HasDangerousPermissions = class extends CustomError {
1814
+ static {
1815
+ __name(this, "HasDangerousPermissions");
1816
+ }
1817
+ role;
1818
+ dangerousPerms;
1819
+ /**
1820
+ * Creates a new HasDangerousPermissions error.
1821
+ *
1822
+ * @param message - The error message
1823
+ * @param role - The role with dangerous permissions
1824
+ * @param dangerousPerms - Array of dangerous permission names
1825
+ */
1826
+ constructor(message, role, dangerousPerms) {
1827
+ super(message), this.role = role, this.dangerousPerms = dangerousPerms;
1828
+ const dangerous = this.dangerousPerms.map((perm) => `\u2022 ${perm}`).join("\n");
1829
+ this.response.setDescription(`The role <@&${this.role.id}> has the following dangerous permissions:
1830
+
1831
+ Please ensure the following dangerous permission(s) are not enabled:
1832
+ ${dangerous}`);
1833
+ }
1834
+ };
1835
+
1836
+ // src/bot/errors/User.ts
1837
+ var UserNotInGuild = class extends CustomError {
1838
+ static {
1839
+ __name(this, "UserNotInGuild");
1840
+ }
1841
+ /**
1842
+ * Creates a new UserNotInGuild error.
1843
+ *
1844
+ * @param message - The error message
1845
+ */
1846
+ constructor(message = "User is not in the guild.") {
1847
+ super(message);
1848
+ this.response.setDescription("User is not in the guild.");
1849
+ }
1850
+ };
1851
+ var UserNotFound = class extends CustomError {
1852
+ static {
1853
+ __name(this, "UserNotFound");
1854
+ }
1855
+ userArg;
1856
+ /**
1857
+ * Creates a new UserNotFound error.
1858
+ *
1859
+ * @param userArg - The user argument that could not be resolved
1860
+ */
1861
+ constructor(userArg) {
1862
+ super(`User not found: ${userArg}`), this.userArg = userArg;
1863
+ this.response.setTitle("User Not Found").setDescription(`User probably doesn't exist or was deleted.
1864
+ **User Argument:** \`${this.userArg}\`
1865
+ Please check the user ID and try again. Only pass valid user IDs as the argument.`);
1866
+ }
1867
+ };
1868
+ async function fetchText(client, channelId) {
1869
+ if (channelId instanceof discord_js.TextChannel) {
1870
+ return channelId;
1871
+ }
1872
+ let channel = client.channels.cache.get(channelId);
1873
+ if (!channel) {
1874
+ try {
1875
+ channel = await client.channels.fetch(channelId);
1876
+ } catch {
1877
+ throw new CouldNotFindChannel("Channel not found or not a text channel", channelId);
1878
+ }
1879
+ }
1880
+ if (channel?.isTextBased()) {
1881
+ return channel;
1882
+ }
1883
+ throw new CouldNotFindChannel("Channel not found or not a text channel", channelId);
1884
+ }
1885
+ __name(fetchText, "fetchText");
1886
+
1887
+ // src/bot/utilities/channels/sendInText.ts
1888
+ async function sendInText(client, channelId, message) {
1889
+ const channel = await fetchText(client, channelId);
1890
+ return await channel.send(message);
1891
+ }
1892
+ __name(sendInText, "sendInText");
1509
1893
  function throwCustomError(error, message, CustomError2) {
1510
1894
  const uuid = crypto.randomUUID();
1511
1895
  services.Logger.Error("Throwing Custom Error", error.name);
@@ -1522,43 +1906,343 @@ function throwCustomError(error, message, CustomError2) {
1522
1906
  }
1523
1907
  __name(throwCustomError, "throwCustomError");
1524
1908
 
1909
+ // src/bot/utilities/messages/attemptSendDM.ts
1910
+ async function attemptSendDM(user, content) {
1911
+ const payload = {
1912
+ ...content.content !== void 0 && {
1913
+ content: content.content
1914
+ },
1915
+ ...content.embeds !== void 0 && {
1916
+ embeds: [
1917
+ ...content.embeds
1918
+ ]
1919
+ },
1920
+ ...content.components !== void 0 && {
1921
+ components: [
1922
+ ...content.components
1923
+ ]
1924
+ }
1925
+ };
1926
+ try {
1927
+ return await user.send(payload);
1928
+ } catch {
1929
+ return null;
1930
+ }
1931
+ }
1932
+ __name(attemptSendDM, "attemptSendDM");
1933
+ var PermissionNames = new Map(Object.entries(discord_js.PermissionFlagsBits).map(([key, bit]) => [
1934
+ bit,
1935
+ utils.prettify(key)
1936
+ ]));
1937
+ var PERM_GROUPS = {
1938
+ manage: /* @__PURE__ */ new Map([
1939
+ [
1940
+ discord_js.PermissionFlagsBits.ManageChannels,
1941
+ "Manage Channels"
1942
+ ],
1943
+ [
1944
+ discord_js.PermissionFlagsBits.ManageRoles,
1945
+ "Manage Roles"
1946
+ ],
1947
+ [
1948
+ discord_js.PermissionFlagsBits.ManageWebhooks,
1949
+ "Manage Webhooks"
1950
+ ],
1951
+ [
1952
+ discord_js.PermissionFlagsBits.ManageMessages,
1953
+ "Manage Messages"
1954
+ ],
1955
+ [
1956
+ discord_js.PermissionFlagsBits.ManageNicknames,
1957
+ "Manage Nicknames"
1958
+ ]
1959
+ ]),
1960
+ embed: /* @__PURE__ */ new Map([
1961
+ [
1962
+ discord_js.PermissionFlagsBits.ViewChannel,
1963
+ "View Channel"
1964
+ ],
1965
+ [
1966
+ discord_js.PermissionFlagsBits.SendMessages,
1967
+ "Send Messages"
1968
+ ],
1969
+ [
1970
+ discord_js.PermissionFlagsBits.EmbedLinks,
1971
+ "Embed Links"
1972
+ ],
1973
+ [
1974
+ discord_js.PermissionFlagsBits.AttachFiles,
1975
+ "Attach Files"
1976
+ ],
1977
+ [
1978
+ discord_js.PermissionFlagsBits.UseExternalEmojis,
1979
+ "Use External Emojis"
1980
+ ],
1981
+ [
1982
+ discord_js.PermissionFlagsBits.ReadMessageHistory,
1983
+ "Read Message History"
1984
+ ]
1985
+ ]),
1986
+ others: /* @__PURE__ */ new Map([
1987
+ [
1988
+ discord_js.PermissionFlagsBits.AddReactions,
1989
+ "Add Reactions"
1990
+ ],
1991
+ [
1992
+ discord_js.PermissionFlagsBits.UseApplicationCommands,
1993
+ "Use Application Commands"
1994
+ ]
1995
+ ])
1996
+ };
1997
+ function checkPermissions(client, roleOrChannel, scope = "all", inverse = false) {
1998
+ let required;
1999
+ if (Array.isArray(scope)) {
2000
+ required = /* @__PURE__ */ new Map();
2001
+ for (const bit of scope) {
2002
+ const name = PermissionNames.get(bit);
2003
+ if (name) required.set(bit, name);
2004
+ }
2005
+ } else {
2006
+ switch (scope) {
2007
+ case "manage":
2008
+ required = PERM_GROUPS.manage;
2009
+ break;
2010
+ case "embed":
2011
+ required = PERM_GROUPS.embed;
2012
+ break;
2013
+ case "others":
2014
+ required = new Map([
2015
+ ...PERM_GROUPS.others,
2016
+ ...PERM_GROUPS.embed
2017
+ ]);
2018
+ break;
2019
+ default:
2020
+ required = new Map([
2021
+ ...PERM_GROUPS.manage,
2022
+ ...PERM_GROUPS.others,
2023
+ ...PERM_GROUPS.embed
2024
+ ]);
2025
+ break;
2026
+ }
2027
+ }
2028
+ let permissions;
2029
+ if (roleOrChannel instanceof discord_js.Role) {
2030
+ permissions = roleOrChannel.permissions;
2031
+ } else {
2032
+ if (!client.user) throw new Error("Client user is not available");
2033
+ permissions = roleOrChannel.permissionsFor(client.user, true);
2034
+ }
2035
+ if (!permissions) {
2036
+ throw new MissingPermissions("Missing Permissions", Array.from(required.values()), roleOrChannel);
2037
+ }
2038
+ if (inverse) {
2039
+ const dangerous = Array.from(required.entries()).filter(([bit]) => permissions.has(bit, true)).map(([, name]) => name);
2040
+ if (dangerous.length > 0) {
2041
+ throw new HasDangerousPermissions("Role has dangerous permissions", roleOrChannel, dangerous);
2042
+ }
2043
+ } else {
2044
+ const missing = Array.from(required.entries()).filter(([bit]) => !permissions.has(bit, true)).map(([, name]) => name);
2045
+ if (missing.length > 0) {
2046
+ throw new MissingPermissions("Missing Permissions", missing, roleOrChannel);
2047
+ }
2048
+ }
2049
+ }
2050
+ __name(checkPermissions, "checkPermissions");
2051
+
2052
+ // src/bot/utilities/roles/getBotRole.ts
2053
+ function getBotRole(client, guild) {
2054
+ if (!client.user) throw new Error("Client user is not available");
2055
+ const botRole = guild.roles.botRoleFor(client.user);
2056
+ if (!botRole) throw new Error("Bot role not found in guild");
2057
+ return botRole;
2058
+ }
2059
+ __name(getBotRole, "getBotRole");
2060
+
2061
+ // src/bot/utilities/roles/checkBotPermissions.ts
2062
+ function checkBotPermissions(client, guildOrChannel, scope = "all", inverse = false) {
2063
+ if (guildOrChannel instanceof discord_js.Guild) {
2064
+ const botRole = getBotRole(client, guildOrChannel);
2065
+ checkPermissions(client, botRole, scope, inverse);
2066
+ } else {
2067
+ checkPermissions(client, guildOrChannel, scope);
2068
+ }
2069
+ }
2070
+ __name(checkBotPermissions, "checkBotPermissions");
2071
+ async function fetchRole(clientOrGuild, roleId) {
2072
+ let role;
2073
+ if (!roleId) {
2074
+ throw new RoleDoesNotExist("Role ID is null or undefined", roleId);
2075
+ }
2076
+ if (clientOrGuild instanceof discord_js.Guild) {
2077
+ const guild = clientOrGuild;
2078
+ role = guild.roles.cache.get(roleId);
2079
+ if (!role) {
2080
+ try {
2081
+ role = await guild.roles.fetch(roleId);
2082
+ } catch {
2083
+ throw new RoleDoesNotExist("Role not found in specified guild", roleId);
2084
+ }
2085
+ }
2086
+ } else {
2087
+ const client = clientOrGuild;
2088
+ role = client.guilds.cache.map((guild) => guild.roles.cache.get(roleId)).find((role2) => role2);
2089
+ if (!role) {
2090
+ const guilds = client.guilds.cache;
2091
+ for (const guild of guilds.values()) {
2092
+ try {
2093
+ role = await guild.roles.fetch(roleId);
2094
+ if (role) break;
2095
+ } catch {
2096
+ continue;
2097
+ }
2098
+ }
2099
+ }
2100
+ }
2101
+ if (!role) {
2102
+ throw new RoleDoesNotExist("Role not found", roleId);
2103
+ }
2104
+ return role;
2105
+ }
2106
+ __name(fetchRole, "fetchRole");
2107
+ function hasPermsToAssign(targetRole) {
2108
+ const botRole = getBotRole(targetRole.client, targetRole.guild);
2109
+ if (targetRole.comparePositionTo(botRole) >= 0) {
2110
+ throw new RoleHigherThanMe("Role is higher than me", targetRole, botRole);
2111
+ }
2112
+ if (targetRole.managed) {
2113
+ throw new CannotAssignBotRole(`Cannot assign bot role ${targetRole.name}`);
2114
+ }
2115
+ checkBotPermissions(targetRole.client, targetRole.guild, [
2116
+ discord_js.PermissionFlagsBits.ManageRoles
2117
+ ]);
2118
+ }
2119
+ __name(hasPermsToAssign, "hasPermsToAssign");
2120
+
2121
+ // src/bot/utilities/users/fetchGuildMember.ts
2122
+ async function fetchGuildMember(guild, userId) {
2123
+ let user = guild.members.cache.get(userId);
2124
+ user ??= await guild.members.fetch(userId).catch(() => {
2125
+ throw new UserNotInGuild(`User with ID ${userId} not found in guild`);
2126
+ });
2127
+ return user;
2128
+ }
2129
+ __name(fetchGuildMember, "fetchGuildMember");
2130
+
2131
+ // src/bot/utilities/users/fetchManyGuildMembers.ts
2132
+ async function fetchManyGuildMembers(guild, userIds) {
2133
+ const results = await Promise.allSettled(userIds.map((userId) => fetchGuildMember(guild, userId)));
2134
+ return results.filter((result) => result.status === "fulfilled").map((result) => result.value);
2135
+ }
2136
+ __name(fetchManyGuildMembers, "fetchManyGuildMembers");
2137
+ async function fetchUser(client, userId) {
2138
+ let user = client.users.cache.get(userId);
2139
+ user ??= await client.users.fetch(userId).catch((err) => {
2140
+ if (err instanceof discord_js.DiscordAPIError && err.code === discord_js.RESTJSONErrorCodes.UnknownUser) {
2141
+ throw new UserNotFound(userId);
2142
+ }
2143
+ throw err;
2144
+ });
2145
+ return user;
2146
+ }
2147
+ __name(fetchUser, "fetchUser");
2148
+
2149
+ // src/bot/utilities/users/fetchManyUsers.ts
2150
+ async function fetchManyUsers(client, userIds) {
2151
+ const results = await Promise.allSettled(userIds.map((userId) => fetchUser(client, userId)));
2152
+ return results.filter((result) => result.status === "fulfilled").map((result) => result.value);
2153
+ }
2154
+ __name(fetchManyUsers, "fetchManyUsers");
2155
+
2156
+ // src/bot/utilities/users/updateMemberRoles.ts
2157
+ async function updateMemberRoles(rolesToAdd, rolesToRemove, member) {
2158
+ const current = new Set(member.roles.cache.map((r) => r.id));
2159
+ const toAdd = new Set(rolesToAdd);
2160
+ const toRemove = new Set(rolesToRemove);
2161
+ const updated = current.union(toAdd).difference(toRemove);
2162
+ await member.roles.set([
2163
+ ...updated
2164
+ ]);
2165
+ }
2166
+ __name(updateMemberRoles, "updateMemberRoles");
2167
+
1525
2168
  exports.AutocompleteHandler = AutocompleteHandler;
1526
2169
  exports.AutocompleteRoute = AutocompleteRoute;
2170
+ exports.BaseComponent = BaseComponent;
1527
2171
  exports.BaseErrorEmbed = BaseErrorEmbed;
2172
+ exports.BaseHandler = BaseHandler;
1528
2173
  exports.Bot = Bot;
1529
2174
  exports.BuilderComponent = BuilderComponent;
2175
+ exports.BuilderTypes = BuilderTypes;
1530
2176
  exports.ButtonRoute = ButtonRoute;
2177
+ exports.CannotAssignBotRole = CannotAssignBotRole;
2178
+ exports.CannotSendEmbedsError = CannotSendEmbedsError;
1531
2179
  exports.Catchable = Catchable;
2180
+ exports.ChannelNotFoundError = ChannelNotFoundError;
2181
+ exports.ChannelNotTextChannel = ChannelNotTextChannel;
1532
2182
  exports.Checkable = Checkable;
1533
2183
  exports.CommandMetadataKey = CommandMetadataKey;
2184
+ exports.CommandRegistry = CommandRegistry;
1534
2185
  exports.ContextMenuRoute = ContextMenuRoute;
2186
+ exports.CouldNotFindChannel = CouldNotFindChannel;
1535
2187
  exports.CustomError = CustomError;
1536
2188
  exports.DatabaseError = DatabaseError;
1537
2189
  exports.EffectMetadataKey = EffectMetadataKey;
1538
2190
  exports.EffectsEmitter = EffectsEmitter;
1539
2191
  exports.EffectsHandler = EffectsHandler;
1540
2192
  exports.EffectsRegistry = EffectsRegistry;
2193
+ exports.EmojiInjector = EmojiInjector;
1541
2194
  exports.EventCatchable = EventCatchable;
2195
+ exports.EventController = EventController;
1542
2196
  exports.EventHandler = EventHandler;
1543
2197
  exports.EventMetadataKey = EventMetadataKey;
2198
+ exports.EventMiddleware = EventMiddleware;
2199
+ exports.GenericError = GenericError;
2200
+ exports.HasDangerousPermissions = HasDangerousPermissions;
2201
+ exports.InteractionController = InteractionController;
1544
2202
  exports.InteractionHandler = InteractionHandler;
1545
2203
  exports.InteractionMetadataKey = InteractionMetadataKey;
1546
2204
  exports.InteractionMiddleware = InteractionMiddleware;
1547
2205
  exports.InteractionRoutes = InteractionRoutes;
1548
- exports.ModalComponent = ModalComponent;
2206
+ exports.Middleware = Middleware;
2207
+ exports.MiddlewareMetadataKey = MiddlewareMetadataKey;
2208
+ exports.MiddlewareType = MiddlewareType;
2209
+ exports.MissingPermissions = MissingPermissions;
1549
2210
  exports.ModalRoute = ModalRoute;
2211
+ exports.PERM_GROUPS = PERM_GROUPS;
2212
+ exports.PermissionNames = PermissionNames;
1550
2213
  exports.Pluggable = Pluggable;
1551
2214
  exports.Plugin = Plugin;
1552
2215
  exports.RegisterCommand = RegisterCommand;
1553
2216
  exports.RegisterEffect = RegisterEffect;
1554
2217
  exports.RegisterEvent = RegisterEvent;
2218
+ exports.RoleDoesNotExist = RoleDoesNotExist;
2219
+ exports.RoleHigherThanMe = RoleHigherThanMe;
1555
2220
  exports.RowComponent = RowComponent;
2221
+ exports.RowTypes = RowTypes;
1556
2222
  exports.Seedcord = Seedcord;
1557
2223
  exports.SelectMenuRoute = SelectMenuRoute;
1558
2224
  exports.SelectMenuType = SelectMenuType;
1559
2225
  exports.SlashRoute = SlashRoute;
2226
+ exports.UnhandledEvent = UnhandledEvent;
2227
+ exports.UserNotFound = UserNotFound;
2228
+ exports.UserNotInGuild = UserNotInGuild;
1560
2229
  exports.WebhookLog = WebhookLog;
2230
+ exports.attemptSendDM = attemptSendDM;
2231
+ exports.buildSlashRoute = buildSlashRoute;
2232
+ exports.checkBotPermissions = checkBotPermissions;
2233
+ exports.checkPermissions = checkPermissions;
2234
+ exports.extractErrorResponse = extractErrorResponse;
2235
+ exports.fetchGuildMember = fetchGuildMember;
2236
+ exports.fetchManyGuildMembers = fetchManyGuildMembers;
2237
+ exports.fetchManyUsers = fetchManyUsers;
2238
+ exports.fetchRole = fetchRole;
2239
+ exports.fetchText = fetchText;
2240
+ exports.fetchUser = fetchUser;
2241
+ exports.getBotRole = getBotRole;
2242
+ exports.hasPermsToAssign = hasPermsToAssign;
2243
+ exports.sendInText = sendInText;
1561
2244
  exports.throwCustomError = throwCustomError;
2245
+ exports.updateMemberRoles = updateMemberRoles;
1562
2246
  Object.keys(services).forEach(function (k) {
1563
2247
  if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
1564
2248
  enumerable: true,