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