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