seedcord 0.4.3 → 0.5.1

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