seedcord 0.1.0-alpha.1 → 0.1.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 +394 -235
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +822 -156
- package/dist/index.d.mts +822 -156
- package/dist/index.d.ts +822 -156
- package/dist/index.mjs +390 -224
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
package/dist/index.cjs
CHANGED
|
@@ -10,7 +10,6 @@ var winston = require('winston');
|
|
|
10
10
|
var crypto2 = require('crypto');
|
|
11
11
|
var events = require('events');
|
|
12
12
|
var http = require('http');
|
|
13
|
-
var mongoose2 = require('mongoose');
|
|
14
13
|
|
|
15
14
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
15
|
|
|
@@ -35,7 +34,6 @@ function _interopNamespace(e) {
|
|
|
35
34
|
var chalk6__default = /*#__PURE__*/_interopDefault(chalk6);
|
|
36
35
|
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
37
36
|
var crypto2__namespace = /*#__PURE__*/_interopNamespace(crypto2);
|
|
38
|
-
var mongoose2__default = /*#__PURE__*/_interopDefault(mongoose2);
|
|
39
37
|
|
|
40
38
|
var __defProp = Object.defineProperty;
|
|
41
39
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
@@ -63,9 +61,7 @@ var Globals = class extends envapt.Envapter {
|
|
|
63
61
|
// Unknown Exception Webhook URL
|
|
64
62
|
static unknownExceptionWebhookUrl;
|
|
65
63
|
// Variables
|
|
66
|
-
/**
|
|
67
|
-
* The default color of the bot's embeds. Can simply override by `Globals.botColor =`
|
|
68
|
-
*/
|
|
64
|
+
/** Default color for bot embeds - can be overridden by setting Globals.botColor */
|
|
69
65
|
static botColor = this.isProduction ? "#fe565a" : "#3fa045";
|
|
70
66
|
};
|
|
71
67
|
_ts_decorate([
|
|
@@ -111,9 +107,9 @@ var BuilderTypes = {
|
|
|
111
107
|
menu_mentionable: discord_js.MentionableSelectMenuBuilder,
|
|
112
108
|
menu_role: discord_js.RoleSelectMenuBuilder,
|
|
113
109
|
modal: discord_js.ModalBuilder,
|
|
110
|
+
context_menu: discord_js.ContextMenuCommandBuilder,
|
|
114
111
|
subcommand: discord_js.SlashCommandSubcommandBuilder,
|
|
115
|
-
group: discord_js.SlashCommandSubcommandGroupBuilder
|
|
116
|
-
context_menu: discord_js.ContextMenuCommandBuilder
|
|
112
|
+
group: discord_js.SlashCommandSubcommandGroupBuilder
|
|
117
113
|
};
|
|
118
114
|
var RowTypes = {
|
|
119
115
|
button: discord_js.ActionRowBuilder,
|
|
@@ -137,9 +133,12 @@ var BaseComponent = class BaseComponent2 {
|
|
|
137
133
|
this._component = new ComponentClass();
|
|
138
134
|
}
|
|
139
135
|
/**
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
136
|
+
* Gets the component instance for configuration
|
|
137
|
+
*
|
|
138
|
+
* Use this to access Discord.js builder methods like setTitle(), setDescription(), etc.
|
|
139
|
+
*
|
|
140
|
+
* Use this in your component classes to configure the builder
|
|
141
|
+
* @example this.instance.setTitle('My Modal')
|
|
143
142
|
*/
|
|
144
143
|
get instance() {
|
|
145
144
|
return this._component;
|
|
@@ -160,6 +159,16 @@ var BuilderComponent = class extends BaseComponent {
|
|
|
160
159
|
get component() {
|
|
161
160
|
return this.instance;
|
|
162
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* Builds a customId string for interactive components
|
|
164
|
+
*
|
|
165
|
+
* Creates customIds in the format "prefix:arg1-arg2-arg3" for buttons, modals, etc.
|
|
166
|
+
* Arguments are joined with hyphens and separated from prefix with a colon.
|
|
167
|
+
*
|
|
168
|
+
* @param prefix - The route prefix that handlers will match against
|
|
169
|
+
* @param args - Additional arguments to encode in the customId
|
|
170
|
+
* @returns Formatted customId string
|
|
171
|
+
*/
|
|
163
172
|
buildCustomId(prefix, ...args) {
|
|
164
173
|
if (args.length === 0) return prefix;
|
|
165
174
|
return `${prefix}:${args.join("-")}`;
|
|
@@ -181,6 +190,11 @@ var ModalRow = class ModalRow2 extends RowComponent {
|
|
|
181
190
|
static {
|
|
182
191
|
__name(this, "ModalRow");
|
|
183
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Creates a new modal action row with the specified component.
|
|
195
|
+
*
|
|
196
|
+
* @param component - The modal field component to wrap in an action row
|
|
197
|
+
*/
|
|
184
198
|
constructor(component) {
|
|
185
199
|
super("modal");
|
|
186
200
|
this.instance.addComponents(component);
|
|
@@ -202,6 +216,9 @@ var BaseErrorEmbed = class extends BuilderComponent {
|
|
|
202
216
|
static {
|
|
203
217
|
__name(this, "BaseErrorEmbed");
|
|
204
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* Creates a new error embed with default configuration.
|
|
221
|
+
*/
|
|
205
222
|
constructor() {
|
|
206
223
|
super("embed");
|
|
207
224
|
this.instance.setTitle("Cannot Proceed");
|
|
@@ -218,27 +235,32 @@ var CustomError = class extends Error {
|
|
|
218
235
|
super(message), this.message = message;
|
|
219
236
|
Error.captureStackTrace(this, this.constructor);
|
|
220
237
|
}
|
|
238
|
+
/**
|
|
239
|
+
* Whether this error should be emitted to logs
|
|
240
|
+
*
|
|
241
|
+
* Controls logging behavior. Errors with emit=true will always be logged,
|
|
242
|
+
* while emit=false errors may be suppressed in production.
|
|
243
|
+
*
|
|
244
|
+
* @returns True if the error should be logged
|
|
245
|
+
*/
|
|
221
246
|
get emit() {
|
|
222
247
|
return this._emit;
|
|
223
248
|
}
|
|
224
249
|
};
|
|
225
250
|
|
|
226
251
|
// src/bot/errors/Database.ts
|
|
227
|
-
var DatabaseConnectionFailure = class extends CustomError {
|
|
228
|
-
static {
|
|
229
|
-
__name(this, "DatabaseConnectionFailure");
|
|
230
|
-
}
|
|
231
|
-
constructor(message = "Failed to connect to the database.") {
|
|
232
|
-
super(message);
|
|
233
|
-
this.response.setDescription("Failed to connect to the database.");
|
|
234
|
-
}
|
|
235
|
-
};
|
|
236
252
|
var DatabaseError = class extends CustomError {
|
|
237
253
|
static {
|
|
238
254
|
__name(this, "DatabaseError");
|
|
239
255
|
}
|
|
240
256
|
uuid;
|
|
241
257
|
_emit = true;
|
|
258
|
+
/**
|
|
259
|
+
* Creates a new DatabaseError.
|
|
260
|
+
*
|
|
261
|
+
* @param message - The error message describing what went wrong
|
|
262
|
+
* @param uuid - A unique identifier for this specific error instance
|
|
263
|
+
*/
|
|
242
264
|
constructor(message, uuid) {
|
|
243
265
|
super(message), this.uuid = uuid;
|
|
244
266
|
this.name = "DatabaseError";
|
|
@@ -346,48 +368,125 @@ ${parts.join(" ")}`;
|
|
|
346
368
|
transports: transportsArray
|
|
347
369
|
});
|
|
348
370
|
}
|
|
371
|
+
/**
|
|
372
|
+
* Logs an error message with optional additional data.
|
|
373
|
+
*
|
|
374
|
+
* @param msg - The error message to log
|
|
375
|
+
* @param args - Additional data to include in the log entry
|
|
376
|
+
*/
|
|
349
377
|
error(msg, ...args) {
|
|
350
378
|
this.logger.error(msg, ...args);
|
|
351
379
|
}
|
|
380
|
+
/**
|
|
381
|
+
* Logs a warning message with optional additional data.
|
|
382
|
+
*
|
|
383
|
+
* @param msg - The warning message to log
|
|
384
|
+
* @param args - Additional data to include in the log entry
|
|
385
|
+
*/
|
|
352
386
|
warn(msg, ...args) {
|
|
353
387
|
this.logger.warn(msg, ...args);
|
|
354
388
|
}
|
|
389
|
+
/**
|
|
390
|
+
* Logs an informational message with optional additional data.
|
|
391
|
+
*
|
|
392
|
+
* @param msg - The informational message to log
|
|
393
|
+
* @param args - Additional data to include in the log entry
|
|
394
|
+
*/
|
|
355
395
|
info(msg, ...args) {
|
|
356
396
|
this.logger.info(msg, ...args);
|
|
357
397
|
}
|
|
398
|
+
/**
|
|
399
|
+
* Logs an HTTP-related message with optional additional data.
|
|
400
|
+
*
|
|
401
|
+
* @param msg - The HTTP message to log
|
|
402
|
+
* @param args - Additional data to include in the log entry
|
|
403
|
+
*/
|
|
358
404
|
http(msg, ...args) {
|
|
359
405
|
this.logger.http(msg, ...args);
|
|
360
406
|
}
|
|
407
|
+
/**
|
|
408
|
+
* Logs a verbose message with optional additional data.
|
|
409
|
+
*
|
|
410
|
+
* @param msg - The verbose message to log
|
|
411
|
+
* @param args - Additional data to include in the log entry
|
|
412
|
+
*/
|
|
361
413
|
verbose(msg, ...args) {
|
|
362
414
|
this.logger.verbose(msg, ...args);
|
|
363
415
|
}
|
|
416
|
+
/**
|
|
417
|
+
* Logs a debug message with optional additional data.
|
|
418
|
+
*
|
|
419
|
+
* @param msg - The debug message to log
|
|
420
|
+
* @param args - Additional data to include in the log entry
|
|
421
|
+
*/
|
|
364
422
|
debug(msg, ...args) {
|
|
365
423
|
this.logger.debug(msg, ...args);
|
|
366
424
|
}
|
|
425
|
+
/**
|
|
426
|
+
* Logs a silly/trace level message with optional additional data.
|
|
427
|
+
*
|
|
428
|
+
* @param msg - The silly message to log
|
|
429
|
+
* @param args - Additional data to include in the log entry
|
|
430
|
+
*/
|
|
367
431
|
silly(msg, ...args) {
|
|
368
432
|
this.logger.silly(msg, ...args);
|
|
369
433
|
}
|
|
370
|
-
|
|
434
|
+
/**
|
|
435
|
+
* Static method to log an error message with a specific prefix.
|
|
436
|
+
* Creates or retrieves a logger instance for the given prefix.
|
|
437
|
+
*
|
|
438
|
+
* @param prefix - The logger prefix/label to use
|
|
439
|
+
* @param msg - The error message to log
|
|
440
|
+
* @param args - Additional data to include in the log entry
|
|
441
|
+
*/
|
|
371
442
|
static Error(prefix, msg, ...args) {
|
|
372
443
|
const logger = this.instance(prefix);
|
|
373
444
|
logger.error(msg, ...args);
|
|
374
445
|
}
|
|
375
|
-
|
|
446
|
+
/**
|
|
447
|
+
* Static method to log an informational message with a specific prefix.
|
|
448
|
+
* Creates or retrieves a logger instance for the given prefix.
|
|
449
|
+
*
|
|
450
|
+
* @param prefix - The logger prefix/label to use
|
|
451
|
+
* @param msg - The informational message to log
|
|
452
|
+
* @param args - Additional data to include in the log entry
|
|
453
|
+
*/
|
|
376
454
|
static Info(prefix, msg, ...args) {
|
|
377
455
|
const logger = this.instance(prefix);
|
|
378
456
|
logger.info(msg, ...args);
|
|
379
457
|
}
|
|
380
|
-
|
|
458
|
+
/**
|
|
459
|
+
* Static method to log a warning message with a specific prefix.
|
|
460
|
+
* Creates or retrieves a logger instance for the given prefix.
|
|
461
|
+
*
|
|
462
|
+
* @param prefix - The logger prefix/label to use
|
|
463
|
+
* @param msg - The warning message to log
|
|
464
|
+
* @param args - Additional data to include in the log entry
|
|
465
|
+
*/
|
|
381
466
|
static Warn(prefix, msg, ...args) {
|
|
382
467
|
const logger = this.instance(prefix);
|
|
383
468
|
logger.warn(msg, ...args);
|
|
384
469
|
}
|
|
385
|
-
|
|
470
|
+
/**
|
|
471
|
+
* Static method to log a debug message with a specific prefix.
|
|
472
|
+
* Creates or retrieves a logger instance for the given prefix.
|
|
473
|
+
*
|
|
474
|
+
* @param prefix - The logger prefix/label to use
|
|
475
|
+
* @param msg - The debug message to log
|
|
476
|
+
* @param args - Additional data to include in the log entry
|
|
477
|
+
*/
|
|
386
478
|
static Debug(prefix, msg, ...args) {
|
|
387
479
|
const logger = this.instance(prefix);
|
|
388
480
|
logger.debug(msg, ...args);
|
|
389
481
|
}
|
|
390
|
-
|
|
482
|
+
/**
|
|
483
|
+
* Static method to log a silly/trace level message with a specific prefix.
|
|
484
|
+
* Creates or retrieves a logger instance for the given prefix.
|
|
485
|
+
*
|
|
486
|
+
* @param prefix - The logger prefix/label to use
|
|
487
|
+
* @param msg - The silly message to log
|
|
488
|
+
* @param args - Additional data to include in the log entry
|
|
489
|
+
*/
|
|
391
490
|
static Silly(prefix, msg, ...args) {
|
|
392
491
|
const logger = this.instance(prefix);
|
|
393
492
|
logger.silly(msg, ...args);
|
|
@@ -498,17 +597,17 @@ async function traverseDirectory(dir, callback) {
|
|
|
498
597
|
}
|
|
499
598
|
}
|
|
500
599
|
__name(traverseDirectory, "traverseDirectory");
|
|
501
|
-
function throwCustomError(error, message,
|
|
600
|
+
function throwCustomError(error, message, CustomError2) {
|
|
502
601
|
const uuid = crypto.randomUUID();
|
|
503
602
|
Logger.Error("Throwing Custom Error", error.name);
|
|
504
|
-
if (typeof
|
|
603
|
+
if (typeof CustomError2 === typeof DatabaseError) {
|
|
505
604
|
const errorMessage = error instanceof Error ? error.message : message;
|
|
506
|
-
throw new
|
|
605
|
+
throw new CustomError2(errorMessage, uuid);
|
|
507
606
|
} else {
|
|
508
607
|
if (error instanceof Error) {
|
|
509
|
-
throw new
|
|
608
|
+
throw new CustomError2(`${message}: ${error.message ? error.message : error.toString()}`);
|
|
510
609
|
} else {
|
|
511
|
-
throw new
|
|
610
|
+
throw new CustomError2(message);
|
|
512
611
|
}
|
|
513
612
|
}
|
|
514
613
|
}
|
|
@@ -647,14 +746,18 @@ var BaseHandler = class BaseHandler2 {
|
|
|
647
746
|
return this.event;
|
|
648
747
|
}
|
|
649
748
|
/**
|
|
650
|
-
*
|
|
651
|
-
*
|
|
749
|
+
* Gets arguments parsed from interaction customId
|
|
750
|
+
*
|
|
751
|
+
* Arguments are extracted from customId using ":" and "-" separators.
|
|
752
|
+
* For customId "accept:user123-guild456", returns ["user123", "guild456"]
|
|
652
753
|
*/
|
|
653
754
|
getArgs() {
|
|
654
755
|
return this.args;
|
|
655
756
|
}
|
|
656
757
|
/**
|
|
657
|
-
*
|
|
758
|
+
* Gets a specific argument by index from parsed customId
|
|
759
|
+
* @param index - Zero-based index of the argument to retrieve
|
|
760
|
+
* @returns The argument at the specified index, or undefined if not found
|
|
658
761
|
*/
|
|
659
762
|
getArg(index) {
|
|
660
763
|
return this.args[index];
|
|
@@ -680,6 +783,7 @@ var AutocompleteHandler = class extends BaseHandler {
|
|
|
680
783
|
static {
|
|
681
784
|
__name(this, "AutocompleteHandler");
|
|
682
785
|
}
|
|
786
|
+
/** The currently focused autocomplete option (Based on what you set in \@AutocompleteRoute) */
|
|
683
787
|
focused;
|
|
684
788
|
constructor(event, core, args) {
|
|
685
789
|
super(event, core, args);
|
|
@@ -886,11 +990,23 @@ var ErrorHandlingUtils = class {
|
|
|
886
990
|
__name(this, "ErrorHandlingUtils");
|
|
887
991
|
}
|
|
888
992
|
static logger = new Logger("Errors");
|
|
889
|
-
|
|
993
|
+
/**
|
|
994
|
+
* Processes an error and extracts the standardized response, if available.
|
|
995
|
+
*
|
|
996
|
+
* Handles different error types (CustomError, DatabaseError) with appropriate
|
|
997
|
+
* logging, side effects, and user-facing error messages.
|
|
998
|
+
*
|
|
999
|
+
* @param error - The error to process
|
|
1000
|
+
* @param core - The core framework instance
|
|
1001
|
+
* @param guild - The guild where the error occurred (if any)
|
|
1002
|
+
* @param user - The user who triggered the error (if any)
|
|
1003
|
+
* @returns Object containing UUID and formatted error response embed
|
|
1004
|
+
*/
|
|
1005
|
+
static extractErrorResponse(error, core, guild, user) {
|
|
890
1006
|
const uuid = crypto2__namespace.randomUUID();
|
|
891
1007
|
if (error instanceof CustomError) {
|
|
892
1008
|
if (error instanceof DatabaseError) {
|
|
893
|
-
core.
|
|
1009
|
+
core.effects.emit("unknownException", {
|
|
894
1010
|
uuid,
|
|
895
1011
|
error,
|
|
896
1012
|
guild,
|
|
@@ -906,7 +1022,7 @@ var ErrorHandlingUtils = class {
|
|
|
906
1022
|
};
|
|
907
1023
|
}
|
|
908
1024
|
this.logger.error(uuid, error);
|
|
909
|
-
core.
|
|
1025
|
+
core.effects.emit("unknownException", {
|
|
910
1026
|
uuid,
|
|
911
1027
|
error,
|
|
912
1028
|
guild,
|
|
@@ -945,7 +1061,7 @@ function Catchable(options) {
|
|
|
945
1061
|
if (!(error instanceof Error)) throw error;
|
|
946
1062
|
this.setErrored();
|
|
947
1063
|
if (log) console.error(error);
|
|
948
|
-
const { response } = ErrorHandlingUtils.
|
|
1064
|
+
const { response } = ErrorHandlingUtils.extractErrorResponse(error, this.core, interaction.guild, interaction.user);
|
|
949
1065
|
const res = {
|
|
950
1066
|
embeds: [
|
|
951
1067
|
response
|
|
@@ -1314,6 +1430,27 @@ var Pluggable = class _Pluggable {
|
|
|
1314
1430
|
this.isInitialized = true;
|
|
1315
1431
|
return this;
|
|
1316
1432
|
}
|
|
1433
|
+
/**
|
|
1434
|
+
* Attaches a plugin to this instance
|
|
1435
|
+
*
|
|
1436
|
+
* Plugins provide external functionality and are initialized during the specified startup phase.
|
|
1437
|
+
* The plugin instance becomes available as a property in `core` wherever it's available.
|
|
1438
|
+
*
|
|
1439
|
+
* Make sure to augment the {@link Core} interface with the plugin type to ensure TypeScript recognizes it and provides intellisense.
|
|
1440
|
+
*
|
|
1441
|
+
* @typeParam Key - The property name for accessing the plugin
|
|
1442
|
+
* @typeParam Ctor - The plugin constructor type
|
|
1443
|
+
* @param key - Property name to access the plugin instance
|
|
1444
|
+
* @param Plugin - Plugin constructor class
|
|
1445
|
+
* @param startupPhase - When during startup to initialize this plugin ({@link StartupPhase})
|
|
1446
|
+
* @param args - Additional arguments to pass to the plugin constructor
|
|
1447
|
+
* @returns This instance with the plugin attached as a typed property
|
|
1448
|
+
* @throws An {@link Error} When called after initialization or if key already exists
|
|
1449
|
+
* @example
|
|
1450
|
+
* ```typescript
|
|
1451
|
+
* seedcord.attach('db', Mongo, StartupPhase.Configuration, { uri: 'mongodb://...', dbName: 'seedcord' })
|
|
1452
|
+
* ```
|
|
1453
|
+
*/
|
|
1317
1454
|
attach(key, Plugin2, startupPhase, ...args) {
|
|
1318
1455
|
if (this.isInitialized) throw new Error("Cannot attach a plugin after initialization.");
|
|
1319
1456
|
if (this[key]) throw new Error(`Plugin with key "${key}" already exists.`);
|
|
@@ -1345,7 +1482,21 @@ var CoordinatedLifecycle = class {
|
|
|
1345
1482
|
this.phaseOrder.forEach((phase) => this.tasksMap.set(phase, []));
|
|
1346
1483
|
}
|
|
1347
1484
|
/**
|
|
1348
|
-
*
|
|
1485
|
+
* Adds a lifecycle task to a specific phase.
|
|
1486
|
+
*
|
|
1487
|
+
* Tasks are executed in phase order during lifecycle operations.
|
|
1488
|
+
* Each task has a timeout to prevent hanging operations.
|
|
1489
|
+
*
|
|
1490
|
+
* @param phase - The lifecycle phase to add the task to
|
|
1491
|
+
* @param taskName - Unique name for the task (used for logging and removal)
|
|
1492
|
+
* @param task - Async function to execute during the phase
|
|
1493
|
+
* @param timeoutMs - Maximum time allowed for task execution in milliseconds
|
|
1494
|
+
* @example
|
|
1495
|
+
* ```typescript
|
|
1496
|
+
* lifecycle.addTask(StartupPhase.Services, 'start-database', async () => {
|
|
1497
|
+
* await database.connect();
|
|
1498
|
+
* }, 10000);
|
|
1499
|
+
* ```
|
|
1349
1500
|
*/
|
|
1350
1501
|
addTask(phase, taskName, task, timeoutMs) {
|
|
1351
1502
|
if (!this.canAddTask()) return;
|
|
@@ -1359,7 +1510,11 @@ var CoordinatedLifecycle = class {
|
|
|
1359
1510
|
this.logger.debug(`${chalk6__default.default.italic("Added")} ${this.getTaskType()} task ${chalk6__default.default.bold.cyan(taskName)} to phase ${chalk6__default.default.bold.magenta(this.phaseEnum[phase])}`);
|
|
1360
1511
|
}
|
|
1361
1512
|
/**
|
|
1362
|
-
*
|
|
1513
|
+
* Removes a lifecycle task from a specific phase.
|
|
1514
|
+
*
|
|
1515
|
+
* @param phase - The lifecycle phase to remove the task from
|
|
1516
|
+
* @param taskName - Name of the task to remove
|
|
1517
|
+
* @returns True if the task was found and removed, false otherwise
|
|
1363
1518
|
*/
|
|
1364
1519
|
removeTask(phase, taskName) {
|
|
1365
1520
|
if (!this.canRemoveTask()) return false;
|
|
@@ -1493,19 +1648,40 @@ var CoordinatedShutdown = class extends CoordinatedLifecycle {
|
|
|
1493
1648
|
});
|
|
1494
1649
|
}
|
|
1495
1650
|
/**
|
|
1496
|
-
*
|
|
1651
|
+
* Adds a task to a specific shutdown phase with timeout.
|
|
1652
|
+
*
|
|
1653
|
+
* @param phase - The shutdown phase from {@link ShutdownPhase}
|
|
1654
|
+
* @param taskName - Unique identifier for the task
|
|
1655
|
+
* @param task - Async function to execute
|
|
1656
|
+
* @param timeoutMs - Task timeout in milliseconds (default: 5000)
|
|
1497
1657
|
*/
|
|
1498
1658
|
addTask(phase, taskName, task, timeoutMs = 5e3) {
|
|
1499
1659
|
super.addTask(phase, taskName, task, timeoutMs);
|
|
1500
1660
|
}
|
|
1501
1661
|
/**
|
|
1502
|
-
*
|
|
1662
|
+
* Removes a task from a specific shutdown phase.
|
|
1663
|
+
*
|
|
1664
|
+
* @param phase - The shutdown phase to remove from
|
|
1665
|
+
* @param taskName - Name of the task to remove
|
|
1666
|
+
* @returns True if task was found and removed
|
|
1503
1667
|
*/
|
|
1504
1668
|
removeTask(phase, taskName) {
|
|
1505
1669
|
return super.removeTask(phase, taskName);
|
|
1506
1670
|
}
|
|
1507
1671
|
/**
|
|
1508
|
-
*
|
|
1672
|
+
* Executes the coordinated shutdown sequence.
|
|
1673
|
+
*
|
|
1674
|
+
* Runs all registered tasks across shutdown phases in reverse order.
|
|
1675
|
+
* Tasks within each phase are executed in parallel for faster shutdown.
|
|
1676
|
+
* Process exits with the specified code when complete.
|
|
1677
|
+
*
|
|
1678
|
+
* @param exitCode - Process exit code (default: 0)
|
|
1679
|
+
* @returns Promise that resolves when shutdown is complete
|
|
1680
|
+
* @example
|
|
1681
|
+
* ```typescript
|
|
1682
|
+
* shutdown.addTask(ShutdownPhase.Services, 'database', () => db.disconnect(), 5000);
|
|
1683
|
+
* await shutdown.run(0); // Graceful shutdown
|
|
1684
|
+
* ```
|
|
1509
1685
|
*/
|
|
1510
1686
|
async run(exitCode = 0) {
|
|
1511
1687
|
if (this.isShuttingDown) {
|
|
@@ -1559,6 +1735,10 @@ var Bot = class extends Plugin {
|
|
|
1559
1735
|
events;
|
|
1560
1736
|
commands;
|
|
1561
1737
|
emojiInjector;
|
|
1738
|
+
/**
|
|
1739
|
+
* @param core - Seedcord core instance
|
|
1740
|
+
* @internal
|
|
1741
|
+
*/
|
|
1562
1742
|
constructor(core) {
|
|
1563
1743
|
super(core), this.core = core;
|
|
1564
1744
|
this._client = new discord_js.Client(core.config.bot.clientOptions);
|
|
@@ -1568,6 +1748,10 @@ var Bot = class extends Plugin {
|
|
|
1568
1748
|
this.emojiInjector = new EmojiInjector(this.core);
|
|
1569
1749
|
this.core.shutdown.addTask(ShutdownPhase.DiscordCleanup, "stop-bot", async () => await this.stop());
|
|
1570
1750
|
}
|
|
1751
|
+
/**
|
|
1752
|
+
* Initializes Discord client and all controllers
|
|
1753
|
+
* @internal
|
|
1754
|
+
*/
|
|
1571
1755
|
async init() {
|
|
1572
1756
|
if (this.isInitialized) {
|
|
1573
1757
|
return;
|
|
@@ -1580,15 +1764,25 @@ var Bot = class extends Plugin {
|
|
|
1580
1764
|
await this.commands.setCommands();
|
|
1581
1765
|
await this.emojiInjector.init();
|
|
1582
1766
|
}
|
|
1767
|
+
/**
|
|
1768
|
+
* Stops the bot and cleans up connections
|
|
1769
|
+
* @internal
|
|
1770
|
+
*/
|
|
1583
1771
|
async stop() {
|
|
1584
1772
|
this._client.removeAllListeners();
|
|
1585
1773
|
await this.logout();
|
|
1586
1774
|
}
|
|
1775
|
+
/**
|
|
1776
|
+
* Logs the bot into Discord using the configured token
|
|
1777
|
+
*/
|
|
1587
1778
|
async login() {
|
|
1588
1779
|
await this._client.login(Globals.botToken);
|
|
1589
1780
|
this.logger.info(`Logged in as ${chalk6__default.default.bold.magenta(this._client.user?.username)}!`);
|
|
1590
1781
|
return this;
|
|
1591
1782
|
}
|
|
1783
|
+
/**
|
|
1784
|
+
* Logs out and destroys the Discord client connection
|
|
1785
|
+
*/
|
|
1592
1786
|
async logout() {
|
|
1593
1787
|
await this._client.destroy();
|
|
1594
1788
|
this.logger.info(chalk6__default.default.bold.red("Logged out of Discord!"));
|
|
@@ -1598,22 +1792,28 @@ var Bot = class extends Plugin {
|
|
|
1598
1792
|
}
|
|
1599
1793
|
};
|
|
1600
1794
|
|
|
1601
|
-
// src/
|
|
1602
|
-
var
|
|
1603
|
-
function
|
|
1795
|
+
// src/effects/decorators/RegisterEffect.ts
|
|
1796
|
+
var EffectMetadataKey = Symbol("effect:metadata");
|
|
1797
|
+
function RegisterEffect(effect) {
|
|
1604
1798
|
return function(constructor) {
|
|
1605
|
-
Reflect.defineMetadata(
|
|
1799
|
+
Reflect.defineMetadata(EffectMetadataKey, effect, constructor);
|
|
1606
1800
|
};
|
|
1607
1801
|
}
|
|
1608
|
-
__name(
|
|
1802
|
+
__name(RegisterEffect, "RegisterEffect");
|
|
1609
1803
|
|
|
1610
|
-
// src/
|
|
1611
|
-
var
|
|
1804
|
+
// src/effects/interfaces/EffectsHandler.ts
|
|
1805
|
+
var EffectsHandler = class {
|
|
1612
1806
|
static {
|
|
1613
|
-
__name(this, "
|
|
1807
|
+
__name(this, "EffectsHandler");
|
|
1614
1808
|
}
|
|
1615
1809
|
data;
|
|
1616
1810
|
core;
|
|
1811
|
+
/**
|
|
1812
|
+
* Creates a new effects handler instance.
|
|
1813
|
+
*
|
|
1814
|
+
* @param data - The effect event data
|
|
1815
|
+
* @param core - The core framework instance
|
|
1816
|
+
*/
|
|
1617
1817
|
constructor(data, core) {
|
|
1618
1818
|
this.data = data;
|
|
1619
1819
|
this.core = core;
|
|
@@ -1622,8 +1822,8 @@ var HookHandler = class {
|
|
|
1622
1822
|
}
|
|
1623
1823
|
};
|
|
1624
1824
|
|
|
1625
|
-
// src/
|
|
1626
|
-
var WebhookLog = class extends
|
|
1825
|
+
// src/effects/interfaces/abstracts/WebhookLog.ts
|
|
1826
|
+
var WebhookLog = class extends EffectsHandler {
|
|
1627
1827
|
static {
|
|
1628
1828
|
__name(this, "WebhookLog");
|
|
1629
1829
|
}
|
|
@@ -1632,7 +1832,7 @@ var WebhookLog = class extends HookHandler {
|
|
|
1632
1832
|
}
|
|
1633
1833
|
};
|
|
1634
1834
|
|
|
1635
|
-
// src/
|
|
1835
|
+
// src/effects/default/UnknownException.ts
|
|
1636
1836
|
function _ts_decorate3(decorators, target, key, desc) {
|
|
1637
1837
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1638
1838
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -1658,7 +1858,7 @@ var UnknownException = class extends WebhookLog {
|
|
|
1658
1858
|
}
|
|
1659
1859
|
};
|
|
1660
1860
|
UnknownException = _ts_decorate3([
|
|
1661
|
-
|
|
1861
|
+
RegisterEffect("unknownException")
|
|
1662
1862
|
], UnknownException);
|
|
1663
1863
|
var UnhandledErrorEmbed = class UnhandledErrorEmbed2 extends BuilderComponent {
|
|
1664
1864
|
static {
|
|
@@ -1695,83 +1895,107 @@ var UnhandledErrorEmbed = class UnhandledErrorEmbed2 extends BuilderComponent {
|
|
|
1695
1895
|
]);
|
|
1696
1896
|
}
|
|
1697
1897
|
};
|
|
1698
|
-
var
|
|
1898
|
+
var EffectsEmitter = class {
|
|
1699
1899
|
static {
|
|
1700
|
-
__name(this, "
|
|
1900
|
+
__name(this, "EffectsEmitter");
|
|
1701
1901
|
}
|
|
1702
1902
|
emitter = new events.EventEmitter();
|
|
1903
|
+
/**
|
|
1904
|
+
* Registers a listener for the specified side effect.
|
|
1905
|
+
*
|
|
1906
|
+
* @typeParam KeyOfEffects - The side effect name type
|
|
1907
|
+
* @param event - The side effect name to listen for
|
|
1908
|
+
* @param listener - Function to call when the event is emitted
|
|
1909
|
+
* @returns This EffectsEmitter instance for chaining
|
|
1910
|
+
*/
|
|
1703
1911
|
on(event, listener) {
|
|
1704
1912
|
this.emitter.on(event, listener);
|
|
1705
1913
|
return this;
|
|
1706
1914
|
}
|
|
1915
|
+
/**
|
|
1916
|
+
* Registers a one-time listener for the specified side effect.
|
|
1917
|
+
*
|
|
1918
|
+
* @typeParam KeyOfEffects - The side effect name type
|
|
1919
|
+
* @param event - The side effect name to listen for once
|
|
1920
|
+
* @param listener - Function to call when the event is emitted
|
|
1921
|
+
* @returns This EffectsEmitter instance for chaining
|
|
1922
|
+
*/
|
|
1707
1923
|
once(event, listener) {
|
|
1708
1924
|
this.emitter.once(event, listener);
|
|
1709
1925
|
return this;
|
|
1710
1926
|
}
|
|
1927
|
+
/**
|
|
1928
|
+
* Emits a side effect with the provided data.
|
|
1929
|
+
*
|
|
1930
|
+
* @typeParam KeyOfEffects - The side effect name type
|
|
1931
|
+
* @param event - The side effect name to emit
|
|
1932
|
+
* @param data - The data to pass to registered listeners
|
|
1933
|
+
* @returns True if the event had listeners, false otherwise
|
|
1934
|
+
*/
|
|
1711
1935
|
emit(event, data) {
|
|
1712
1936
|
return this.emitter.emit(event, data);
|
|
1713
1937
|
}
|
|
1714
1938
|
};
|
|
1715
1939
|
|
|
1716
|
-
// src/
|
|
1717
|
-
var
|
|
1940
|
+
// src/effects/EffectsRegistry.ts
|
|
1941
|
+
var EffectsRegistry = class extends Plugin {
|
|
1718
1942
|
static {
|
|
1719
|
-
__name(this, "
|
|
1943
|
+
__name(this, "EffectsRegistry");
|
|
1720
1944
|
}
|
|
1721
1945
|
core;
|
|
1722
|
-
logger = new Logger("
|
|
1946
|
+
logger = new Logger("Effects");
|
|
1723
1947
|
isInitialized = false;
|
|
1724
|
-
|
|
1725
|
-
emitter = new
|
|
1948
|
+
effectsMap = /* @__PURE__ */ new Map();
|
|
1949
|
+
emitter = new EffectsEmitter();
|
|
1726
1950
|
constructor(core) {
|
|
1727
1951
|
super(core), this.core = core;
|
|
1728
1952
|
}
|
|
1729
1953
|
async init() {
|
|
1730
1954
|
if (this.isInitialized) return;
|
|
1731
1955
|
this.isInitialized = true;
|
|
1732
|
-
const
|
|
1733
|
-
this.logger.info(chalk6__default.default.bold(
|
|
1734
|
-
this.
|
|
1735
|
-
await this.
|
|
1736
|
-
this.
|
|
1737
|
-
const
|
|
1738
|
-
this.logger.info(`${chalk6__default.default.bold.green("Loaded")}: ${chalk6__default.default.bold.magenta(
|
|
1739
|
-
}
|
|
1740
|
-
async
|
|
1956
|
+
const effectsDir = this.core.config.effects.path;
|
|
1957
|
+
this.logger.info(chalk6__default.default.bold(effectsDir));
|
|
1958
|
+
this.registerEffect("unknownException", UnknownException);
|
|
1959
|
+
await this.loadEffects(effectsDir);
|
|
1960
|
+
this.attachEffects();
|
|
1961
|
+
const totalEffects = Array.from(this.effectsMap.values()).reduce((acc, handlers) => acc + handlers.length, 0);
|
|
1962
|
+
this.logger.info(`${chalk6__default.default.bold.green("Loaded")}: ${chalk6__default.default.bold.magenta(totalEffects)} side effects`);
|
|
1963
|
+
}
|
|
1964
|
+
async loadEffects(dir) {
|
|
1741
1965
|
await traverseDirectory(dir, (_fullPath, relativePath, imported) => {
|
|
1742
1966
|
for (const exportName of Object.keys(imported)) {
|
|
1743
1967
|
const val = imported[exportName];
|
|
1744
|
-
if (this.
|
|
1745
|
-
const
|
|
1746
|
-
if (
|
|
1747
|
-
this.
|
|
1968
|
+
if (this.isEffectHandler(val)) {
|
|
1969
|
+
const effectName = Reflect.getMetadata(EffectMetadataKey, val);
|
|
1970
|
+
if (effectName) {
|
|
1971
|
+
this.registerEffect(effectName, val);
|
|
1748
1972
|
this.logger.info(`${chalk6__default.default.italic("Registered")} ${chalk6__default.default.bold.yellow(val.name)} from ${chalk6__default.default.gray(relativePath)}`);
|
|
1749
1973
|
}
|
|
1750
1974
|
}
|
|
1751
1975
|
}
|
|
1752
1976
|
});
|
|
1753
1977
|
}
|
|
1754
|
-
|
|
1755
|
-
let handlers = this.
|
|
1978
|
+
registerEffect(effectName, handler) {
|
|
1979
|
+
let handlers = this.effectsMap.get(effectName);
|
|
1756
1980
|
if (!handlers) {
|
|
1757
1981
|
handlers = [];
|
|
1758
|
-
this.
|
|
1982
|
+
this.effectsMap.set(effectName, handlers);
|
|
1759
1983
|
}
|
|
1760
1984
|
handlers.push(handler);
|
|
1761
1985
|
}
|
|
1762
|
-
|
|
1986
|
+
isEffectHandler(obj) {
|
|
1763
1987
|
if (typeof obj !== "function") return false;
|
|
1764
|
-
return obj.prototype instanceof
|
|
1988
|
+
return obj.prototype instanceof EffectsHandler;
|
|
1765
1989
|
}
|
|
1766
|
-
|
|
1767
|
-
for (const [
|
|
1768
|
-
this.emitter.on(
|
|
1990
|
+
attachEffects() {
|
|
1991
|
+
for (const [effectName, handlerCtors] of this.effectsMap) {
|
|
1992
|
+
this.emitter.on(effectName, (data) => {
|
|
1769
1993
|
for (const HandlerCtor of handlerCtors) {
|
|
1770
1994
|
try {
|
|
1771
1995
|
const instance = new HandlerCtor(data, this.core);
|
|
1772
1996
|
void instance.execute();
|
|
1773
1997
|
} catch (err) {
|
|
1774
|
-
this.logger.error(`Error in
|
|
1998
|
+
this.logger.error(`Error in side effect ${String(effectName)} handler ${HandlerCtor.name}:`, err);
|
|
1775
1999
|
}
|
|
1776
2000
|
}
|
|
1777
2001
|
});
|
|
@@ -1827,6 +2051,11 @@ var HealthCheck = class extends Plugin {
|
|
|
1827
2051
|
});
|
|
1828
2052
|
});
|
|
1829
2053
|
}
|
|
2054
|
+
/**
|
|
2055
|
+
* Stops the health check server.
|
|
2056
|
+
*
|
|
2057
|
+
* @returns Promise that resolves when the server is closed
|
|
2058
|
+
*/
|
|
1830
2059
|
stop() {
|
|
1831
2060
|
return new Promise((shutdownResolve) => {
|
|
1832
2061
|
this.server?.close(() => {
|
|
@@ -1865,7 +2094,12 @@ var CoordinatedStartup = class extends CoordinatedLifecycle {
|
|
|
1865
2094
|
super("CoordinatedStartup", PHASE_ORDER2, StartupPhase);
|
|
1866
2095
|
}
|
|
1867
2096
|
/**
|
|
1868
|
-
*
|
|
2097
|
+
* Adds a task to a specific startup phase with timeout.
|
|
2098
|
+
*
|
|
2099
|
+
* @param phase - The startup phase from {@link StartupPhase}
|
|
2100
|
+
* @param taskName - Unique identifier for the task
|
|
2101
|
+
* @param task - Async function to execute
|
|
2102
|
+
* @param timeoutMs - Task timeout in milliseconds (default: 10000)
|
|
1869
2103
|
*/
|
|
1870
2104
|
addTask(phase, taskName, task, timeoutMs = 1e4) {
|
|
1871
2105
|
super.addTask(phase, taskName, task, timeoutMs);
|
|
@@ -1902,7 +2136,20 @@ var CoordinatedStartup = class extends CoordinatedLifecycle {
|
|
|
1902
2136
|
return results;
|
|
1903
2137
|
}
|
|
1904
2138
|
/**
|
|
1905
|
-
*
|
|
2139
|
+
* Executes the coordinated startup sequence.
|
|
2140
|
+
*
|
|
2141
|
+
* Runs all registered tasks across startup phases in the correct order.
|
|
2142
|
+
* Each phase completes before the next phase begins. Tasks within a phase
|
|
2143
|
+
* are executed sequentially to maintain predictable initialization.
|
|
2144
|
+
*
|
|
2145
|
+
* @returns Promise that resolves when startup is complete
|
|
2146
|
+
* @throws An {@link Error} If startup fails or is called multiple times
|
|
2147
|
+
* @example
|
|
2148
|
+
* ```typescript
|
|
2149
|
+
* const startup = new CoordinatedStartup();
|
|
2150
|
+
* startup.addTask(StartupPhase.Services, 'database', () => db.connect(), 10000);
|
|
2151
|
+
* await startup.run();
|
|
2152
|
+
* ```
|
|
1906
2153
|
*/
|
|
1907
2154
|
async run() {
|
|
1908
2155
|
if (this.hasStarted) {
|
|
@@ -1962,11 +2209,22 @@ var Seedcord = class _Seedcord extends Pluggable {
|
|
|
1962
2209
|
}
|
|
1963
2210
|
config;
|
|
1964
2211
|
static isInstantiated = false;
|
|
2212
|
+
/** @see {@link CoordinatedShutdown} */
|
|
1965
2213
|
shutdown;
|
|
2214
|
+
/** @see {@link CoordinatedStartup} */
|
|
1966
2215
|
startup;
|
|
1967
|
-
|
|
2216
|
+
/** @see {@link EffectsRegistry} */
|
|
2217
|
+
effects;
|
|
2218
|
+
/** @see {@link Bot} */
|
|
1968
2219
|
bot;
|
|
2220
|
+
/** @see {@link HealthCheck} */
|
|
1969
2221
|
healthCheck;
|
|
2222
|
+
/**
|
|
2223
|
+
* Creates a new Seedcord instance
|
|
2224
|
+
*
|
|
2225
|
+
* @param config - Bot configuration including paths and Discord client options
|
|
2226
|
+
* @throws An {@link Error} When attempting to create multiple instances (singleton)
|
|
2227
|
+
*/
|
|
1970
2228
|
constructor(config) {
|
|
1971
2229
|
const shutdown = new CoordinatedShutdown();
|
|
1972
2230
|
const startup = new CoordinatedStartup();
|
|
@@ -1977,16 +2235,20 @@ var Seedcord = class _Seedcord extends Pluggable {
|
|
|
1977
2235
|
throw new Error("Seedcord can only be instantiated once. Use the existing instance instead.");
|
|
1978
2236
|
}
|
|
1979
2237
|
_Seedcord.isInstantiated = true;
|
|
1980
|
-
this.
|
|
2238
|
+
this.effects = new EffectsRegistry(this);
|
|
1981
2239
|
this.bot = new Bot(this);
|
|
1982
2240
|
this.healthCheck = new HealthCheck(this);
|
|
1983
2241
|
this.registerStartupTasks();
|
|
1984
2242
|
}
|
|
2243
|
+
/**
|
|
2244
|
+
* Registers default startup tasks
|
|
2245
|
+
* @internal
|
|
2246
|
+
*/
|
|
1985
2247
|
registerStartupTasks() {
|
|
1986
|
-
this.startup.addTask(StartupPhase.Configuration, "
|
|
1987
|
-
this.
|
|
1988
|
-
await this.
|
|
1989
|
-
this.
|
|
2248
|
+
this.startup.addTask(StartupPhase.Configuration, "Effect Initialization", async () => {
|
|
2249
|
+
this.effects.logger.info(chalk6__default.default.bold("Initializing"));
|
|
2250
|
+
await this.effects.init();
|
|
2251
|
+
this.effects.logger.info(chalk6__default.default.bold("Initialized"));
|
|
1990
2252
|
});
|
|
1991
2253
|
this.startup.addTask(StartupPhase.Instantiation, "Bot Initialization", async () => {
|
|
1992
2254
|
this.bot.logger.info(chalk6__default.default.bold("Initializing"));
|
|
@@ -1999,6 +2261,11 @@ var Seedcord = class _Seedcord extends Pluggable {
|
|
|
1999
2261
|
this.healthCheck.logger.info(chalk6__default.default.bold("Initialized"));
|
|
2000
2262
|
});
|
|
2001
2263
|
}
|
|
2264
|
+
/**
|
|
2265
|
+
* Starts the bot and runs all initialization tasks
|
|
2266
|
+
*
|
|
2267
|
+
* @returns This Seedcord instance when fully initialized
|
|
2268
|
+
*/
|
|
2002
2269
|
async start() {
|
|
2003
2270
|
await super.init();
|
|
2004
2271
|
return this;
|
|
@@ -2028,11 +2295,11 @@ function EventCatchable(log) {
|
|
|
2028
2295
|
this.getEvent()
|
|
2029
2296
|
];
|
|
2030
2297
|
const msg = eventArgs.find((x) => x instanceof discord_js.Message);
|
|
2031
|
-
const
|
|
2298
|
+
const { response } = ErrorHandlingUtils.extractErrorResponse(err, this.core, msg?.guild ?? null, msg?.author ?? null);
|
|
2032
2299
|
if (!msg) return;
|
|
2033
2300
|
await msg.reply({
|
|
2034
2301
|
embeds: [
|
|
2035
|
-
|
|
2302
|
+
response
|
|
2036
2303
|
],
|
|
2037
2304
|
components: []
|
|
2038
2305
|
});
|
|
@@ -2051,19 +2318,32 @@ var CooldownManager = class {
|
|
|
2051
2318
|
Err;
|
|
2052
2319
|
msg;
|
|
2053
2320
|
map = /* @__PURE__ */ new Map();
|
|
2321
|
+
/**
|
|
2322
|
+
* Creates a new CooldownManager instance.
|
|
2323
|
+
*
|
|
2324
|
+
* @param opts - Configuration options for the cooldown behavior
|
|
2325
|
+
*/
|
|
2054
2326
|
constructor(opts = {}) {
|
|
2055
2327
|
this.window = opts.cooldown ?? 1e3;
|
|
2056
2328
|
this.Err = opts.err ?? Error;
|
|
2057
2329
|
this.msg = opts.message ?? "Cooldown active";
|
|
2058
2330
|
}
|
|
2059
|
-
/**
|
|
2331
|
+
/**
|
|
2332
|
+
* Records usage timestamp for a key without any cooldown checks.
|
|
2333
|
+
*
|
|
2334
|
+
* @param key - The unique identifier for the cooldown entry
|
|
2335
|
+
*/
|
|
2060
2336
|
set(key) {
|
|
2061
2337
|
this.map.set(key, Date.now());
|
|
2062
2338
|
}
|
|
2063
2339
|
/**
|
|
2064
|
-
*
|
|
2065
|
-
*
|
|
2066
|
-
* If
|
|
2340
|
+
* Verifies cooldown status for a key and updates timestamp if not active.
|
|
2341
|
+
*
|
|
2342
|
+
* If the cooldown is still active, throws the configured error.
|
|
2343
|
+
* If not active, updates the timestamp and returns successfully.
|
|
2344
|
+
*
|
|
2345
|
+
* @param key - The unique identifier to check cooldown for
|
|
2346
|
+
* @throws An {@link Err} When the cooldown is still active for the given key
|
|
2067
2347
|
*/
|
|
2068
2348
|
check(key) {
|
|
2069
2349
|
const now = Date.now();
|
|
@@ -2077,145 +2357,29 @@ var CooldownManager = class {
|
|
|
2077
2357
|
}
|
|
2078
2358
|
this.map.set(key, now);
|
|
2079
2359
|
}
|
|
2080
|
-
/**
|
|
2360
|
+
/**
|
|
2361
|
+
* Checks if a key is currently cooling down without updating timestamp.
|
|
2362
|
+
*
|
|
2363
|
+
* @param key - The unique identifier to check
|
|
2364
|
+
* @returns True if the key is still cooling down, false otherwise
|
|
2365
|
+
*/
|
|
2081
2366
|
isActive(key) {
|
|
2082
2367
|
const last = this.map.get(key);
|
|
2083
2368
|
return last !== void 0 && Date.now() - last < this.window;
|
|
2084
2369
|
}
|
|
2085
|
-
/** Remove a key from the map (useful for manual resets). */
|
|
2086
|
-
clear(key) {
|
|
2087
|
-
this.map.delete(key);
|
|
2088
|
-
}
|
|
2089
|
-
};
|
|
2090
|
-
var ModelMetadataKey = Symbol("db:model");
|
|
2091
|
-
function DatabaseModel(collection) {
|
|
2092
|
-
return (target, propertyKey) => {
|
|
2093
|
-
const schema = target[propertyKey];
|
|
2094
|
-
const name = String(collection);
|
|
2095
|
-
const model = mongoose2__default.default.model(name, schema);
|
|
2096
|
-
Reflect.defineMetadata(ModelMetadataKey, model, target);
|
|
2097
|
-
};
|
|
2098
|
-
}
|
|
2099
|
-
__name(DatabaseModel, "DatabaseModel");
|
|
2100
|
-
|
|
2101
|
-
// src/mongo/decorators/DatabaseService.ts
|
|
2102
|
-
var ServiceMetadataKey = Symbol("db:serviceKey");
|
|
2103
|
-
function DatabaseService(key) {
|
|
2104
|
-
return (ctor) => {
|
|
2105
|
-
Reflect.defineMetadata(ServiceMetadataKey, key, ctor);
|
|
2106
|
-
};
|
|
2107
|
-
}
|
|
2108
|
-
__name(DatabaseService, "DatabaseService");
|
|
2109
|
-
|
|
2110
|
-
// src/mongo/BaseService.ts
|
|
2111
|
-
var BaseService = class {
|
|
2112
|
-
static {
|
|
2113
|
-
__name(this, "BaseService");
|
|
2114
|
-
}
|
|
2115
|
-
db;
|
|
2116
|
-
core;
|
|
2117
|
-
model;
|
|
2118
|
-
constructor(db, core) {
|
|
2119
|
-
this.db = db;
|
|
2120
|
-
this.core = core;
|
|
2121
|
-
const ctor = this.constructor;
|
|
2122
|
-
const key = Reflect.getMetadata(ServiceMetadataKey, ctor);
|
|
2123
|
-
if (!key) throw new Error(`Missing @DatabaseService on ${ctor.name}`);
|
|
2124
|
-
const model = Reflect.getMetadata(ModelMetadataKey, ctor);
|
|
2125
|
-
if (!model) throw new Error(`Missing @DatabaseModel on ${ctor.name}`);
|
|
2126
|
-
this.model = model;
|
|
2127
|
-
db._register(key, this);
|
|
2128
|
-
}
|
|
2129
|
-
};
|
|
2130
|
-
|
|
2131
|
-
// src/mongo/Mongo.ts
|
|
2132
|
-
var Mongo = class extends Plugin {
|
|
2133
|
-
static {
|
|
2134
|
-
__name(this, "Mongo");
|
|
2135
|
-
}
|
|
2136
|
-
core;
|
|
2137
|
-
options;
|
|
2138
|
-
logger = new Logger("MongoDB");
|
|
2139
|
-
isInitialised = false;
|
|
2140
|
-
uri;
|
|
2141
2370
|
/**
|
|
2142
|
-
*
|
|
2143
|
-
*
|
|
2371
|
+
* Removes a key from the cooldown map.
|
|
2372
|
+
*
|
|
2373
|
+
* @param key - The unique identifier to remove (useful for manual resets)
|
|
2144
2374
|
*/
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
super(core), this.core = core, this.options = options;
|
|
2148
|
-
this.uri = options.uri;
|
|
2149
|
-
this.core.shutdown.addTask(ShutdownPhase.ExternalResources, "stop-database", async () => await this.stop());
|
|
2150
|
-
}
|
|
2151
|
-
async init() {
|
|
2152
|
-
if (this.isInitialised) return;
|
|
2153
|
-
this.isInitialised = true;
|
|
2154
|
-
await this.connect();
|
|
2155
|
-
await this.loadServices();
|
|
2156
|
-
}
|
|
2157
|
-
async stop() {
|
|
2158
|
-
await this.disconnect();
|
|
2159
|
-
}
|
|
2160
|
-
async connect() {
|
|
2161
|
-
await mongoose2__default.default.connect(this.uri, {
|
|
2162
|
-
dbName: this.options.dbName,
|
|
2163
|
-
...Globals.isProduction && {
|
|
2164
|
-
tls: true,
|
|
2165
|
-
ssl: true
|
|
2166
|
-
}
|
|
2167
|
-
}).then((i) => this.logger.info(`Connected to MongoDB: ${chalk6__default.default.bold.magenta(i.connection.name)}`)).catch((err) => throwCustomError(err, "Could not connect to MongoDB", DatabaseConnectionFailure));
|
|
2168
|
-
}
|
|
2169
|
-
async disconnect() {
|
|
2170
|
-
await mongoose2__default.default.disconnect().then(() => this.logger.info(chalk6__default.default.red.bold("Disconnected from MongoDB"))).catch((err) => this.logger.error(`Could not disconnect from MongoDB: ${err.message}`));
|
|
2171
|
-
}
|
|
2172
|
-
async loadServices() {
|
|
2173
|
-
const servicesDir = this.options.servicesDir;
|
|
2174
|
-
this.logger.info(chalk6__default.default.bold(servicesDir));
|
|
2175
|
-
await traverseDirectory(servicesDir, (_full, rel, mod) => {
|
|
2176
|
-
for (const Service of Object.values(mod)) {
|
|
2177
|
-
if (this.isServiceClass(Service)) {
|
|
2178
|
-
const instance = new Service(this, this.core);
|
|
2179
|
-
this.logger.info(`${chalk6__default.default.italic("Registered")} ${chalk6__default.default.bold.yellow(instance.constructor.name)} from ${chalk6__default.default.gray(rel)}`);
|
|
2180
|
-
}
|
|
2181
|
-
}
|
|
2182
|
-
});
|
|
2183
|
-
this.logger.info(`${chalk6__default.default.bold.green("Loaded")}: ${chalk6__default.default.magenta(Object.keys(this.services).length)} services`);
|
|
2184
|
-
}
|
|
2185
|
-
isServiceClass(obj) {
|
|
2186
|
-
return typeof obj === "function" && obj.prototype instanceof BaseService && Reflect.hasMetadata(ServiceMetadataKey, obj);
|
|
2187
|
-
}
|
|
2188
|
-
_register(key, instance) {
|
|
2189
|
-
this.services[key] = instance;
|
|
2375
|
+
clear(key) {
|
|
2376
|
+
this.map.delete(key);
|
|
2190
2377
|
}
|
|
2191
2378
|
};
|
|
2192
2379
|
|
|
2193
|
-
// src/mongo/decorators/DBCatchable.ts
|
|
2194
|
-
function DBCatchable(errorMessage) {
|
|
2195
|
-
return function(_target, _propertyKey, descriptor) {
|
|
2196
|
-
const originalMethod = descriptor.value;
|
|
2197
|
-
descriptor.value = async function(...args) {
|
|
2198
|
-
if (!originalMethod) {
|
|
2199
|
-
throw new Error("Method not found");
|
|
2200
|
-
}
|
|
2201
|
-
try {
|
|
2202
|
-
return await originalMethod.apply(this, args);
|
|
2203
|
-
} catch (error) {
|
|
2204
|
-
if (!(error instanceof CustomError)) {
|
|
2205
|
-
throwCustomError(error, errorMessage, DatabaseError);
|
|
2206
|
-
} else {
|
|
2207
|
-
throw error;
|
|
2208
|
-
}
|
|
2209
|
-
}
|
|
2210
|
-
};
|
|
2211
|
-
};
|
|
2212
|
-
}
|
|
2213
|
-
__name(DBCatchable, "DBCatchable");
|
|
2214
|
-
|
|
2215
2380
|
exports.AutocompleteHandler = AutocompleteHandler;
|
|
2216
2381
|
exports.AutocompleteRoute = AutocompleteRoute;
|
|
2217
2382
|
exports.BaseErrorEmbed = BaseErrorEmbed;
|
|
2218
|
-
exports.BaseService = BaseService;
|
|
2219
2383
|
exports.Bot = Bot;
|
|
2220
2384
|
exports.BuilderComponent = BuilderComponent;
|
|
2221
2385
|
exports.ButtonRoute = ButtonRoute;
|
|
@@ -2227,18 +2391,16 @@ exports.CooldownManager = CooldownManager;
|
|
|
2227
2391
|
exports.CoordinatedShutdown = CoordinatedShutdown;
|
|
2228
2392
|
exports.CoordinatedStartup = CoordinatedStartup;
|
|
2229
2393
|
exports.CustomError = CustomError;
|
|
2230
|
-
exports.
|
|
2231
|
-
exports.
|
|
2232
|
-
exports.
|
|
2394
|
+
exports.DatabaseError = DatabaseError;
|
|
2395
|
+
exports.EffectMetadataKey = EffectMetadataKey;
|
|
2396
|
+
exports.EffectsEmitter = EffectsEmitter;
|
|
2397
|
+
exports.EffectsHandler = EffectsHandler;
|
|
2398
|
+
exports.EffectsRegistry = EffectsRegistry;
|
|
2233
2399
|
exports.EventCatchable = EventCatchable;
|
|
2234
2400
|
exports.EventHandler = EventHandler;
|
|
2235
2401
|
exports.EventMetadataKey = EventMetadataKey;
|
|
2236
2402
|
exports.Globals = Globals;
|
|
2237
2403
|
exports.HealthCheck = HealthCheck;
|
|
2238
|
-
exports.HookController = HookController;
|
|
2239
|
-
exports.HookEmitter = HookEmitter;
|
|
2240
|
-
exports.HookHandler = HookHandler;
|
|
2241
|
-
exports.HookMetadataKey = HookMetadataKey;
|
|
2242
2404
|
exports.InteractionHandler = InteractionHandler;
|
|
2243
2405
|
exports.InteractionMetadataKey = InteractionMetadataKey;
|
|
2244
2406
|
exports.InteractionMiddleware = InteractionMiddleware;
|
|
@@ -2246,18 +2408,15 @@ exports.InteractionRoutes = InteractionRoutes;
|
|
|
2246
2408
|
exports.Logger = Logger;
|
|
2247
2409
|
exports.ModalComponent = ModalComponent;
|
|
2248
2410
|
exports.ModalRoute = ModalRoute;
|
|
2249
|
-
exports.ModelMetadataKey = ModelMetadataKey;
|
|
2250
|
-
exports.Mongo = Mongo;
|
|
2251
2411
|
exports.Pluggable = Pluggable;
|
|
2252
2412
|
exports.Plugin = Plugin;
|
|
2253
2413
|
exports.RegisterCommand = RegisterCommand;
|
|
2414
|
+
exports.RegisterEffect = RegisterEffect;
|
|
2254
2415
|
exports.RegisterEvent = RegisterEvent;
|
|
2255
|
-
exports.RegisterHook = RegisterHook;
|
|
2256
2416
|
exports.RowComponent = RowComponent;
|
|
2257
2417
|
exports.Seedcord = Seedcord;
|
|
2258
2418
|
exports.SelectMenuRoute = SelectMenuRoute;
|
|
2259
2419
|
exports.SelectMenuType = SelectMenuType;
|
|
2260
|
-
exports.ServiceMetadataKey = ServiceMetadataKey;
|
|
2261
2420
|
exports.ShutdownPhase = ShutdownPhase;
|
|
2262
2421
|
exports.SlashRoute = SlashRoute;
|
|
2263
2422
|
exports.StartupPhase = StartupPhase;
|