seedcord 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/index.cjs +251 -1126
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -558
- package/dist/index.d.mts +27 -558
- package/dist/index.d.ts +27 -558
- package/dist/index.mjs +226 -1090
- package/dist/index.mjs.map +1 -1
- package/package.json +14 -21
package/dist/index.cjs
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
require('reflect-metadata');
|
|
4
|
-
var
|
|
4
|
+
var services = require('@seedcord/services');
|
|
5
|
+
var chalk2 = require('chalk');
|
|
5
6
|
var discord_js = require('discord.js');
|
|
6
7
|
var envapt = require('envapt');
|
|
7
|
-
var
|
|
8
|
-
var path = require('path');
|
|
9
|
-
var winston = require('winston');
|
|
8
|
+
var utils = require('@seedcord/utils');
|
|
10
9
|
var crypto2 = require('crypto');
|
|
11
10
|
var events = require('events');
|
|
12
|
-
var http = require('http');
|
|
13
11
|
|
|
14
12
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
13
|
|
|
@@ -31,12 +29,74 @@ function _interopNamespace(e) {
|
|
|
31
29
|
return Object.freeze(n);
|
|
32
30
|
}
|
|
33
31
|
|
|
34
|
-
var
|
|
35
|
-
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
32
|
+
var chalk2__default = /*#__PURE__*/_interopDefault(chalk2);
|
|
36
33
|
var crypto2__namespace = /*#__PURE__*/_interopNamespace(crypto2);
|
|
37
34
|
|
|
38
35
|
var __defProp = Object.defineProperty;
|
|
39
36
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
37
|
+
var Plugin = class {
|
|
38
|
+
static {
|
|
39
|
+
__name(this, "Plugin");
|
|
40
|
+
}
|
|
41
|
+
pluggable;
|
|
42
|
+
constructor(pluggable) {
|
|
43
|
+
this.pluggable = pluggable;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var Pluggable = class _Pluggable {
|
|
47
|
+
static {
|
|
48
|
+
__name(this, "Pluggable");
|
|
49
|
+
}
|
|
50
|
+
isInitialized = false;
|
|
51
|
+
shutdown;
|
|
52
|
+
startup;
|
|
53
|
+
static PLUGIN_INIT_TIMEOUT_MS = 15e3;
|
|
54
|
+
constructor(shutdown, startup) {
|
|
55
|
+
this.shutdown = shutdown;
|
|
56
|
+
this.startup = startup;
|
|
57
|
+
}
|
|
58
|
+
async init() {
|
|
59
|
+
if (this.isInitialized) return this;
|
|
60
|
+
await this.startup.run();
|
|
61
|
+
this.isInitialized = true;
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
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
|
+
*/
|
|
85
|
+
attach(key, Plugin2, startupPhase, ...args) {
|
|
86
|
+
if (this.isInitialized) throw new Error("Cannot attach a plugin after initialization.");
|
|
87
|
+
if (this[key]) throw new Error(`Plugin with key "${key}" already exists.`);
|
|
88
|
+
const instance = new Plugin2(this, ...args);
|
|
89
|
+
const entry = {
|
|
90
|
+
[key]: instance
|
|
91
|
+
};
|
|
92
|
+
this.startup.addTask(startupPhase, `Plugin:${key}`, async () => {
|
|
93
|
+
instance.logger.info(chalk2__default.default.bold("Initializing"));
|
|
94
|
+
await instance.init();
|
|
95
|
+
instance.logger.info(chalk2__default.default.bold("Initialized"));
|
|
96
|
+
}, _Pluggable.PLUGIN_INIT_TIMEOUT_MS);
|
|
97
|
+
return Object.assign(this, entry);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
40
100
|
function _ts_decorate(decorators, target, key, desc) {
|
|
41
101
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
42
102
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -48,54 +108,6 @@ function _ts_metadata(k, v) {
|
|
|
48
108
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
49
109
|
}
|
|
50
110
|
__name(_ts_metadata, "_ts_metadata");
|
|
51
|
-
var Globals = class extends envapt.Envapter {
|
|
52
|
-
static {
|
|
53
|
-
__name(this, "Globals");
|
|
54
|
-
}
|
|
55
|
-
static botToken;
|
|
56
|
-
// Healthcheck
|
|
57
|
-
static healthCheckPort;
|
|
58
|
-
static healthCheckPath;
|
|
59
|
-
// Coordinated Shutdown
|
|
60
|
-
static shutdownIsEnabled;
|
|
61
|
-
// Unknown Exception Webhook URL
|
|
62
|
-
static unknownExceptionWebhookUrl;
|
|
63
|
-
// Variables
|
|
64
|
-
/** Default color for bot embeds - can be overridden by setting Globals.botColor */
|
|
65
|
-
static botColor = this.isProduction ? "#fe565a" : "#3fa045";
|
|
66
|
-
};
|
|
67
|
-
_ts_decorate([
|
|
68
|
-
envapt.Envapt("DISCORD_BOT_TOKEN", {
|
|
69
|
-
fallback: void 0
|
|
70
|
-
}),
|
|
71
|
-
_ts_metadata("design:type", String)
|
|
72
|
-
], Globals, "botToken", void 0);
|
|
73
|
-
_ts_decorate([
|
|
74
|
-
envapt.Envapt("HEALTH_CHECK_PORT", {
|
|
75
|
-
fallback: 6956
|
|
76
|
-
}),
|
|
77
|
-
_ts_metadata("design:type", Number)
|
|
78
|
-
], Globals, "healthCheckPort", void 0);
|
|
79
|
-
_ts_decorate([
|
|
80
|
-
envapt.Envapt("HEALTH_CHECK_PATH", {
|
|
81
|
-
fallback: "/healthcheck"
|
|
82
|
-
}),
|
|
83
|
-
_ts_metadata("design:type", String)
|
|
84
|
-
], Globals, "healthCheckPath", void 0);
|
|
85
|
-
_ts_decorate([
|
|
86
|
-
envapt.Envapt("SHUTDOWN_IS_ENABLED", {
|
|
87
|
-
fallback: false
|
|
88
|
-
}),
|
|
89
|
-
_ts_metadata("design:type", Boolean)
|
|
90
|
-
], Globals, "shutdownIsEnabled", void 0);
|
|
91
|
-
_ts_decorate([
|
|
92
|
-
envapt.Envapt("UNKNOWN_EXCEPTION_WEBHOOK_URL", {
|
|
93
|
-
fallback: void 0
|
|
94
|
-
}),
|
|
95
|
-
_ts_metadata("design:type", String)
|
|
96
|
-
], Globals, "unknownExceptionWebhookUrl", void 0);
|
|
97
|
-
|
|
98
|
-
// src/interfaces/Components.ts
|
|
99
111
|
var BuilderTypes = {
|
|
100
112
|
command: discord_js.SlashCommandBuilder,
|
|
101
113
|
embed: discord_js.EmbedBuilder,
|
|
@@ -109,7 +121,13 @@ var BuilderTypes = {
|
|
|
109
121
|
modal: discord_js.ModalBuilder,
|
|
110
122
|
context_menu: discord_js.ContextMenuCommandBuilder,
|
|
111
123
|
subcommand: discord_js.SlashCommandSubcommandBuilder,
|
|
112
|
-
group: discord_js.SlashCommandSubcommandGroupBuilder
|
|
124
|
+
group: discord_js.SlashCommandSubcommandGroupBuilder,
|
|
125
|
+
container: discord_js.ContainerBuilder,
|
|
126
|
+
text_display: discord_js.TextDisplayBuilder,
|
|
127
|
+
file: discord_js.FileBuilder,
|
|
128
|
+
media: discord_js.MediaGalleryBuilder,
|
|
129
|
+
section: discord_js.SectionBuilder,
|
|
130
|
+
separator: discord_js.SeparatorBuilder
|
|
113
131
|
};
|
|
114
132
|
var RowTypes = {
|
|
115
133
|
button: discord_js.ActionRowBuilder,
|
|
@@ -143,6 +161,20 @@ var BaseComponent = class BaseComponent2 {
|
|
|
143
161
|
get instance() {
|
|
144
162
|
return this._component;
|
|
145
163
|
}
|
|
164
|
+
/**
|
|
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
|
+
*/
|
|
174
|
+
buildCustomId(prefix, ...args) {
|
|
175
|
+
if (args.length === 0) return prefix;
|
|
176
|
+
return `${prefix}:${args.join("-")}`;
|
|
177
|
+
}
|
|
146
178
|
};
|
|
147
179
|
var BuilderComponent = class extends BaseComponent {
|
|
148
180
|
static {
|
|
@@ -151,7 +183,7 @@ var BuilderComponent = class extends BaseComponent {
|
|
|
151
183
|
constructor(type) {
|
|
152
184
|
const ComponentClass = BuilderTypes[type];
|
|
153
185
|
super(ComponentClass);
|
|
154
|
-
if (this.instance instanceof discord_js.EmbedBuilder) this.instance.setColor(
|
|
186
|
+
if (this.instance instanceof discord_js.EmbedBuilder) this.instance.setColor(this.botColor);
|
|
155
187
|
if (this.instance instanceof discord_js.SlashCommandBuilder || this.instance instanceof discord_js.ContextMenuCommandBuilder) {
|
|
156
188
|
this.instance.setContexts(discord_js.InteractionContextType.Guild);
|
|
157
189
|
}
|
|
@@ -159,21 +191,13 @@ var BuilderComponent = class extends BaseComponent {
|
|
|
159
191
|
get component() {
|
|
160
192
|
return this.instance;
|
|
161
193
|
}
|
|
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
|
-
*/
|
|
172
|
-
buildCustomId(prefix, ...args) {
|
|
173
|
-
if (args.length === 0) return prefix;
|
|
174
|
-
return `${prefix}:${args.join("-")}`;
|
|
175
|
-
}
|
|
176
194
|
};
|
|
195
|
+
_ts_decorate([
|
|
196
|
+
envapt.Envapt("DEFAULT_BOT_COLOR", {
|
|
197
|
+
fallback: "Default"
|
|
198
|
+
}),
|
|
199
|
+
_ts_metadata("design:type", typeof ColorResolvable === "undefined" ? Object : ColorResolvable)
|
|
200
|
+
], BuilderComponent.prototype, "botColor", void 0);
|
|
177
201
|
var RowComponent = class extends BaseComponent {
|
|
178
202
|
static {
|
|
179
203
|
__name(this, "RowComponent");
|
|
@@ -248,387 +272,6 @@ var CustomError = class extends Error {
|
|
|
248
272
|
}
|
|
249
273
|
};
|
|
250
274
|
|
|
251
|
-
// src/bot/errors/Database.ts
|
|
252
|
-
var DatabaseError = class extends CustomError {
|
|
253
|
-
static {
|
|
254
|
-
__name(this, "DatabaseError");
|
|
255
|
-
}
|
|
256
|
-
uuid;
|
|
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
|
-
*/
|
|
264
|
-
constructor(message, uuid) {
|
|
265
|
-
super(message), this.uuid = uuid;
|
|
266
|
-
this.name = "DatabaseError";
|
|
267
|
-
this.response.setTitle("Database Error").setDescription(`An error occurred while interacting with the database.
|
|
268
|
-
### UUID: \`${this.uuid}\``);
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
var Logger = class _Logger {
|
|
272
|
-
static {
|
|
273
|
-
__name(this, "Logger");
|
|
274
|
-
}
|
|
275
|
-
static instances = /* @__PURE__ */ new Map();
|
|
276
|
-
static instance(prefix) {
|
|
277
|
-
let instance = this.instances.get(prefix);
|
|
278
|
-
if (!instance) {
|
|
279
|
-
instance = new _Logger(prefix);
|
|
280
|
-
this.instances.set(prefix, instance);
|
|
281
|
-
}
|
|
282
|
-
return instance;
|
|
283
|
-
}
|
|
284
|
-
constructor(transportName) {
|
|
285
|
-
const consoleTransport = this.createConsoleTransport(transportName);
|
|
286
|
-
this.initializeLogger(consoleTransport);
|
|
287
|
-
}
|
|
288
|
-
getFormatCustomizations() {
|
|
289
|
-
const padding = 7;
|
|
290
|
-
return [
|
|
291
|
-
winston.format.errors({
|
|
292
|
-
stack: true
|
|
293
|
-
}),
|
|
294
|
-
winston.format.splat(),
|
|
295
|
-
winston.format.colorize({
|
|
296
|
-
level: true
|
|
297
|
-
}),
|
|
298
|
-
winston.format.timestamp({
|
|
299
|
-
format: "D MMM, hh:mm:ss a"
|
|
300
|
-
}),
|
|
301
|
-
winston.format.printf((info) => {
|
|
302
|
-
const ts = String(info.timestamp ?? "");
|
|
303
|
-
const lvl = String(info.level).padEnd(padding);
|
|
304
|
-
const lbl = String(info.label ?? "");
|
|
305
|
-
const msg = String(info.message ?? "");
|
|
306
|
-
const base = `${ts} [${lvl}]: ${lbl} - ${msg}`;
|
|
307
|
-
const splatSym = Symbol.for("splat");
|
|
308
|
-
const raw = info[splatSym];
|
|
309
|
-
const extras = Array.isArray(raw) ? raw : [];
|
|
310
|
-
const cleaned = extras.filter((x) => !(x instanceof Error)).filter((x) => {
|
|
311
|
-
if (!x) return false;
|
|
312
|
-
if (typeof x !== "object") return true;
|
|
313
|
-
return Object.keys(x).length > 0;
|
|
314
|
-
});
|
|
315
|
-
let rendered = base;
|
|
316
|
-
if (typeof info.stack === "string") {
|
|
317
|
-
rendered += `
|
|
318
|
-
${String(info.stack)}`;
|
|
319
|
-
}
|
|
320
|
-
if (cleaned.length) {
|
|
321
|
-
const parts = [];
|
|
322
|
-
for (const x of cleaned) {
|
|
323
|
-
if (typeof x === "string") parts.push(x);
|
|
324
|
-
else {
|
|
325
|
-
try {
|
|
326
|
-
parts.push(JSON.stringify(x, null, 2));
|
|
327
|
-
} catch {
|
|
328
|
-
parts.push(String(x));
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
rendered += `
|
|
333
|
-
${parts.join(" ")}`;
|
|
334
|
-
}
|
|
335
|
-
return rendered;
|
|
336
|
-
})
|
|
337
|
-
];
|
|
338
|
-
}
|
|
339
|
-
createConsoleTransport(transportName) {
|
|
340
|
-
return new winston.transports.Console({
|
|
341
|
-
format: winston.format.combine(winston.format.label({
|
|
342
|
-
label: transportName
|
|
343
|
-
}), ...this.getFormatCustomizations()),
|
|
344
|
-
level: Globals.isDevelopment ? "silly" : Globals.isStaging ? "debug" : "info"
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
initializeLogger(consoleTransport) {
|
|
348
|
-
const transportsArray = [
|
|
349
|
-
consoleTransport
|
|
350
|
-
];
|
|
351
|
-
if (Globals.isDevelopment) {
|
|
352
|
-
const maxSizeInMB = 10;
|
|
353
|
-
transportsArray.push(new winston.transports.File({
|
|
354
|
-
filename: "logs/application.log",
|
|
355
|
-
level: "debug",
|
|
356
|
-
format: winston.format.combine(winston.format.uncolorize(), winston.format.errors({
|
|
357
|
-
stack: true
|
|
358
|
-
}), winston.format.timestamp(), winston.format.json({
|
|
359
|
-
bigint: true,
|
|
360
|
-
space: 2
|
|
361
|
-
})),
|
|
362
|
-
maxsize: maxSizeInMB * 1024 * 1024,
|
|
363
|
-
maxFiles: 5,
|
|
364
|
-
tailable: true
|
|
365
|
-
}));
|
|
366
|
-
}
|
|
367
|
-
this.logger = winston.createLogger({
|
|
368
|
-
transports: transportsArray
|
|
369
|
-
});
|
|
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
|
-
*/
|
|
377
|
-
error(msg, ...args) {
|
|
378
|
-
this.logger.error(msg, ...args);
|
|
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
|
-
*/
|
|
386
|
-
warn(msg, ...args) {
|
|
387
|
-
this.logger.warn(msg, ...args);
|
|
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
|
-
*/
|
|
395
|
-
info(msg, ...args) {
|
|
396
|
-
this.logger.info(msg, ...args);
|
|
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
|
-
*/
|
|
404
|
-
http(msg, ...args) {
|
|
405
|
-
this.logger.http(msg, ...args);
|
|
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
|
-
*/
|
|
413
|
-
verbose(msg, ...args) {
|
|
414
|
-
this.logger.verbose(msg, ...args);
|
|
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
|
-
*/
|
|
422
|
-
debug(msg, ...args) {
|
|
423
|
-
this.logger.debug(msg, ...args);
|
|
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
|
-
*/
|
|
431
|
-
silly(msg, ...args) {
|
|
432
|
-
this.logger.silly(msg, ...args);
|
|
433
|
-
}
|
|
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
|
-
*/
|
|
442
|
-
static Error(prefix, msg, ...args) {
|
|
443
|
-
const logger = this.instance(prefix);
|
|
444
|
-
logger.error(msg, ...args);
|
|
445
|
-
}
|
|
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
|
-
*/
|
|
454
|
-
static Info(prefix, msg, ...args) {
|
|
455
|
-
const logger = this.instance(prefix);
|
|
456
|
-
logger.info(msg, ...args);
|
|
457
|
-
}
|
|
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
|
-
*/
|
|
466
|
-
static Warn(prefix, msg, ...args) {
|
|
467
|
-
const logger = this.instance(prefix);
|
|
468
|
-
logger.warn(msg, ...args);
|
|
469
|
-
}
|
|
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
|
-
*/
|
|
478
|
-
static Debug(prefix, msg, ...args) {
|
|
479
|
-
const logger = this.instance(prefix);
|
|
480
|
-
logger.debug(msg, ...args);
|
|
481
|
-
}
|
|
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
|
-
*/
|
|
490
|
-
static Silly(prefix, msg, ...args) {
|
|
491
|
-
const logger = this.instance(prefix);
|
|
492
|
-
logger.silly(msg, ...args);
|
|
493
|
-
}
|
|
494
|
-
};
|
|
495
|
-
|
|
496
|
-
// src/library/Helpers.ts
|
|
497
|
-
function numberFixer(num, decimalPlaces) {
|
|
498
|
-
const factor = Math.pow(10, decimalPlaces);
|
|
499
|
-
return Math.round((num + Number.EPSILON) * factor) / factor;
|
|
500
|
-
}
|
|
501
|
-
__name(numberFixer, "numberFixer");
|
|
502
|
-
function percentage(num1, num2) {
|
|
503
|
-
return Number((num1 / num2 * 100).toFixed(2));
|
|
504
|
-
}
|
|
505
|
-
__name(percentage, "percentage");
|
|
506
|
-
function generateAsciiTable(data) {
|
|
507
|
-
if (data.length === 0) return "";
|
|
508
|
-
const firstRow = data[0];
|
|
509
|
-
if (!firstRow || firstRow.length === 0) return "";
|
|
510
|
-
let table = "";
|
|
511
|
-
const columnWidths = [];
|
|
512
|
-
for (let i = 0; i < firstRow.length; i++) {
|
|
513
|
-
let maxWidth = 0;
|
|
514
|
-
for (const row of data) {
|
|
515
|
-
const cell = row[i];
|
|
516
|
-
if (cell !== void 0) maxWidth = Math.max(maxWidth, cell.length);
|
|
517
|
-
}
|
|
518
|
-
columnWidths.push(maxWidth);
|
|
519
|
-
}
|
|
520
|
-
const createLine = /* @__PURE__ */ __name((char, left, intersect, right) => {
|
|
521
|
-
let line = left;
|
|
522
|
-
columnWidths.forEach((width, index) => {
|
|
523
|
-
line += char.repeat(width + 2);
|
|
524
|
-
if (index < columnWidths.length - 1) line += intersect;
|
|
525
|
-
else line += right;
|
|
526
|
-
});
|
|
527
|
-
line += "\n";
|
|
528
|
-
return line;
|
|
529
|
-
}, "createLine");
|
|
530
|
-
table += createLine("\u2550", "\u2554", "\u2566", "\u2557");
|
|
531
|
-
data.forEach((row, rowIndex) => {
|
|
532
|
-
table += "\u2551";
|
|
533
|
-
row.forEach((cell, columnIndex) => {
|
|
534
|
-
const columnWidth = columnWidths[columnIndex];
|
|
535
|
-
if (columnWidth !== void 0) table += ` ${cell.padEnd(columnWidth)} \u2551`;
|
|
536
|
-
});
|
|
537
|
-
table += "\n";
|
|
538
|
-
if (rowIndex < data.length - 1) table += createLine("\u2500", "\u2560", "\u256C", "\u2563");
|
|
539
|
-
else table += createLine("\u2550", "\u255A", "\u2569", "\u255D");
|
|
540
|
-
});
|
|
541
|
-
return table;
|
|
542
|
-
}
|
|
543
|
-
__name(generateAsciiTable, "generateAsciiTable");
|
|
544
|
-
function formatWord(word) {
|
|
545
|
-
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
546
|
-
}
|
|
547
|
-
__name(formatWord, "formatWord");
|
|
548
|
-
function longestStringLength(arr) {
|
|
549
|
-
return Math.max(...arr.map((el) => el.toString().length));
|
|
550
|
-
}
|
|
551
|
-
__name(longestStringLength, "longestStringLength");
|
|
552
|
-
function currentTime() {
|
|
553
|
-
return Math.floor(Date.now() / 1e3);
|
|
554
|
-
}
|
|
555
|
-
__name(currentTime, "currentTime");
|
|
556
|
-
function ordinal(n) {
|
|
557
|
-
const s = [
|
|
558
|
-
"th",
|
|
559
|
-
"st",
|
|
560
|
-
"nd",
|
|
561
|
-
"rd"
|
|
562
|
-
];
|
|
563
|
-
const v = n % 100;
|
|
564
|
-
const index = (v - 20) % 10;
|
|
565
|
-
const suffix = s[index] ?? s[v] ?? s[0];
|
|
566
|
-
if (!suffix) return `${n}th`;
|
|
567
|
-
return `${n}${suffix}`;
|
|
568
|
-
}
|
|
569
|
-
__name(ordinal, "ordinal");
|
|
570
|
-
function prettyDifference(numBefore, numAfter) {
|
|
571
|
-
return (numAfter - numBefore > 0 ? `+${numAfter - numBefore}` : numAfter - numBefore).toString();
|
|
572
|
-
}
|
|
573
|
-
__name(prettyDifference, "prettyDifference");
|
|
574
|
-
function isTsOrJsFile(entry) {
|
|
575
|
-
return entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".js")) && !entry.name.endsWith(".d.ts") && !entry.name.endsWith(".map");
|
|
576
|
-
}
|
|
577
|
-
__name(isTsOrJsFile, "isTsOrJsFile");
|
|
578
|
-
async function traverseDirectory(dir, callback) {
|
|
579
|
-
let entries;
|
|
580
|
-
try {
|
|
581
|
-
entries = await promises.readdir(dir, {
|
|
582
|
-
withFileTypes: true
|
|
583
|
-
});
|
|
584
|
-
} catch {
|
|
585
|
-
Logger.Error("Failed to read directory", dir);
|
|
586
|
-
entries = [];
|
|
587
|
-
}
|
|
588
|
-
for (const entry of entries) {
|
|
589
|
-
const fullPath = path__namespace.join(dir, entry.name);
|
|
590
|
-
const relativePath = path__namespace.relative(process.cwd(), fullPath);
|
|
591
|
-
if (entry.isDirectory()) {
|
|
592
|
-
await traverseDirectory(fullPath, callback);
|
|
593
|
-
} else if (isTsOrJsFile(entry)) {
|
|
594
|
-
const imported = await import(fullPath);
|
|
595
|
-
await callback(fullPath, relativePath, imported);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
__name(traverseDirectory, "traverseDirectory");
|
|
600
|
-
function throwCustomError(error, message, CustomError2) {
|
|
601
|
-
const uuid = crypto.randomUUID();
|
|
602
|
-
Logger.Error("Throwing Custom Error", error.name);
|
|
603
|
-
if (typeof CustomError2 === typeof DatabaseError) {
|
|
604
|
-
const errorMessage = error instanceof Error ? error.message : message;
|
|
605
|
-
throw new CustomError2(errorMessage, uuid);
|
|
606
|
-
} else {
|
|
607
|
-
if (error instanceof Error) {
|
|
608
|
-
throw new CustomError2(`${message}: ${error.message ? error.message : error.toString()}`);
|
|
609
|
-
} else {
|
|
610
|
-
throw new CustomError2(message);
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
__name(throwCustomError, "throwCustomError");
|
|
615
|
-
function prettify(key) {
|
|
616
|
-
return key.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/_/g, " ").trim();
|
|
617
|
-
}
|
|
618
|
-
__name(prettify, "prettify");
|
|
619
|
-
function fyShuffle(items) {
|
|
620
|
-
const array = items.slice();
|
|
621
|
-
for (let i = array.length - 1; i > 0; i--) {
|
|
622
|
-
const j = Math.floor(Math.random() * (i + 1));
|
|
623
|
-
[array[i], array[j]] = [
|
|
624
|
-
array[j],
|
|
625
|
-
array[i]
|
|
626
|
-
];
|
|
627
|
-
}
|
|
628
|
-
return array;
|
|
629
|
-
}
|
|
630
|
-
__name(fyShuffle, "fyShuffle");
|
|
631
|
-
|
|
632
275
|
// src/bot/decorators/CommandRegisterable.ts
|
|
633
276
|
var CommandMetadataKey = Symbol("command:metadata");
|
|
634
277
|
function RegisterCommand(scope, guilds = []) {
|
|
@@ -650,7 +293,7 @@ var CommandRegistry = class {
|
|
|
650
293
|
__name(this, "CommandRegistry");
|
|
651
294
|
}
|
|
652
295
|
core;
|
|
653
|
-
logger = new Logger("Commands");
|
|
296
|
+
logger = new services.Logger("Commands");
|
|
654
297
|
isInitialised = false;
|
|
655
298
|
globalCommands = [];
|
|
656
299
|
guildCommands = /* @__PURE__ */ new Map();
|
|
@@ -660,14 +303,14 @@ var CommandRegistry = class {
|
|
|
660
303
|
async init() {
|
|
661
304
|
if (this.isInitialised) return;
|
|
662
305
|
this.isInitialised = true;
|
|
663
|
-
this.logger.info(
|
|
306
|
+
this.logger.info(chalk2__default.default.bold(this.core.config.bot.commands.path));
|
|
664
307
|
await this.loadCommands(this.core.config.bot.commands.path);
|
|
665
|
-
this.logger.info(`${
|
|
308
|
+
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`);
|
|
666
309
|
}
|
|
667
310
|
async loadCommands(dir) {
|
|
668
|
-
await traverseDirectory(dir, (_full, rel, mod) => {
|
|
311
|
+
await utils.traverseDirectory(dir, (_full, rel, mod) => {
|
|
669
312
|
for (const exported of Object.values(mod)) if (this.isCommandClass(exported)) this.registerCommand(exported, rel);
|
|
670
|
-
});
|
|
313
|
+
}, this.logger);
|
|
671
314
|
}
|
|
672
315
|
isCommandClass(obj) {
|
|
673
316
|
if (typeof obj !== "function") return false;
|
|
@@ -681,24 +324,24 @@ var CommandRegistry = class {
|
|
|
681
324
|
const commandType = comp instanceof discord_js.SlashCommandBuilder ? "slash command" : "context menu command";
|
|
682
325
|
if (meta.scope === "global") {
|
|
683
326
|
this.globalCommands.push(comp);
|
|
684
|
-
this.logger.info(`${
|
|
685
|
-
this.logger.info(` \u2192 Global ${commandType}: ${
|
|
327
|
+
this.logger.info(`${chalk2__default.default.italic("Registered")} ${chalk2__default.default.bold.yellow(ctor.name)} from ${chalk2__default.default.gray(rel)}`);
|
|
328
|
+
this.logger.info(` \u2192 Global ${commandType}: ${chalk2__default.default.bold.cyan(comp.name)}`);
|
|
686
329
|
} else {
|
|
687
330
|
for (const g of meta.guilds) {
|
|
688
331
|
const arr = this.guildCommands.get(g) ?? [];
|
|
689
332
|
arr.push(comp);
|
|
690
333
|
this.guildCommands.set(g, arr);
|
|
691
334
|
}
|
|
692
|
-
this.logger.info(`${
|
|
693
|
-
this.logger.info(` \u2192 Guild ${commandType}: ${
|
|
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 Guild ${commandType}: ${chalk2__default.default.bold.cyan(comp.name)} for ${chalk2__default.default.magenta.bold(meta.guilds.length)} guild(s)`);
|
|
694
337
|
}
|
|
695
338
|
}
|
|
696
339
|
async setCommands() {
|
|
697
340
|
if (this.globalCommands.length > 0) {
|
|
698
341
|
await this.core.bot.client.application?.commands.set(this.globalCommands);
|
|
699
342
|
const tag = this.globalCommands.length === 1 ? "command" : "commands";
|
|
700
|
-
this.logger.info(`${
|
|
701
|
-
this.logger.info(` \u2192 ${this.globalCommands.map((command) =>
|
|
343
|
+
this.logger.info(`${chalk2__default.default.bold.green("Configured")} ${chalk2__default.default.magenta.bold(this.globalCommands.length)} global ${tag}`);
|
|
344
|
+
this.logger.info(` \u2192 ${this.globalCommands.map((command) => chalk2__default.default.bold.cyan(command.name)).join(", ")}`);
|
|
702
345
|
}
|
|
703
346
|
for (const [guildId, commands] of this.guildCommands.entries()) {
|
|
704
347
|
const guild = this.core.bot.client.guilds.cache.get(guildId);
|
|
@@ -708,8 +351,8 @@ var CommandRegistry = class {
|
|
|
708
351
|
}
|
|
709
352
|
await guild.commands.set(commands);
|
|
710
353
|
const tag = commands.length === 1 ? "command" : "commands";
|
|
711
|
-
this.logger.info(`${
|
|
712
|
-
this.logger.info(` \u2192 ${commands.map((command) =>
|
|
354
|
+
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)}`);
|
|
355
|
+
this.logger.info(` \u2192 ${commands.map((command) => chalk2__default.default.bold.cyan(command.name)).join(", ")}`);
|
|
713
356
|
}
|
|
714
357
|
}
|
|
715
358
|
};
|
|
@@ -814,7 +457,7 @@ var EventController = class {
|
|
|
814
457
|
__name(this, "EventController");
|
|
815
458
|
}
|
|
816
459
|
core;
|
|
817
|
-
logger = new Logger("Events");
|
|
460
|
+
logger = new services.Logger("Events");
|
|
818
461
|
isInitialized = false;
|
|
819
462
|
eventMap = /* @__PURE__ */ new Map();
|
|
820
463
|
constructor(core) {
|
|
@@ -826,24 +469,24 @@ var EventController = class {
|
|
|
826
469
|
}
|
|
827
470
|
this.isInitialized = true;
|
|
828
471
|
const handlersDir = this.core.config.bot.events.path;
|
|
829
|
-
this.logger.info(
|
|
472
|
+
this.logger.info(chalk2__default.default.bold(handlersDir));
|
|
830
473
|
await this.loadHandlers(handlersDir);
|
|
831
474
|
this.attachToClient();
|
|
832
475
|
const loadedEventsArray = [];
|
|
833
476
|
this.eventMap.forEach((handlers, eventName) => {
|
|
834
|
-
loadedEventsArray.push(`${
|
|
477
|
+
loadedEventsArray.push(`${chalk2__default.default.magenta.bold(handlers.length)} ${eventName}`);
|
|
835
478
|
});
|
|
836
|
-
this.logger.info(`${
|
|
479
|
+
this.logger.info(`${chalk2__default.default.bold.green("Loaded")}: ${this.eventMap.size > 0 ? loadedEventsArray.join(", ") : "none"}`);
|
|
837
480
|
}
|
|
838
481
|
async loadHandlers(dir) {
|
|
839
|
-
await traverseDirectory(dir, (_fullPath, relativePath, imported) => {
|
|
482
|
+
await utils.traverseDirectory(dir, (_fullPath, relativePath, imported) => {
|
|
840
483
|
for (const val of Object.values(imported)) {
|
|
841
484
|
if (this.isEventHandlerClass(val)) {
|
|
842
485
|
this.registerHandler(val);
|
|
843
|
-
this.logger.info(`${
|
|
486
|
+
this.logger.info(`${chalk2__default.default.italic("Registered")} ${chalk2__default.default.bold.yellow(val.name)} from ${chalk2__default.default.gray(relativePath)}`);
|
|
844
487
|
}
|
|
845
488
|
}
|
|
846
|
-
});
|
|
489
|
+
}, this.logger);
|
|
847
490
|
}
|
|
848
491
|
isEventHandlerClass(obj) {
|
|
849
492
|
if (typeof obj !== "function") return false;
|
|
@@ -861,7 +504,7 @@ var EventController = class {
|
|
|
861
504
|
}
|
|
862
505
|
attachToClient() {
|
|
863
506
|
for (const [eventName] of this.eventMap) {
|
|
864
|
-
this.logger.debug(`Attaching ${
|
|
507
|
+
this.logger.debug(`Attaching ${chalk2__default.default.bold.green(eventName)} to ${chalk2__default.default.bold.yellow(this.core.bot.client.user?.username)}`);
|
|
865
508
|
this.core.bot.client.on(eventName, (...args) => {
|
|
866
509
|
void (async () => {
|
|
867
510
|
await this.processEvent(eventName, args);
|
|
@@ -874,7 +517,7 @@ var EventController = class {
|
|
|
874
517
|
if (!handlerCtors || handlerCtors.length === 0) return;
|
|
875
518
|
for (const HandlerCtor of handlerCtors) {
|
|
876
519
|
try {
|
|
877
|
-
this.logger.debug(`Processing ${
|
|
520
|
+
this.logger.debug(`Processing ${chalk2__default.default.bold.green(eventName)} with ${chalk2__default.default.gray(HandlerCtor.name)}`);
|
|
878
521
|
const handler = new HandlerCtor(args, this.core);
|
|
879
522
|
if (handler.hasChecks()) {
|
|
880
523
|
await handler.runChecks();
|
|
@@ -985,11 +628,34 @@ function storeMetadata(symbol, routes, constructor) {
|
|
|
985
628
|
Reflect.defineMetadata(InteractionMetadataKey, true, constructor);
|
|
986
629
|
}
|
|
987
630
|
__name(storeMetadata, "storeMetadata");
|
|
631
|
+
|
|
632
|
+
// src/bot/errors/Database.ts
|
|
633
|
+
var DatabaseError = class extends CustomError {
|
|
634
|
+
static {
|
|
635
|
+
__name(this, "DatabaseError");
|
|
636
|
+
}
|
|
637
|
+
uuid;
|
|
638
|
+
_emit = true;
|
|
639
|
+
/**
|
|
640
|
+
* Creates a new DatabaseError.
|
|
641
|
+
*
|
|
642
|
+
* @param message - The error message describing what went wrong
|
|
643
|
+
* @param uuid - A unique identifier for this specific error instance
|
|
644
|
+
*/
|
|
645
|
+
constructor(message, uuid) {
|
|
646
|
+
super(message), this.uuid = uuid;
|
|
647
|
+
this.name = "DatabaseError";
|
|
648
|
+
this.response.setTitle("Database Error").setDescription(`An error occurred while interacting with the database.
|
|
649
|
+
### UUID: \`${this.uuid}\``);
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
// src/bot/utilities/ErrorHandlingUtils.ts
|
|
988
654
|
var ErrorHandlingUtils = class {
|
|
989
655
|
static {
|
|
990
656
|
__name(this, "ErrorHandlingUtils");
|
|
991
657
|
}
|
|
992
|
-
static logger = new Logger("Errors");
|
|
658
|
+
static logger = new services.Logger("Errors");
|
|
993
659
|
/**
|
|
994
660
|
* Processes an error and extracts the standardized response, if available.
|
|
995
661
|
*
|
|
@@ -1130,7 +796,7 @@ var InteractionController = class {
|
|
|
1130
796
|
__name(this, "InteractionController");
|
|
1131
797
|
}
|
|
1132
798
|
core;
|
|
1133
|
-
logger = new Logger("Interactions");
|
|
799
|
+
logger = new services.Logger("Interactions");
|
|
1134
800
|
isInitialized = false;
|
|
1135
801
|
slashMap = /* @__PURE__ */ new Map();
|
|
1136
802
|
buttonMap = /* @__PURE__ */ new Map();
|
|
@@ -1155,31 +821,31 @@ var InteractionController = class {
|
|
|
1155
821
|
if (this.isInitialized) return;
|
|
1156
822
|
this.isInitialized = true;
|
|
1157
823
|
const handlersDir = this.core.config.bot.interactions.path;
|
|
1158
|
-
this.logger.info(
|
|
824
|
+
this.logger.info(chalk2__default.default.bold(handlersDir));
|
|
1159
825
|
await this.loadHandlers(handlersDir);
|
|
1160
826
|
this.attachToClient();
|
|
1161
|
-
this.logger.info(`${
|
|
1162
|
-
this.logger.info(`\u2192 ${
|
|
1163
|
-
this.logger.info(`\u2192 ${
|
|
1164
|
-
this.logger.info(`\u2192 ${
|
|
1165
|
-
this.logger.info(`\u2192 ${
|
|
1166
|
-
this.logger.info(`\u2192 ${
|
|
1167
|
-
this.logger.info(`\u2192 ${
|
|
1168
|
-
this.logger.info(`\u2192 ${
|
|
1169
|
-
this.logger.info(`\u2192 ${
|
|
1170
|
-
this.logger.info(`\u2192 ${
|
|
1171
|
-
this.logger.info(`\u2192 ${
|
|
1172
|
-
this.logger.info(`\u2192 ${
|
|
827
|
+
this.logger.info(`${chalk2__default.default.bold.green("Loaded interaction handlers:")}`);
|
|
828
|
+
this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.slashMap.size)} slash commands`);
|
|
829
|
+
this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.buttonMap.size)} buttons`);
|
|
830
|
+
this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.modalMap.size)} modals`);
|
|
831
|
+
this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.stringSelectMap.size)} string selects`);
|
|
832
|
+
this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.userSelectMap.size)} user selects`);
|
|
833
|
+
this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.roleSelectMap.size)} role selects`);
|
|
834
|
+
this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.channelSelectMap.size)} channel selects`);
|
|
835
|
+
this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.mentionableSelectMap.size)} mentionable selects`);
|
|
836
|
+
this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.messageContextMenuMap.size)} message context menus`);
|
|
837
|
+
this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.userContextMenuMap.size)} user context menus`);
|
|
838
|
+
this.logger.info(`\u2192 ${chalk2__default.default.magenta.bold(this.autocompleteMap.size)} autocomplete`);
|
|
1173
839
|
}
|
|
1174
840
|
async loadHandlers(dir) {
|
|
1175
|
-
await traverseDirectory(dir, (_fullPath, relativePath, imported) => {
|
|
841
|
+
await utils.traverseDirectory(dir, (_fullPath, relativePath, imported) => {
|
|
1176
842
|
for (const val of Object.values(imported)) {
|
|
1177
843
|
if (this.isHandlerClass(val)) {
|
|
1178
844
|
this.registerHandler(val);
|
|
1179
|
-
this.logger.info(`${
|
|
845
|
+
this.logger.info(`${chalk2__default.default.italic("Registered")} ${chalk2__default.default.bold.yellow(val.name)} from ${chalk2__default.default.gray(relativePath)}`);
|
|
1180
846
|
}
|
|
1181
847
|
}
|
|
1182
|
-
});
|
|
848
|
+
}, this.logger);
|
|
1183
849
|
}
|
|
1184
850
|
isHandlerClass(obj) {
|
|
1185
851
|
if (typeof obj !== "function") return false;
|
|
@@ -1245,7 +911,7 @@ var InteractionController = class {
|
|
|
1245
911
|
attachToClient() {
|
|
1246
912
|
this.core.bot.client.on(discord_js.Events.InteractionCreate, (interaction) => {
|
|
1247
913
|
this.handleInteraction(interaction).catch((err) => {
|
|
1248
|
-
this.logger.error(`[${
|
|
914
|
+
this.logger.error(`[${chalk2__default.default.bold.red("UNHANDLED ERROR AT ROOT")}] ${err.name}`, err.stack);
|
|
1249
915
|
});
|
|
1250
916
|
});
|
|
1251
917
|
}
|
|
@@ -1274,10 +940,10 @@ var InteractionController = class {
|
|
|
1274
940
|
}
|
|
1275
941
|
let HandlerCtor = getHandler(key);
|
|
1276
942
|
if (!HandlerCtor) {
|
|
1277
|
-
this.logger.warn(`No handler found for key ${
|
|
943
|
+
this.logger.warn(`No handler found for key ${chalk2__default.default.bold.cyan(key)}. Falling back to UnhandledEvent.`);
|
|
1278
944
|
HandlerCtor = UnhandledEvent;
|
|
1279
945
|
}
|
|
1280
|
-
this.logger.debug(`Processing ${
|
|
946
|
+
this.logger.debug(`Processing ${chalk2__default.default.bold.green(key)} with ${chalk2__default.default.gray(HandlerCtor.name)}`);
|
|
1281
947
|
const handler = new HandlerCtor(interaction, this.core, args);
|
|
1282
948
|
if (handler.hasChecks()) await handler.runChecks();
|
|
1283
949
|
if (handler.shouldBreak()) return;
|
|
@@ -1381,13 +1047,13 @@ var EmojiInjector = class {
|
|
|
1381
1047
|
__name(this, "EmojiInjector");
|
|
1382
1048
|
}
|
|
1383
1049
|
core;
|
|
1384
|
-
logger = new Logger("Emojis");
|
|
1050
|
+
logger = new services.Logger("Emojis");
|
|
1385
1051
|
constructor(core) {
|
|
1386
1052
|
this.core = core;
|
|
1387
1053
|
}
|
|
1388
1054
|
async init() {
|
|
1389
1055
|
if (!this.core.config.bot.emojis || Object.keys(this.core.config.bot.emojis).length === 0) {
|
|
1390
|
-
this.logger.info(`${
|
|
1056
|
+
this.logger.info(`${chalk2__default.default.bold.green("Loaded")}: ${chalk2__default.default.magenta.bold("0")} emojis`);
|
|
1391
1057
|
return;
|
|
1392
1058
|
}
|
|
1393
1059
|
const configEmojis = this.core.config.bot.emojis;
|
|
@@ -1398,337 +1064,31 @@ var EmojiInjector = class {
|
|
|
1398
1064
|
if (emoji) {
|
|
1399
1065
|
configEmojis[key] = `<${emoji.identifier}>`;
|
|
1400
1066
|
foundCount++;
|
|
1067
|
+
this.logger.debug(`${chalk2__default.default.bold.green("Found")}: ${chalk2__default.default.magenta.bold(emojiName)} (${emoji.id})`);
|
|
1401
1068
|
}
|
|
1402
1069
|
});
|
|
1403
|
-
this.logger.info(`${
|
|
1404
|
-
}
|
|
1405
|
-
};
|
|
1406
|
-
var Plugin = class {
|
|
1407
|
-
static {
|
|
1408
|
-
__name(this, "Plugin");
|
|
1409
|
-
}
|
|
1410
|
-
pluggable;
|
|
1411
|
-
constructor(pluggable) {
|
|
1412
|
-
this.pluggable = pluggable;
|
|
1413
|
-
}
|
|
1414
|
-
};
|
|
1415
|
-
var Pluggable = class _Pluggable {
|
|
1416
|
-
static {
|
|
1417
|
-
__name(this, "Pluggable");
|
|
1418
|
-
}
|
|
1419
|
-
isInitialized = false;
|
|
1420
|
-
shutdown;
|
|
1421
|
-
startup;
|
|
1422
|
-
static PLUGIN_INIT_TIMEOUT_MS = 15e3;
|
|
1423
|
-
constructor(shutdown, startup) {
|
|
1424
|
-
this.shutdown = shutdown;
|
|
1425
|
-
this.startup = startup;
|
|
1426
|
-
}
|
|
1427
|
-
async init() {
|
|
1428
|
-
if (this.isInitialized) return this;
|
|
1429
|
-
await this.startup.run();
|
|
1430
|
-
this.isInitialized = true;
|
|
1431
|
-
return this;
|
|
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
|
-
*/
|
|
1454
|
-
attach(key, Plugin2, startupPhase, ...args) {
|
|
1455
|
-
if (this.isInitialized) throw new Error("Cannot attach a plugin after initialization.");
|
|
1456
|
-
if (this[key]) throw new Error(`Plugin with key "${key}" already exists.`);
|
|
1457
|
-
const instance = new Plugin2(this, ...args);
|
|
1458
|
-
const entry = {
|
|
1459
|
-
[key]: instance
|
|
1460
|
-
};
|
|
1461
|
-
this.startup.addTask(startupPhase, `Plugin:${key}`, async () => {
|
|
1462
|
-
instance.logger.info(chalk6__default.default.bold("Initializing"));
|
|
1463
|
-
await instance.init();
|
|
1464
|
-
instance.logger.info(chalk6__default.default.bold("Initialized"));
|
|
1465
|
-
}, _Pluggable.PLUGIN_INIT_TIMEOUT_MS);
|
|
1466
|
-
return Object.assign(this, entry);
|
|
1467
|
-
}
|
|
1468
|
-
};
|
|
1469
|
-
var CoordinatedLifecycle = class {
|
|
1470
|
-
static {
|
|
1471
|
-
__name(this, "CoordinatedLifecycle");
|
|
1472
|
-
}
|
|
1473
|
-
phaseOrder;
|
|
1474
|
-
phaseEnum;
|
|
1475
|
-
logger;
|
|
1476
|
-
events = new events.EventEmitter();
|
|
1477
|
-
tasksMap = /* @__PURE__ */ new Map();
|
|
1478
|
-
constructor(loggerName, phaseOrder, phaseEnum) {
|
|
1479
|
-
this.phaseOrder = phaseOrder;
|
|
1480
|
-
this.phaseEnum = phaseEnum;
|
|
1481
|
-
this.logger = new Logger(loggerName);
|
|
1482
|
-
this.phaseOrder.forEach((phase) => this.tasksMap.set(phase, []));
|
|
1483
|
-
}
|
|
1484
|
-
/**
|
|
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
|
-
* ```
|
|
1500
|
-
*/
|
|
1501
|
-
addTask(phase, taskName, task, timeoutMs) {
|
|
1502
|
-
if (!this.canAddTask()) return;
|
|
1503
|
-
const tasks = this.tasksMap.get(phase);
|
|
1504
|
-
if (!tasks) throw new Error(`Unknown phase: ${phase}`);
|
|
1505
|
-
tasks.push({
|
|
1506
|
-
name: taskName,
|
|
1507
|
-
task,
|
|
1508
|
-
timeout: timeoutMs
|
|
1509
|
-
});
|
|
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])}`);
|
|
1511
|
-
}
|
|
1512
|
-
/**
|
|
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
|
|
1518
|
-
*/
|
|
1519
|
-
removeTask(phase, taskName) {
|
|
1520
|
-
if (!this.canRemoveTask()) return false;
|
|
1521
|
-
const tasks = this.tasksMap.get(phase);
|
|
1522
|
-
if (!tasks) return false;
|
|
1523
|
-
const initialLength = tasks.length;
|
|
1524
|
-
const filteredTasks = tasks.filter((task) => task.name !== taskName);
|
|
1525
|
-
this.tasksMap.set(phase, filteredTasks);
|
|
1526
|
-
const removed = initialLength !== filteredTasks.length;
|
|
1527
|
-
if (removed) {
|
|
1528
|
-
this.logger.debug(`${chalk6__default.default.italic("Removed")} ${this.getTaskType()} task ${chalk6__default.default.bold.cyan(taskName)} from phase ${chalk6__default.default.bold.magenta(this.phaseEnum[phase])}`);
|
|
1529
|
-
}
|
|
1530
|
-
return removed;
|
|
1531
|
-
}
|
|
1532
|
-
/**
|
|
1533
|
-
* Run all tasks in a specific phase
|
|
1534
|
-
*/
|
|
1535
|
-
async runPhase(phase) {
|
|
1536
|
-
const tasks = this.tasksMap.get(phase) ?? [];
|
|
1537
|
-
if (tasks.length === 0) {
|
|
1538
|
-
this.logger.warn(`No tasks to run in phase ${chalk6__default.default.bold.magenta(this.phaseEnum[phase])}`);
|
|
1539
|
-
return;
|
|
1540
|
-
}
|
|
1541
|
-
this.logger.info(`${chalk6__default.default.bold.yellow("Running")} ${this.getTaskType()} phase ${chalk6__default.default.bold.magenta(this.phaseEnum[phase])} with ${chalk6__default.default.bold.cyan(tasks.length)} tasks`);
|
|
1542
|
-
this.emit(`phase:${phase}:start`);
|
|
1543
|
-
const results = await this.executeTasksInPhase(phase, tasks);
|
|
1544
|
-
const failures = results.filter((r) => r.status === "rejected").length;
|
|
1545
|
-
if (failures > 0) {
|
|
1546
|
-
const errorMessage = `Phase ${chalk6__default.default.bold.magenta(this.phaseEnum[phase])} completed with ${chalk6__default.default.bold.red(failures)} failed tasks`;
|
|
1547
|
-
throw new Error(errorMessage);
|
|
1548
|
-
} else {
|
|
1549
|
-
this.logger.info(`Phase ${chalk6__default.default.bold.magenta(this.phaseEnum[phase])} ${chalk6__default.default.bold.green("completed successfully")}`);
|
|
1550
|
-
}
|
|
1551
|
-
this.emit(`phase:${phase}:complete`);
|
|
1552
|
-
}
|
|
1553
|
-
/**
|
|
1554
|
-
* Run a single task with timeout
|
|
1555
|
-
*/
|
|
1556
|
-
async runTaskWithTimeout(phase, task) {
|
|
1557
|
-
this.logger.info(`${chalk6__default.default.italic("Starting")} task ${chalk6__default.default.bold.cyan(task.name)} in phase ${chalk6__default.default.bold.magenta(this.phaseEnum[phase])}`);
|
|
1558
|
-
try {
|
|
1559
|
-
await Promise.race([
|
|
1560
|
-
task.task(),
|
|
1561
|
-
new Promise((_, reject) => {
|
|
1562
|
-
setTimeout(() => {
|
|
1563
|
-
reject(new Error(`Task '${task.name}' timed out after ${task.timeout}ms`));
|
|
1564
|
-
}, task.timeout);
|
|
1565
|
-
})
|
|
1566
|
-
]);
|
|
1567
|
-
this.logger.info(`${chalk6__default.default.italic("Completed")} task ${chalk6__default.default.bold.cyan(task.name)} in phase ${chalk6__default.default.bold.magenta(this.phaseEnum[phase])}`);
|
|
1568
|
-
} catch (error) {
|
|
1569
|
-
this.logger.error(`${chalk6__default.default.italic("Failed")} task ${chalk6__default.default.bold.cyan(task.name)} in phase ${chalk6__default.default.bold.magenta(this.phaseEnum[phase])}:`, error);
|
|
1570
|
-
throw error;
|
|
1571
|
-
}
|
|
1572
|
-
}
|
|
1573
|
-
/**
|
|
1574
|
-
* Subscribe to lifecycle events
|
|
1575
|
-
*/
|
|
1576
|
-
on(event, listener) {
|
|
1577
|
-
this.events.on(event, listener);
|
|
1578
|
-
}
|
|
1579
|
-
/**
|
|
1580
|
-
* Unsubscribe from lifecycle events
|
|
1581
|
-
*/
|
|
1582
|
-
off(event, listener) {
|
|
1583
|
-
this.events.off(event, listener);
|
|
1584
|
-
}
|
|
1585
|
-
emit(event, ...args) {
|
|
1586
|
-
return this.events.emit(event, ...args);
|
|
1587
|
-
}
|
|
1588
|
-
};
|
|
1589
|
-
|
|
1590
|
-
// src/services/Lifecycle/CoordinatedShutdown.ts
|
|
1591
|
-
var ShutdownPhase = /* @__PURE__ */ (function(ShutdownPhase2) {
|
|
1592
|
-
ShutdownPhase2[ShutdownPhase2["StopAcceptingRequests"] = 1] = "StopAcceptingRequests";
|
|
1593
|
-
ShutdownPhase2[ShutdownPhase2["StopServices"] = 2] = "StopServices";
|
|
1594
|
-
ShutdownPhase2[ShutdownPhase2["ExternalResources"] = 3] = "ExternalResources";
|
|
1595
|
-
ShutdownPhase2[ShutdownPhase2["DiscordCleanup"] = 4] = "DiscordCleanup";
|
|
1596
|
-
ShutdownPhase2[ShutdownPhase2["FinalCleanup"] = 5] = "FinalCleanup";
|
|
1597
|
-
return ShutdownPhase2;
|
|
1598
|
-
})({});
|
|
1599
|
-
var PHASE_ORDER = [
|
|
1600
|
-
1,
|
|
1601
|
-
2,
|
|
1602
|
-
3,
|
|
1603
|
-
4,
|
|
1604
|
-
5
|
|
1605
|
-
];
|
|
1606
|
-
var LOG_FLUSH_DELAY_MS = 500;
|
|
1607
|
-
var CoordinatedShutdown = class extends CoordinatedLifecycle {
|
|
1608
|
-
static {
|
|
1609
|
-
__name(this, "CoordinatedShutdown");
|
|
1610
|
-
}
|
|
1611
|
-
isShuttingDown = false;
|
|
1612
|
-
exitCode = 0;
|
|
1613
|
-
constructor() {
|
|
1614
|
-
super("CoordinatedShutdown", PHASE_ORDER, ShutdownPhase);
|
|
1615
|
-
this.registerSignalHandlers();
|
|
1616
|
-
}
|
|
1617
|
-
canAddTask() {
|
|
1618
|
-
return Globals.shutdownIsEnabled;
|
|
1619
|
-
}
|
|
1620
|
-
canRemoveTask() {
|
|
1621
|
-
return true;
|
|
1622
|
-
}
|
|
1623
|
-
getTaskType() {
|
|
1624
|
-
return "shutdown";
|
|
1625
|
-
}
|
|
1626
|
-
async executeTasksInPhase(phase, tasks) {
|
|
1627
|
-
const results = [];
|
|
1628
|
-
for (const task of tasks) {
|
|
1629
|
-
results.push(await Promise.resolve().then(() => this.runTaskWithTimeout(phase, task)).then(() => ({
|
|
1630
|
-
status: "fulfilled",
|
|
1631
|
-
value: void 0
|
|
1632
|
-
}), (reason) => ({
|
|
1633
|
-
status: "rejected",
|
|
1634
|
-
reason
|
|
1635
|
-
})));
|
|
1636
|
-
}
|
|
1637
|
-
return results;
|
|
1638
|
-
}
|
|
1639
|
-
registerSignalHandlers() {
|
|
1640
|
-
if (!Globals.shutdownIsEnabled) return;
|
|
1641
|
-
process.on("SIGTERM", () => {
|
|
1642
|
-
this.logger.info(`Received ${chalk6__default.default.yellow.bold("SIGTERM")} signal`);
|
|
1643
|
-
void this.run(0);
|
|
1644
|
-
});
|
|
1645
|
-
process.on("SIGINT", () => {
|
|
1646
|
-
this.logger.info(`Received ${chalk6__default.default.yellow.bold("SIGINT")} signal`);
|
|
1647
|
-
void this.run(0);
|
|
1648
|
-
});
|
|
1649
|
-
}
|
|
1650
|
-
/**
|
|
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)
|
|
1657
|
-
*/
|
|
1658
|
-
addTask(phase, taskName, task, timeoutMs = 5e3) {
|
|
1659
|
-
super.addTask(phase, taskName, task, timeoutMs);
|
|
1660
|
-
}
|
|
1661
|
-
/**
|
|
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
|
|
1667
|
-
*/
|
|
1668
|
-
removeTask(phase, taskName) {
|
|
1669
|
-
return super.removeTask(phase, taskName);
|
|
1670
|
-
}
|
|
1671
|
-
/**
|
|
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
|
-
* ```
|
|
1685
|
-
*/
|
|
1686
|
-
async run(exitCode = 0) {
|
|
1687
|
-
if (this.isShuttingDown) {
|
|
1688
|
-
this.logger.warn("Shutdown sequence already in progress");
|
|
1689
|
-
return;
|
|
1690
|
-
}
|
|
1691
|
-
this.isShuttingDown = true;
|
|
1692
|
-
this.exitCode = exitCode;
|
|
1693
|
-
this.logger.info(`${chalk6__default.default.bold.yellow("Starting")} coordinated shutdown with exit code ${chalk6__default.default.bold.cyan(exitCode)}`);
|
|
1694
|
-
this.emit("shutdown:start");
|
|
1695
|
-
try {
|
|
1696
|
-
for (const phase of PHASE_ORDER) {
|
|
1697
|
-
await this.runPhase(phase);
|
|
1698
|
-
}
|
|
1699
|
-
this.logger.info(`${chalk6__default.default.bold.green("Coordinated shutdown completed")} successfully`);
|
|
1700
|
-
this.emit("shutdown:complete");
|
|
1701
|
-
} catch (error) {
|
|
1702
|
-
this.logger.error(`${chalk6__default.default.bold.red("Coordinated shutdown failed")}`);
|
|
1703
|
-
this.emit("shutdown:error", error);
|
|
1704
|
-
} finally {
|
|
1705
|
-
this.logger.info(`${chalk6__default.default.bold.red("Exiting")} process with code ${chalk6__default.default.bold.cyan(this.exitCode)}`);
|
|
1706
|
-
setTimeout(() => {
|
|
1707
|
-
process.exit(this.exitCode);
|
|
1708
|
-
}, LOG_FLUSH_DELAY_MS);
|
|
1709
|
-
}
|
|
1710
|
-
}
|
|
1711
|
-
/**
|
|
1712
|
-
* Subscribe to shutdown events
|
|
1713
|
-
*/
|
|
1714
|
-
on(event, listener) {
|
|
1715
|
-
super.on(event, listener);
|
|
1716
|
-
}
|
|
1717
|
-
/**
|
|
1718
|
-
* Unsubscribe from shutdown events
|
|
1719
|
-
*/
|
|
1720
|
-
off(event, listener) {
|
|
1721
|
-
super.off(event, listener);
|
|
1070
|
+
this.logger.info(`${chalk2__default.default.bold.green("Loaded")}: ${chalk2__default.default.magenta.bold(foundCount)} emojis`);
|
|
1722
1071
|
}
|
|
1723
1072
|
};
|
|
1724
1073
|
|
|
1725
1074
|
// src/bot/Bot.ts
|
|
1075
|
+
function _ts_decorate3(decorators, target, key, desc) {
|
|
1076
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1077
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1078
|
+
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;
|
|
1079
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1080
|
+
}
|
|
1081
|
+
__name(_ts_decorate3, "_ts_decorate");
|
|
1082
|
+
function _ts_metadata3(k, v) {
|
|
1083
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1084
|
+
}
|
|
1085
|
+
__name(_ts_metadata3, "_ts_metadata");
|
|
1726
1086
|
var Bot = class extends Plugin {
|
|
1727
1087
|
static {
|
|
1728
1088
|
__name(this, "Bot");
|
|
1729
1089
|
}
|
|
1730
1090
|
core;
|
|
1731
|
-
logger = new Logger("Bot");
|
|
1091
|
+
logger = new services.Logger("Bot");
|
|
1732
1092
|
isInitialized = false;
|
|
1733
1093
|
_client;
|
|
1734
1094
|
interactions;
|
|
@@ -1746,7 +1106,7 @@ var Bot = class extends Plugin {
|
|
|
1746
1106
|
this.events = new EventController(core);
|
|
1747
1107
|
this.commands = new CommandRegistry(this.core);
|
|
1748
1108
|
this.emojiInjector = new EmojiInjector(this.core);
|
|
1749
|
-
this.core.shutdown.addTask(ShutdownPhase.DiscordCleanup, "stop-bot", async () => await this.stop());
|
|
1109
|
+
this.core.shutdown.addTask(services.ShutdownPhase.DiscordCleanup, "stop-bot", async () => await this.stop());
|
|
1750
1110
|
}
|
|
1751
1111
|
/**
|
|
1752
1112
|
* Initializes Discord client and all controllers
|
|
@@ -1776,8 +1136,8 @@ var Bot = class extends Plugin {
|
|
|
1776
1136
|
* Logs the bot into Discord using the configured token
|
|
1777
1137
|
*/
|
|
1778
1138
|
async login() {
|
|
1779
|
-
await this._client.login(
|
|
1780
|
-
this.logger.info(`Logged in as ${
|
|
1139
|
+
await this._client.login(this.botToken);
|
|
1140
|
+
this.logger.info(`Logged in as ${chalk2__default.default.bold.magenta(this._client.user?.username)}!`);
|
|
1781
1141
|
return this;
|
|
1782
1142
|
}
|
|
1783
1143
|
/**
|
|
@@ -1785,12 +1145,21 @@ var Bot = class extends Plugin {
|
|
|
1785
1145
|
*/
|
|
1786
1146
|
async logout() {
|
|
1787
1147
|
await this._client.destroy();
|
|
1788
|
-
this.logger.info(
|
|
1148
|
+
this.logger.info(chalk2__default.default.bold.red("Logged out of Discord!"));
|
|
1789
1149
|
}
|
|
1790
1150
|
get client() {
|
|
1791
1151
|
return this._client;
|
|
1792
1152
|
}
|
|
1793
1153
|
};
|
|
1154
|
+
_ts_decorate3([
|
|
1155
|
+
envapt.Envapt("DISCORD_BOT_TOKEN", {
|
|
1156
|
+
converter(raw, _fallback) {
|
|
1157
|
+
if (typeof raw !== "string") throw new Error("Missing DISCORD_BOT_TOKEN");
|
|
1158
|
+
return raw;
|
|
1159
|
+
}
|
|
1160
|
+
}),
|
|
1161
|
+
_ts_metadata3("design:type", String)
|
|
1162
|
+
], Bot.prototype, "botToken", void 0);
|
|
1794
1163
|
|
|
1795
1164
|
// src/effects/decorators/RegisterEffect.ts
|
|
1796
1165
|
var EffectMetadataKey = Symbol("effect:metadata");
|
|
@@ -1833,19 +1202,23 @@ var WebhookLog = class extends EffectsHandler {
|
|
|
1833
1202
|
};
|
|
1834
1203
|
|
|
1835
1204
|
// src/effects/default/UnknownException.ts
|
|
1836
|
-
function
|
|
1205
|
+
function _ts_decorate4(decorators, target, key, desc) {
|
|
1837
1206
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1838
1207
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1839
1208
|
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;
|
|
1840
1209
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1841
1210
|
}
|
|
1842
|
-
__name(
|
|
1843
|
-
|
|
1211
|
+
__name(_ts_decorate4, "_ts_decorate");
|
|
1212
|
+
function _ts_metadata4(k, v) {
|
|
1213
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1214
|
+
}
|
|
1215
|
+
__name(_ts_metadata4, "_ts_metadata");
|
|
1216
|
+
var UnknownException = class _UnknownException extends WebhookLog {
|
|
1844
1217
|
static {
|
|
1845
1218
|
__name(this, "UnknownException");
|
|
1846
1219
|
}
|
|
1847
1220
|
webhook = new discord_js.WebhookClient({
|
|
1848
|
-
url:
|
|
1221
|
+
url: _UnknownException.unknownExceptionWebhookUrl
|
|
1849
1222
|
});
|
|
1850
1223
|
async execute() {
|
|
1851
1224
|
await this.webhook.send({
|
|
@@ -1857,7 +1230,16 @@ var UnknownException = class extends WebhookLog {
|
|
|
1857
1230
|
});
|
|
1858
1231
|
}
|
|
1859
1232
|
};
|
|
1860
|
-
|
|
1233
|
+
_ts_decorate4([
|
|
1234
|
+
envapt.Envapt("UNKNOWN_EXCEPTION_WEBHOOK_URL", {
|
|
1235
|
+
converter(raw, _fallback) {
|
|
1236
|
+
if (!raw) throw new Error("Missing UNKNOWN_EXCEPTION_WEBHOOK_URL");
|
|
1237
|
+
return raw;
|
|
1238
|
+
}
|
|
1239
|
+
}),
|
|
1240
|
+
_ts_metadata4("design:type", String)
|
|
1241
|
+
], UnknownException, "unknownExceptionWebhookUrl", void 0);
|
|
1242
|
+
UnknownException = _ts_decorate4([
|
|
1861
1243
|
RegisterEffect("unknownException")
|
|
1862
1244
|
], UnknownException);
|
|
1863
1245
|
var UnhandledErrorEmbed = class UnhandledErrorEmbed2 extends BuilderComponent {
|
|
@@ -1943,7 +1325,7 @@ var EffectsRegistry = class extends Plugin {
|
|
|
1943
1325
|
__name(this, "EffectsRegistry");
|
|
1944
1326
|
}
|
|
1945
1327
|
core;
|
|
1946
|
-
logger = new Logger("Effects");
|
|
1328
|
+
logger = new services.Logger("Effects");
|
|
1947
1329
|
isInitialized = false;
|
|
1948
1330
|
effectsMap = /* @__PURE__ */ new Map();
|
|
1949
1331
|
emitter = new EffectsEmitter();
|
|
@@ -1954,26 +1336,26 @@ var EffectsRegistry = class extends Plugin {
|
|
|
1954
1336
|
if (this.isInitialized) return;
|
|
1955
1337
|
this.isInitialized = true;
|
|
1956
1338
|
const effectsDir = this.core.config.effects.path;
|
|
1957
|
-
this.logger.info(
|
|
1339
|
+
this.logger.info(chalk2__default.default.bold(effectsDir));
|
|
1958
1340
|
this.registerEffect("unknownException", UnknownException);
|
|
1959
1341
|
await this.loadEffects(effectsDir);
|
|
1960
1342
|
this.attachEffects();
|
|
1961
1343
|
const totalEffects = Array.from(this.effectsMap.values()).reduce((acc, handlers) => acc + handlers.length, 0);
|
|
1962
|
-
this.logger.info(`${
|
|
1344
|
+
this.logger.info(`${chalk2__default.default.bold.green("Loaded")}: ${chalk2__default.default.bold.magenta(totalEffects)} side effects`);
|
|
1963
1345
|
}
|
|
1964
1346
|
async loadEffects(dir) {
|
|
1965
|
-
await traverseDirectory(dir, (_fullPath, relativePath, imported) => {
|
|
1347
|
+
await utils.traverseDirectory(dir, (_fullPath, relativePath, imported) => {
|
|
1966
1348
|
for (const exportName of Object.keys(imported)) {
|
|
1967
1349
|
const val = imported[exportName];
|
|
1968
1350
|
if (this.isEffectHandler(val)) {
|
|
1969
1351
|
const effectName = Reflect.getMetadata(EffectMetadataKey, val);
|
|
1970
1352
|
if (effectName) {
|
|
1971
1353
|
this.registerEffect(effectName, val);
|
|
1972
|
-
this.logger.info(`${
|
|
1354
|
+
this.logger.info(`${chalk2__default.default.italic("Registered")} ${chalk2__default.default.bold.yellow(val.name)} from ${chalk2__default.default.gray(relativePath)}`);
|
|
1973
1355
|
}
|
|
1974
1356
|
}
|
|
1975
1357
|
}
|
|
1976
|
-
});
|
|
1358
|
+
}, this.logger);
|
|
1977
1359
|
}
|
|
1978
1360
|
registerEffect(effectName, handler) {
|
|
1979
1361
|
let handlers = this.effectsMap.get(effectName);
|
|
@@ -2005,202 +1387,6 @@ var EffectsRegistry = class extends Plugin {
|
|
|
2005
1387
|
return this.emitter.emit(event, data);
|
|
2006
1388
|
}
|
|
2007
1389
|
};
|
|
2008
|
-
var HTTP_OK = 200;
|
|
2009
|
-
var HTTP_NOT_FOUND = 404;
|
|
2010
|
-
var HealthCheck = class extends Plugin {
|
|
2011
|
-
static {
|
|
2012
|
-
__name(this, "HealthCheck");
|
|
2013
|
-
}
|
|
2014
|
-
core;
|
|
2015
|
-
logger = new Logger("HealthCheck");
|
|
2016
|
-
port = Globals.healthCheckPort;
|
|
2017
|
-
path = Globals.healthCheckPath;
|
|
2018
|
-
server;
|
|
2019
|
-
constructor(core) {
|
|
2020
|
-
super(core), this.core = core;
|
|
2021
|
-
this.core.shutdown.addTask(ShutdownPhase.StopServices, "stop-healthcheck-server", async () => await this.stop());
|
|
2022
|
-
}
|
|
2023
|
-
/**
|
|
2024
|
-
* Starts the health check server.
|
|
2025
|
-
* @returns Promise that resolves when the server is listening
|
|
2026
|
-
*/
|
|
2027
|
-
async init() {
|
|
2028
|
-
return new Promise((resolve, reject) => {
|
|
2029
|
-
this.server = http.createServer((req, res) => {
|
|
2030
|
-
if (req.method === "GET" && req.url === this.path) {
|
|
2031
|
-
res.writeHead(HTTP_OK, {
|
|
2032
|
-
"Content-Type": "application/json"
|
|
2033
|
-
});
|
|
2034
|
-
res.end(JSON.stringify({
|
|
2035
|
-
status: "ok",
|
|
2036
|
-
timestamp: Date.now()
|
|
2037
|
-
}));
|
|
2038
|
-
} else {
|
|
2039
|
-
res.writeHead(HTTP_NOT_FOUND, {
|
|
2040
|
-
"Content-Type": "application/json"
|
|
2041
|
-
});
|
|
2042
|
-
res.end(JSON.stringify({
|
|
2043
|
-
status: "not found"
|
|
2044
|
-
}));
|
|
2045
|
-
}
|
|
2046
|
-
});
|
|
2047
|
-
this.server.on("error", reject);
|
|
2048
|
-
this.server.listen(this.port, () => {
|
|
2049
|
-
this.logger.info(`${chalk6__default.default.green.bold("\u2713")} Health check server listening on ${chalk6__default.default.cyan(`http://localhost:${this.port}${this.path}`)}`);
|
|
2050
|
-
resolve();
|
|
2051
|
-
});
|
|
2052
|
-
});
|
|
2053
|
-
}
|
|
2054
|
-
/**
|
|
2055
|
-
* Stops the health check server.
|
|
2056
|
-
*
|
|
2057
|
-
* @returns Promise that resolves when the server is closed
|
|
2058
|
-
*/
|
|
2059
|
-
stop() {
|
|
2060
|
-
return new Promise((shutdownResolve) => {
|
|
2061
|
-
this.server?.close(() => {
|
|
2062
|
-
this.logger.info(chalk6__default.default.bold.red("Health check server stopped"));
|
|
2063
|
-
shutdownResolve();
|
|
2064
|
-
});
|
|
2065
|
-
});
|
|
2066
|
-
}
|
|
2067
|
-
};
|
|
2068
|
-
var StartupPhase = /* @__PURE__ */ (function(StartupPhase2) {
|
|
2069
|
-
StartupPhase2[StartupPhase2["Validation"] = 1] = "Validation";
|
|
2070
|
-
StartupPhase2[StartupPhase2["Discovery"] = 2] = "Discovery";
|
|
2071
|
-
StartupPhase2[StartupPhase2["Registration"] = 3] = "Registration";
|
|
2072
|
-
StartupPhase2[StartupPhase2["Configuration"] = 4] = "Configuration";
|
|
2073
|
-
StartupPhase2[StartupPhase2["Instantiation"] = 5] = "Instantiation";
|
|
2074
|
-
StartupPhase2[StartupPhase2["Activation"] = 6] = "Activation";
|
|
2075
|
-
StartupPhase2[StartupPhase2["Ready"] = 7] = "Ready";
|
|
2076
|
-
return StartupPhase2;
|
|
2077
|
-
})({});
|
|
2078
|
-
var PHASE_ORDER2 = [
|
|
2079
|
-
1,
|
|
2080
|
-
2,
|
|
2081
|
-
3,
|
|
2082
|
-
4,
|
|
2083
|
-
5,
|
|
2084
|
-
6,
|
|
2085
|
-
7
|
|
2086
|
-
];
|
|
2087
|
-
var CoordinatedStartup = class extends CoordinatedLifecycle {
|
|
2088
|
-
static {
|
|
2089
|
-
__name(this, "CoordinatedStartup");
|
|
2090
|
-
}
|
|
2091
|
-
isStartingUp = false;
|
|
2092
|
-
hasStarted = false;
|
|
2093
|
-
constructor() {
|
|
2094
|
-
super("CoordinatedStartup", PHASE_ORDER2, StartupPhase);
|
|
2095
|
-
}
|
|
2096
|
-
/**
|
|
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)
|
|
2103
|
-
*/
|
|
2104
|
-
addTask(phase, taskName, task, timeoutMs = 1e4) {
|
|
2105
|
-
super.addTask(phase, taskName, task, timeoutMs);
|
|
2106
|
-
}
|
|
2107
|
-
canAddTask() {
|
|
2108
|
-
if (this.hasStarted) {
|
|
2109
|
-
throw new Error("Cannot add tasks after startup sequence has already completed");
|
|
2110
|
-
}
|
|
2111
|
-
if (this.isStartingUp) {
|
|
2112
|
-
throw new Error("Cannot add tasks while startup sequence is in progress");
|
|
2113
|
-
}
|
|
2114
|
-
return true;
|
|
2115
|
-
}
|
|
2116
|
-
canRemoveTask() {
|
|
2117
|
-
if (this.isStartingUp) {
|
|
2118
|
-
throw new Error("Cannot remove tasks while startup sequence is in progress");
|
|
2119
|
-
}
|
|
2120
|
-
return true;
|
|
2121
|
-
}
|
|
2122
|
-
getTaskType() {
|
|
2123
|
-
return "startup";
|
|
2124
|
-
}
|
|
2125
|
-
async executeTasksInPhase(phase, tasks) {
|
|
2126
|
-
const results = [];
|
|
2127
|
-
for (const task of tasks) {
|
|
2128
|
-
results.push(await Promise.resolve().then(() => this.runTaskWithTimeout(phase, task)).then(() => ({
|
|
2129
|
-
status: "fulfilled",
|
|
2130
|
-
value: void 0
|
|
2131
|
-
}), (reason) => ({
|
|
2132
|
-
status: "rejected",
|
|
2133
|
-
reason
|
|
2134
|
-
})));
|
|
2135
|
-
}
|
|
2136
|
-
return results;
|
|
2137
|
-
}
|
|
2138
|
-
/**
|
|
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
|
-
* ```
|
|
2153
|
-
*/
|
|
2154
|
-
async run() {
|
|
2155
|
-
if (this.hasStarted) {
|
|
2156
|
-
this.logger.warn("Startup sequence has already completed");
|
|
2157
|
-
return;
|
|
2158
|
-
}
|
|
2159
|
-
if (this.isStartingUp) {
|
|
2160
|
-
this.logger.warn("Startup sequence already in progress");
|
|
2161
|
-
return;
|
|
2162
|
-
}
|
|
2163
|
-
this.isStartingUp = true;
|
|
2164
|
-
this.logger.info(`${chalk6__default.default.bold.green("Starting")} coordinated startup sequence`);
|
|
2165
|
-
this.emit("startup:start");
|
|
2166
|
-
try {
|
|
2167
|
-
for (const phase of PHASE_ORDER2) await this.runPhase(phase);
|
|
2168
|
-
this.hasStarted = true;
|
|
2169
|
-
this.logger.info(`${chalk6__default.default.bold.green("Coordinated startup completed")} successfully`);
|
|
2170
|
-
this.emit("startup:complete");
|
|
2171
|
-
} catch (error) {
|
|
2172
|
-
this.logger.error(`${chalk6__default.default.bold.red("Coordinated startup failed")}`);
|
|
2173
|
-
this.emit("startup:error", error);
|
|
2174
|
-
throw error;
|
|
2175
|
-
} finally {
|
|
2176
|
-
this.isStartingUp = false;
|
|
2177
|
-
}
|
|
2178
|
-
}
|
|
2179
|
-
/**
|
|
2180
|
-
* Subscribe to startup events
|
|
2181
|
-
*/
|
|
2182
|
-
on(event, listener) {
|
|
2183
|
-
super.on(event, listener);
|
|
2184
|
-
}
|
|
2185
|
-
/**
|
|
2186
|
-
* Unsubscribe from startup events
|
|
2187
|
-
*/
|
|
2188
|
-
off(event, listener) {
|
|
2189
|
-
super.off(event, listener);
|
|
2190
|
-
}
|
|
2191
|
-
/**
|
|
2192
|
-
* Check if startup has completed
|
|
2193
|
-
*/
|
|
2194
|
-
get isReady() {
|
|
2195
|
-
return this.hasStarted;
|
|
2196
|
-
}
|
|
2197
|
-
/**
|
|
2198
|
-
* Check if startup is currently running
|
|
2199
|
-
*/
|
|
2200
|
-
get isRunning() {
|
|
2201
|
-
return this.isStartingUp;
|
|
2202
|
-
}
|
|
2203
|
-
};
|
|
2204
1390
|
|
|
2205
1391
|
// src/Seedcord.ts
|
|
2206
1392
|
var Seedcord = class _Seedcord extends Pluggable {
|
|
@@ -2226,8 +1412,8 @@ var Seedcord = class _Seedcord extends Pluggable {
|
|
|
2226
1412
|
* @throws An {@link Error} When attempting to create multiple instances (singleton)
|
|
2227
1413
|
*/
|
|
2228
1414
|
constructor(config) {
|
|
2229
|
-
const shutdown = new CoordinatedShutdown();
|
|
2230
|
-
const startup = new CoordinatedStartup();
|
|
1415
|
+
const shutdown = new services.CoordinatedShutdown();
|
|
1416
|
+
const startup = new services.CoordinatedStartup();
|
|
2231
1417
|
super(shutdown, startup), this.config = config;
|
|
2232
1418
|
this.shutdown = shutdown;
|
|
2233
1419
|
this.startup = startup;
|
|
@@ -2237,7 +1423,7 @@ var Seedcord = class _Seedcord extends Pluggable {
|
|
|
2237
1423
|
_Seedcord.isInstantiated = true;
|
|
2238
1424
|
this.effects = new EffectsRegistry(this);
|
|
2239
1425
|
this.bot = new Bot(this);
|
|
2240
|
-
this.healthCheck = new HealthCheck(this);
|
|
1426
|
+
this.healthCheck = new services.HealthCheck(this.shutdown);
|
|
2241
1427
|
this.registerStartupTasks();
|
|
2242
1428
|
}
|
|
2243
1429
|
/**
|
|
@@ -2245,20 +1431,20 @@ var Seedcord = class _Seedcord extends Pluggable {
|
|
|
2245
1431
|
* @internal
|
|
2246
1432
|
*/
|
|
2247
1433
|
registerStartupTasks() {
|
|
2248
|
-
this.startup.addTask(StartupPhase.Configuration, "Effect Initialization", async () => {
|
|
2249
|
-
this.effects.logger.info(
|
|
1434
|
+
this.startup.addTask(services.StartupPhase.Configuration, "Effect Initialization", async () => {
|
|
1435
|
+
this.effects.logger.info(chalk2__default.default.bold("Initializing"));
|
|
2250
1436
|
await this.effects.init();
|
|
2251
|
-
this.effects.logger.info(
|
|
1437
|
+
this.effects.logger.info(chalk2__default.default.bold("Initialized"));
|
|
2252
1438
|
});
|
|
2253
|
-
this.startup.addTask(StartupPhase.Instantiation, "Bot Initialization", async () => {
|
|
2254
|
-
this.bot.logger.info(
|
|
1439
|
+
this.startup.addTask(services.StartupPhase.Instantiation, "Bot Initialization", async () => {
|
|
1440
|
+
this.bot.logger.info(chalk2__default.default.bold("Initializing"));
|
|
2255
1441
|
await this.bot.init();
|
|
2256
|
-
this.bot.logger.info(
|
|
1442
|
+
this.bot.logger.info(chalk2__default.default.bold("Initialized"));
|
|
2257
1443
|
});
|
|
2258
|
-
this.startup.addTask(StartupPhase.Ready, "Health Check", async () => {
|
|
2259
|
-
this.healthCheck.logger.info(
|
|
1444
|
+
this.startup.addTask(services.StartupPhase.Ready, "Health Check", async () => {
|
|
1445
|
+
this.healthCheck.logger.info(chalk2__default.default.bold("Initializing"));
|
|
2260
1446
|
await this.healthCheck.init();
|
|
2261
|
-
this.healthCheck.logger.info(
|
|
1447
|
+
this.healthCheck.logger.info(chalk2__default.default.bold("Initialized"));
|
|
2262
1448
|
});
|
|
2263
1449
|
}
|
|
2264
1450
|
/**
|
|
@@ -2308,74 +1494,21 @@ function EventCatchable(log) {
|
|
|
2308
1494
|
};
|
|
2309
1495
|
}
|
|
2310
1496
|
__name(EventCatchable, "EventCatchable");
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
* Creates a new CooldownManager instance.
|
|
2323
|
-
*
|
|
2324
|
-
* @param opts - Configuration options for the cooldown behavior
|
|
2325
|
-
*/
|
|
2326
|
-
constructor(opts = {}) {
|
|
2327
|
-
this.window = opts.cooldown ?? 1e3;
|
|
2328
|
-
this.Err = opts.err ?? Error;
|
|
2329
|
-
this.msg = opts.message ?? "Cooldown active";
|
|
2330
|
-
}
|
|
2331
|
-
/**
|
|
2332
|
-
* Records usage timestamp for a key without any cooldown checks.
|
|
2333
|
-
*
|
|
2334
|
-
* @param key - The unique identifier for the cooldown entry
|
|
2335
|
-
*/
|
|
2336
|
-
set(key) {
|
|
2337
|
-
this.map.set(key, Date.now());
|
|
2338
|
-
}
|
|
2339
|
-
/**
|
|
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
|
|
2347
|
-
*/
|
|
2348
|
-
check(key) {
|
|
2349
|
-
const now = Date.now();
|
|
2350
|
-
const last = this.map.get(key);
|
|
2351
|
-
const remaining = this.window - (now - (last ?? 0));
|
|
2352
|
-
if (Globals.isDevelopment && remaining > 0) {
|
|
2353
|
-
Logger.Debug("CooldownManager", `${key} - ${remaining}ms remaining`);
|
|
2354
|
-
}
|
|
2355
|
-
if (last !== void 0 && remaining > 0) {
|
|
2356
|
-
throw new this.Err(this.msg, remaining);
|
|
1497
|
+
function throwCustomError(error, message, CustomError2) {
|
|
1498
|
+
const uuid = crypto.randomUUID();
|
|
1499
|
+
services.Logger.Error("Throwing Custom Error", error.name);
|
|
1500
|
+
if (typeof CustomError2 === typeof DatabaseError) {
|
|
1501
|
+
const errorMessage = error instanceof Error ? error.message : message;
|
|
1502
|
+
throw new CustomError2(errorMessage, uuid);
|
|
1503
|
+
} else {
|
|
1504
|
+
if (error instanceof Error) {
|
|
1505
|
+
throw new CustomError2(`${message}: ${error.message ? error.message : error.toString()}`);
|
|
1506
|
+
} else {
|
|
1507
|
+
throw new CustomError2(message);
|
|
2357
1508
|
}
|
|
2358
|
-
this.map.set(key, now);
|
|
2359
|
-
}
|
|
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
|
-
*/
|
|
2366
|
-
isActive(key) {
|
|
2367
|
-
const last = this.map.get(key);
|
|
2368
|
-
return last !== void 0 && Date.now() - last < this.window;
|
|
2369
1509
|
}
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
*
|
|
2373
|
-
* @param key - The unique identifier to remove (useful for manual resets)
|
|
2374
|
-
*/
|
|
2375
|
-
clear(key) {
|
|
2376
|
-
this.map.delete(key);
|
|
2377
|
-
}
|
|
2378
|
-
};
|
|
1510
|
+
}
|
|
1511
|
+
__name(throwCustomError, "throwCustomError");
|
|
2379
1512
|
|
|
2380
1513
|
exports.AutocompleteHandler = AutocompleteHandler;
|
|
2381
1514
|
exports.AutocompleteRoute = AutocompleteRoute;
|
|
@@ -2387,9 +1520,6 @@ exports.Catchable = Catchable;
|
|
|
2387
1520
|
exports.Checkable = Checkable;
|
|
2388
1521
|
exports.CommandMetadataKey = CommandMetadataKey;
|
|
2389
1522
|
exports.ContextMenuRoute = ContextMenuRoute;
|
|
2390
|
-
exports.CooldownManager = CooldownManager;
|
|
2391
|
-
exports.CoordinatedShutdown = CoordinatedShutdown;
|
|
2392
|
-
exports.CoordinatedStartup = CoordinatedStartup;
|
|
2393
1523
|
exports.CustomError = CustomError;
|
|
2394
1524
|
exports.DatabaseError = DatabaseError;
|
|
2395
1525
|
exports.EffectMetadataKey = EffectMetadataKey;
|
|
@@ -2399,13 +1529,10 @@ exports.EffectsRegistry = EffectsRegistry;
|
|
|
2399
1529
|
exports.EventCatchable = EventCatchable;
|
|
2400
1530
|
exports.EventHandler = EventHandler;
|
|
2401
1531
|
exports.EventMetadataKey = EventMetadataKey;
|
|
2402
|
-
exports.Globals = Globals;
|
|
2403
|
-
exports.HealthCheck = HealthCheck;
|
|
2404
1532
|
exports.InteractionHandler = InteractionHandler;
|
|
2405
1533
|
exports.InteractionMetadataKey = InteractionMetadataKey;
|
|
2406
1534
|
exports.InteractionMiddleware = InteractionMiddleware;
|
|
2407
1535
|
exports.InteractionRoutes = InteractionRoutes;
|
|
2408
|
-
exports.Logger = Logger;
|
|
2409
1536
|
exports.ModalComponent = ModalComponent;
|
|
2410
1537
|
exports.ModalRoute = ModalRoute;
|
|
2411
1538
|
exports.Pluggable = Pluggable;
|
|
@@ -2417,22 +1544,20 @@ exports.RowComponent = RowComponent;
|
|
|
2417
1544
|
exports.Seedcord = Seedcord;
|
|
2418
1545
|
exports.SelectMenuRoute = SelectMenuRoute;
|
|
2419
1546
|
exports.SelectMenuType = SelectMenuType;
|
|
2420
|
-
exports.ShutdownPhase = ShutdownPhase;
|
|
2421
1547
|
exports.SlashRoute = SlashRoute;
|
|
2422
|
-
exports.StartupPhase = StartupPhase;
|
|
2423
1548
|
exports.WebhookLog = WebhookLog;
|
|
2424
|
-
exports.currentTime = currentTime;
|
|
2425
|
-
exports.formatWord = formatWord;
|
|
2426
|
-
exports.fyShuffle = fyShuffle;
|
|
2427
|
-
exports.generateAsciiTable = generateAsciiTable;
|
|
2428
|
-
exports.isTsOrJsFile = isTsOrJsFile;
|
|
2429
|
-
exports.longestStringLength = longestStringLength;
|
|
2430
|
-
exports.numberFixer = numberFixer;
|
|
2431
|
-
exports.ordinal = ordinal;
|
|
2432
|
-
exports.percentage = percentage;
|
|
2433
|
-
exports.prettify = prettify;
|
|
2434
|
-
exports.prettyDifference = prettyDifference;
|
|
2435
1549
|
exports.throwCustomError = throwCustomError;
|
|
2436
|
-
|
|
1550
|
+
Object.keys(services).forEach(function (k) {
|
|
1551
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
1552
|
+
enumerable: true,
|
|
1553
|
+
get: function () { return services[k]; }
|
|
1554
|
+
});
|
|
1555
|
+
});
|
|
1556
|
+
Object.keys(utils).forEach(function (k) {
|
|
1557
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
1558
|
+
enumerable: true,
|
|
1559
|
+
get: function () { return utils[k]; }
|
|
1560
|
+
});
|
|
1561
|
+
});
|
|
2437
1562
|
//# sourceMappingURL=index.cjs.map
|
|
2438
1563
|
//# sourceMappingURL=index.cjs.map
|