seedcord 0.7.0 → 0.8.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 +314 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +332 -56
- package/dist/index.d.ts +332 -56
- package/dist/index.mjs +315 -47
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -34,8 +34,6 @@ var crypto2__namespace = /*#__PURE__*/_interopNamespace(crypto2);
|
|
|
34
34
|
|
|
35
35
|
var __defProp = Object.defineProperty;
|
|
36
36
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
37
|
-
|
|
38
|
-
// src/bot/decorators/Command.ts
|
|
39
37
|
var CommandMetadataKey = Symbol("command:metadata");
|
|
40
38
|
function RegisterCommand(scope, guilds = []) {
|
|
41
39
|
return (ctor) => {
|
|
@@ -45,6 +43,20 @@ function RegisterCommand(scope, guilds = []) {
|
|
|
45
43
|
scope,
|
|
46
44
|
guilds
|
|
47
45
|
};
|
|
46
|
+
const existingMeta = Reflect.getOwnMetadata(CommandMetadataKey, ctor);
|
|
47
|
+
if (existingMeta) {
|
|
48
|
+
throw new services.SeedcordError(services.SeedcordErrorCode.DecoratorCommandAlreadyRegistered, [
|
|
49
|
+
ctor.name,
|
|
50
|
+
existingMeta.scope,
|
|
51
|
+
scope
|
|
52
|
+
]);
|
|
53
|
+
}
|
|
54
|
+
if (scope === "global" && guilds.length > 0) {
|
|
55
|
+
throw new services.SeedcordError(services.SeedcordErrorCode.DecoratorCommandGlobalWithGuilds);
|
|
56
|
+
}
|
|
57
|
+
if (scope === "guild" && (!Array.isArray(guilds) || guilds.length === 0)) {
|
|
58
|
+
throw new services.SeedcordError(services.SeedcordErrorCode.DecoratorCommandGuildWithoutGuilds);
|
|
59
|
+
}
|
|
48
60
|
Reflect.defineMetadata(CommandMetadataKey, meta, ctor);
|
|
49
61
|
};
|
|
50
62
|
}
|
|
@@ -291,24 +303,20 @@ var CommandRegistry = class {
|
|
|
291
303
|
await guild.commands.set(commands);
|
|
292
304
|
const tag = commands.length === 1 ? "command" : "commands";
|
|
293
305
|
this.logger.info(`${chalk3__default.default.bold.green("Configured")} ${chalk3__default.default.magenta.bold(commands.length)} ${tag} for guild ${chalk3__default.default.bold.yellow(guild.name)}`);
|
|
294
|
-
this.logger.info(
|
|
306
|
+
this.logger.info(`\u2192 ${commands.map((command) => chalk3__default.default.bold.cyan(command.name)).join(", ")}`);
|
|
295
307
|
}
|
|
296
308
|
}
|
|
297
309
|
};
|
|
298
310
|
|
|
299
311
|
// src/bot/decorators/Events.ts
|
|
300
312
|
var EventMetadataKey = Symbol("event:metadata");
|
|
301
|
-
function RegisterEvent(
|
|
313
|
+
function RegisterEvent(...defs) {
|
|
302
314
|
return function(constructor) {
|
|
303
315
|
const saved = Reflect.getMetadata(EventMetadataKey, constructor);
|
|
304
316
|
const existing = saved ?? [];
|
|
305
|
-
const
|
|
306
|
-
events
|
|
307
|
-
];
|
|
308
|
-
const frequency = options?.frequency ?? "on";
|
|
309
|
-
const entries = toStore.map((event) => ({
|
|
317
|
+
const entries = defs.map(([event, options]) => ({
|
|
310
318
|
event,
|
|
311
|
-
frequency
|
|
319
|
+
frequency: options?.frequency ?? "on"
|
|
312
320
|
}));
|
|
313
321
|
Reflect.defineMetadata(EventMetadataKey, [
|
|
314
322
|
...existing,
|
|
@@ -317,8 +325,6 @@ function RegisterEvent(events, options) {
|
|
|
317
325
|
};
|
|
318
326
|
}
|
|
319
327
|
__name(RegisterEvent, "RegisterEvent");
|
|
320
|
-
|
|
321
|
-
// src/bot/decorators/Middlewares.ts
|
|
322
328
|
var MiddlewareType = /* @__PURE__ */ (function(MiddlewareType2) {
|
|
323
329
|
MiddlewareType2["Interaction"] = "middleware:interaction";
|
|
324
330
|
MiddlewareType2["Event"] = "middleware:event";
|
|
@@ -329,10 +335,10 @@ function Middleware(type, priority = 0, options = {}) {
|
|
|
329
335
|
return (ctor) => {
|
|
330
336
|
const normalizedPriority = Number(priority);
|
|
331
337
|
if (!Number.isFinite(normalizedPriority)) {
|
|
332
|
-
throw new
|
|
338
|
+
throw new services.SeedcordTypeError(services.SeedcordErrorCode.DecoratorInvalidMiddlewarePriority);
|
|
333
339
|
}
|
|
334
|
-
if (type === "middleware:interaction" && options.events
|
|
335
|
-
throw new
|
|
340
|
+
if (type === "middleware:interaction" && Array.isArray(options.events) && options.events.length > 0) {
|
|
341
|
+
throw new services.SeedcordError(services.SeedcordErrorCode.DecoratorInteractionEventFilter);
|
|
336
342
|
}
|
|
337
343
|
const metadata = {
|
|
338
344
|
priority: normalizedPriority,
|
|
@@ -345,8 +351,6 @@ function Middleware(type, priority = 0, options = {}) {
|
|
|
345
351
|
};
|
|
346
352
|
}
|
|
347
353
|
__name(Middleware, "Middleware");
|
|
348
|
-
|
|
349
|
-
// src/interfaces/Handler.ts
|
|
350
354
|
var BaseHandler = class {
|
|
351
355
|
static {
|
|
352
356
|
__name(this, "BaseHandler");
|
|
@@ -357,10 +361,18 @@ var BaseHandler = class {
|
|
|
357
361
|
errored = false;
|
|
358
362
|
event;
|
|
359
363
|
args = [];
|
|
364
|
+
logger;
|
|
360
365
|
constructor(event, core, args) {
|
|
361
366
|
this.core = core;
|
|
362
367
|
this.event = event;
|
|
363
368
|
this.args = args ?? [];
|
|
369
|
+
this.logger = new services.Logger(this.constructor.name);
|
|
370
|
+
this.populate();
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Populates the handler with necessary data before execution. Override this method in your handler classes to customize population logic. This method is called at the end of the constructor before all async operations.
|
|
374
|
+
*/
|
|
375
|
+
populate() {
|
|
364
376
|
}
|
|
365
377
|
hasChecks() {
|
|
366
378
|
return this.checkable;
|
|
@@ -571,12 +583,16 @@ var EventController = class {
|
|
|
571
583
|
}
|
|
572
584
|
attachToClient() {
|
|
573
585
|
for (const [eventName, handlerEntries] of this.eventMap) {
|
|
574
|
-
this.logger.debug(`Attaching ${chalk3__default.default.bold.green(eventName)} to ${chalk3__default.default.
|
|
586
|
+
this.logger.debug(`Attaching ${chalk3__default.default.bold.green(eventName)} to the client with ${chalk3__default.default.gray(handlerEntries.length)} handler(s)`);
|
|
575
587
|
for (const entry of handlerEntries) {
|
|
576
588
|
const register = entry.frequency === "once" ? this.core.bot.client.once.bind(this.core.bot.client) : this.core.bot.client.on.bind(this.core.bot.client);
|
|
577
589
|
register(eventName, (...args) => {
|
|
590
|
+
this.core.bot.emit("any:event", eventName, ...args);
|
|
578
591
|
void (async () => {
|
|
579
|
-
await this.processEvent(eventName, args, entry.ctor)
|
|
592
|
+
await this.processEvent(eventName, args, entry.ctor).catch((err) => {
|
|
593
|
+
this.logger.error(`[${chalk3__default.default.bold.red("UNHANDLED ERROR AT ROOT")}] ${err.name}`, err.stack);
|
|
594
|
+
this.core.bot.emit("error:unhandled:event", err);
|
|
595
|
+
});
|
|
580
596
|
})();
|
|
581
597
|
});
|
|
582
598
|
}
|
|
@@ -713,7 +729,7 @@ function buildSlashRoute(arg1, arg2, arg3) {
|
|
|
713
729
|
group = arg1.options.getSubcommandGroup(false) ?? void 0;
|
|
714
730
|
sub = arg1.options.getSubcommand(false) ?? void 0;
|
|
715
731
|
} else {
|
|
716
|
-
throw new
|
|
732
|
+
throw new services.SeedcordTypeError(services.SeedcordErrorCode.UtilInvalidSlashRouteArgument);
|
|
717
733
|
}
|
|
718
734
|
if (sub && group) return `${command}/${group}/${sub}`;
|
|
719
735
|
if (sub) return `${command}/${sub}`;
|
|
@@ -816,7 +832,7 @@ function Catchable(options) {
|
|
|
816
832
|
const originalMethod = descriptor.value;
|
|
817
833
|
descriptor.value = async function(...args) {
|
|
818
834
|
const interaction = this.getEvent();
|
|
819
|
-
if (!originalMethod) throw new
|
|
835
|
+
if (!originalMethod) throw new services.SeedcordError(services.SeedcordErrorCode.DecoratorMethodNotFound);
|
|
820
836
|
try {
|
|
821
837
|
await originalMethod.apply(this, args);
|
|
822
838
|
} catch (error) {
|
|
@@ -1033,8 +1049,10 @@ var InteractionController = class {
|
|
|
1033
1049
|
}
|
|
1034
1050
|
attachToClient() {
|
|
1035
1051
|
this.core.bot.client.on(discord_js.Events.InteractionCreate, (interaction) => {
|
|
1052
|
+
this.core.bot.emit("any:interaction", interaction);
|
|
1036
1053
|
this.handleInteraction(interaction).catch((err) => {
|
|
1037
1054
|
this.logger.error(`[${chalk3__default.default.bold.red("UNHANDLED ERROR AT ROOT")}] ${err.name}`, err.stack);
|
|
1055
|
+
this.core.bot.emit("error:unhandled:interaction", err);
|
|
1038
1056
|
});
|
|
1039
1057
|
});
|
|
1040
1058
|
}
|
|
@@ -1055,7 +1073,11 @@ var InteractionController = class {
|
|
|
1055
1073
|
}
|
|
1056
1074
|
async processInteraction(interaction, extractKey, getHandler, args) {
|
|
1057
1075
|
const key = extractKey(interaction);
|
|
1058
|
-
if (
|
|
1076
|
+
if ([
|
|
1077
|
+
...this.keysToIgnore
|
|
1078
|
+
].some((pattern) => typeof pattern === "string" ? pattern === key : pattern.test(key))) {
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
1059
1081
|
for (const { ctor } of this.middlewares) {
|
|
1060
1082
|
const middleware = new ctor(interaction, this.core, args);
|
|
1061
1083
|
if (middleware.hasChecks()) await middleware.runChecks();
|
|
@@ -1152,16 +1174,16 @@ var InteractionController = class {
|
|
|
1152
1174
|
await this.processInteraction(interaction, () => autocompleteKey, (key) => this.autocompleteMap.get(key));
|
|
1153
1175
|
}
|
|
1154
1176
|
};
|
|
1155
|
-
var Plugin = class {
|
|
1177
|
+
var Plugin = class extends services.StrictEventEmitter {
|
|
1156
1178
|
static {
|
|
1157
1179
|
__name(this, "Plugin");
|
|
1158
1180
|
}
|
|
1159
1181
|
pluggable;
|
|
1160
1182
|
constructor(pluggable) {
|
|
1161
|
-
this.pluggable = pluggable;
|
|
1183
|
+
super(), this.pluggable = pluggable;
|
|
1162
1184
|
}
|
|
1163
1185
|
};
|
|
1164
|
-
var Pluggable = class _Pluggable {
|
|
1186
|
+
var Pluggable = class _Pluggable extends services.StrictEventEmitter {
|
|
1165
1187
|
static {
|
|
1166
1188
|
__name(this, "Pluggable");
|
|
1167
1189
|
}
|
|
@@ -1170,6 +1192,7 @@ var Pluggable = class _Pluggable {
|
|
|
1170
1192
|
startup;
|
|
1171
1193
|
static PLUGIN_INIT_TIMEOUT_MS = 15e3;
|
|
1172
1194
|
constructor(shutdown, startup) {
|
|
1195
|
+
super();
|
|
1173
1196
|
this.shutdown = shutdown;
|
|
1174
1197
|
this.startup = startup;
|
|
1175
1198
|
}
|
|
@@ -1194,15 +1217,21 @@ var Pluggable = class _Pluggable {
|
|
|
1194
1217
|
* @param startupPhase - When during startup to initialize this plugin ({@link StartupPhase})
|
|
1195
1218
|
* @param args - Additional arguments to pass to the plugin constructor
|
|
1196
1219
|
* @returns This instance with the plugin attached as a typed property
|
|
1197
|
-
* @throws
|
|
1220
|
+
* @throws A {@link SeedcordError} When called after initialization or if key already exists
|
|
1198
1221
|
* @example
|
|
1199
1222
|
* ```typescript
|
|
1200
1223
|
* seedcord.attach('db', Mongo, StartupPhase.Configuration, { uri: 'mongodb://...', name: 'seedcord', dir: ... })
|
|
1201
1224
|
* ```
|
|
1202
1225
|
*/
|
|
1203
1226
|
attach(key, Plugin2, startupPhase, ...args) {
|
|
1204
|
-
if (this.isInitialized)
|
|
1205
|
-
|
|
1227
|
+
if (this.isInitialized) {
|
|
1228
|
+
throw new services.SeedcordError(services.SeedcordErrorCode.CorePluginAfterInit);
|
|
1229
|
+
}
|
|
1230
|
+
if (this[key]) {
|
|
1231
|
+
throw new services.SeedcordError(services.SeedcordErrorCode.CorePluginKeyExists, [
|
|
1232
|
+
key
|
|
1233
|
+
]);
|
|
1234
|
+
}
|
|
1206
1235
|
const instance = new Plugin2(this, ...args);
|
|
1207
1236
|
const entry = {
|
|
1208
1237
|
[key]: instance
|
|
@@ -1215,6 +1244,8 @@ var Pluggable = class _Pluggable {
|
|
|
1215
1244
|
return Object.assign(this, entry);
|
|
1216
1245
|
}
|
|
1217
1246
|
};
|
|
1247
|
+
var emojiStorage = {};
|
|
1248
|
+
var Emojis = emojiStorage;
|
|
1218
1249
|
var EmojiInjector = class {
|
|
1219
1250
|
static {
|
|
1220
1251
|
__name(this, "EmojiInjector");
|
|
@@ -1225,6 +1256,7 @@ var EmojiInjector = class {
|
|
|
1225
1256
|
this.core = core;
|
|
1226
1257
|
}
|
|
1227
1258
|
async init() {
|
|
1259
|
+
this.clearEmojis();
|
|
1228
1260
|
if (!this.core.config.bot.emojis || Object.keys(this.core.config.bot.emojis).length === 0) {
|
|
1229
1261
|
this.logger.info(`${chalk3__default.default.bold.green("Loaded")}: ${chalk3__default.default.magenta.bold("0")} emojis`);
|
|
1230
1262
|
return;
|
|
@@ -1233,15 +1265,24 @@ var EmojiInjector = class {
|
|
|
1233
1265
|
await this.core.bot.client.application?.emojis.fetch();
|
|
1234
1266
|
let foundCount = 0;
|
|
1235
1267
|
Object.entries(configEmojis).forEach(([key, emojiName]) => {
|
|
1268
|
+
if (typeof emojiName !== "string") {
|
|
1269
|
+
this.logger.warn(`${chalk3__default.default.bold.yellow("Invalid")}: ${chalk3__default.default.magenta.bold(String(key))} (expected string, received ${typeof emojiName})`);
|
|
1270
|
+
return;
|
|
1271
|
+
}
|
|
1236
1272
|
const emoji = this.core.bot.client.application?.emojis.cache.find((e) => e.name === emojiName);
|
|
1237
1273
|
if (emoji) {
|
|
1238
|
-
|
|
1274
|
+
emojiStorage[key] = `<${emoji.identifier}>`;
|
|
1239
1275
|
foundCount++;
|
|
1240
|
-
|
|
1276
|
+
return;
|
|
1241
1277
|
}
|
|
1278
|
+
emojiStorage[key] = emojiName;
|
|
1279
|
+
this.logger.warn(`${chalk3__default.default.bold.yellow("Missing")}: ${chalk3__default.default.magenta.bold(emojiName)} (using configured value)`);
|
|
1242
1280
|
});
|
|
1243
1281
|
this.logger.info(`${chalk3__default.default.bold.green("Loaded")}: ${chalk3__default.default.magenta.bold(foundCount)} emojis`);
|
|
1244
1282
|
}
|
|
1283
|
+
clearEmojis() {
|
|
1284
|
+
for (const key of Object.keys(emojiStorage)) Reflect.deleteProperty(emojiStorage, key);
|
|
1285
|
+
}
|
|
1245
1286
|
};
|
|
1246
1287
|
|
|
1247
1288
|
// src/bot/Bot.ts
|
|
@@ -1268,6 +1309,7 @@ var Bot = class extends Plugin {
|
|
|
1268
1309
|
events;
|
|
1269
1310
|
commands;
|
|
1270
1311
|
emojiInjector;
|
|
1312
|
+
emojis = Emojis;
|
|
1271
1313
|
constructor(core) {
|
|
1272
1314
|
super(core), this.core = core;
|
|
1273
1315
|
this._client = new discord_js.Client(core.config.bot.clientOptions);
|
|
@@ -1319,11 +1361,16 @@ var Bot = class extends Plugin {
|
|
|
1319
1361
|
get client() {
|
|
1320
1362
|
return this._client;
|
|
1321
1363
|
}
|
|
1364
|
+
emit(event, ...args) {
|
|
1365
|
+
return super.emit(event, ...args);
|
|
1366
|
+
}
|
|
1322
1367
|
};
|
|
1323
1368
|
_ts_decorate4([
|
|
1324
1369
|
envapt.Envapt("DISCORD_BOT_TOKEN", {
|
|
1325
1370
|
converter(raw, _fallback) {
|
|
1326
|
-
if (typeof raw !== "string")
|
|
1371
|
+
if (typeof raw !== "string") {
|
|
1372
|
+
throw new services.SeedcordError(services.SeedcordErrorCode.ConfigMissingDiscordToken);
|
|
1373
|
+
}
|
|
1327
1374
|
return raw;
|
|
1328
1375
|
}
|
|
1329
1376
|
}),
|
|
@@ -1386,6 +1433,25 @@ function _ts_metadata5(k, v) {
|
|
|
1386
1433
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1387
1434
|
}
|
|
1388
1435
|
__name(_ts_metadata5, "_ts_metadata");
|
|
1436
|
+
function webhookUrlValidator(raw, _fallback) {
|
|
1437
|
+
if (raw === null) {
|
|
1438
|
+
throw new services.SeedcordError(services.SeedcordErrorCode.ConfigUnknownExceptionWebhookMissing);
|
|
1439
|
+
}
|
|
1440
|
+
if (typeof raw !== "string") {
|
|
1441
|
+
throw new services.SeedcordError(services.SeedcordErrorCode.ConfigUnknownExceptionWebhookInvalid);
|
|
1442
|
+
}
|
|
1443
|
+
const value = raw.trim();
|
|
1444
|
+
if (value === "") {
|
|
1445
|
+
throw new services.SeedcordError(services.SeedcordErrorCode.ConfigUnknownExceptionWebhookMissing);
|
|
1446
|
+
}
|
|
1447
|
+
const pattern = String.raw`^https?:\/\/(?:canary\.|ptb\.)?discord(?:app)?\.com\/api\/webhooks\/\d+\/[\w$-]+$`;
|
|
1448
|
+
const discordWebhookRegex = new RegExp(pattern);
|
|
1449
|
+
if (!URL.canParse(value) || !discordWebhookRegex.test(value)) {
|
|
1450
|
+
throw new services.SeedcordError(services.SeedcordErrorCode.ConfigUnknownExceptionWebhookInvalid);
|
|
1451
|
+
}
|
|
1452
|
+
return value;
|
|
1453
|
+
}
|
|
1454
|
+
__name(webhookUrlValidator, "webhookUrlValidator");
|
|
1389
1455
|
exports.UnknownException = class _UnknownException extends WebhookLog {
|
|
1390
1456
|
static {
|
|
1391
1457
|
__name(this, "UnknownException");
|
|
@@ -1425,11 +1491,7 @@ exports.UnknownException = class _UnknownException extends WebhookLog {
|
|
|
1425
1491
|
};
|
|
1426
1492
|
_ts_decorate5([
|
|
1427
1493
|
envapt.Envapt("UNKNOWN_EXCEPTION_WEBHOOK_URL", {
|
|
1428
|
-
converter(raw,
|
|
1429
|
-
if (!raw) throw new Error("Missing UNKNOWN_EXCEPTION_WEBHOOK_URL");
|
|
1430
|
-
if (!URL.canParse(String(raw))) throw new Error("Invalid UNKNOWN_EXCEPTION_WEBHOOK_URL");
|
|
1431
|
-
return raw;
|
|
1432
|
-
}
|
|
1494
|
+
converter: /* @__PURE__ */ __name((raw, fallback) => webhookUrlValidator(raw), "converter")
|
|
1433
1495
|
}),
|
|
1434
1496
|
_ts_metadata5("design:type", String)
|
|
1435
1497
|
], exports.UnknownException, "unknownExceptionWebhookUrl", void 0);
|
|
@@ -1618,7 +1680,7 @@ var Seedcord = class _Seedcord extends Pluggable {
|
|
|
1618
1680
|
* Creates a new Seedcord instance
|
|
1619
1681
|
*
|
|
1620
1682
|
* @param config - Bot configuration including paths and Discord client options
|
|
1621
|
-
* @throws An {@link
|
|
1683
|
+
* @throws An {@link SeedcordError} When attempting to create multiple instances (singleton)
|
|
1622
1684
|
*/
|
|
1623
1685
|
constructor(config) {
|
|
1624
1686
|
const shutdown = new services.CoordinatedShutdown();
|
|
@@ -1627,7 +1689,7 @@ var Seedcord = class _Seedcord extends Pluggable {
|
|
|
1627
1689
|
this.shutdown = shutdown;
|
|
1628
1690
|
this.startup = startup;
|
|
1629
1691
|
if (_Seedcord.isInstantiated) {
|
|
1630
|
-
throw new
|
|
1692
|
+
throw new services.SeedcordError(services.SeedcordErrorCode.CoreSingletonViolation);
|
|
1631
1693
|
}
|
|
1632
1694
|
_Seedcord.isInstantiated = true;
|
|
1633
1695
|
this.effects = new EffectsRegistry(this);
|
|
@@ -1679,7 +1741,7 @@ function EventCatchable(log) {
|
|
|
1679
1741
|
return function(_target, _prop, descriptor) {
|
|
1680
1742
|
const original = descriptor.value;
|
|
1681
1743
|
descriptor.value = async function(...args) {
|
|
1682
|
-
if (!original) throw new
|
|
1744
|
+
if (!original) throw new services.SeedcordError(services.SeedcordErrorCode.DecoratorMethodNotFound);
|
|
1683
1745
|
try {
|
|
1684
1746
|
await original.apply(this, args);
|
|
1685
1747
|
} catch (err) {
|
|
@@ -1703,6 +1765,206 @@ function EventCatchable(log) {
|
|
|
1703
1765
|
};
|
|
1704
1766
|
}
|
|
1705
1767
|
__name(EventCatchable, "EventCatchable");
|
|
1768
|
+
var resolveFactory = /* @__PURE__ */ __name(async (input, ctx) => typeof input === "function" ? await input(ctx) : input, "resolveFactory");
|
|
1769
|
+
var isV2 = /* @__PURE__ */ __name((opts) => "container" in opts, "isV2");
|
|
1770
|
+
var usesResolver = /* @__PURE__ */ __name((opts) => "resolveDecision" in opts, "usesResolver");
|
|
1771
|
+
var usesCustomIds = /* @__PURE__ */ __name((opts) => "confirmCustomIds" in opts, "usesCustomIds");
|
|
1772
|
+
var isMessageComponentIx = /* @__PURE__ */ __name((ix) => "deferUpdate" in ix && "customId" in ix, "isMessageComponentIx");
|
|
1773
|
+
var buildPrompt = /* @__PURE__ */ __name(async (opts, ctx) => {
|
|
1774
|
+
if (isV2(opts)) {
|
|
1775
|
+
const container = await resolveFactory(opts.container, ctx);
|
|
1776
|
+
return {
|
|
1777
|
+
flags: "IsComponentsV2",
|
|
1778
|
+
components: [
|
|
1779
|
+
container.component
|
|
1780
|
+
]
|
|
1781
|
+
};
|
|
1782
|
+
}
|
|
1783
|
+
const prompt = await resolveFactory(opts.prompt, ctx);
|
|
1784
|
+
const rows = await resolveFactory(opts.rows, ctx);
|
|
1785
|
+
const components = [
|
|
1786
|
+
...rows
|
|
1787
|
+
];
|
|
1788
|
+
const payload = {
|
|
1789
|
+
components
|
|
1790
|
+
};
|
|
1791
|
+
if (typeof prompt === "string") payload.content = prompt;
|
|
1792
|
+
else payload.embeds = [
|
|
1793
|
+
prompt.component
|
|
1794
|
+
];
|
|
1795
|
+
return payload;
|
|
1796
|
+
}, "buildPrompt");
|
|
1797
|
+
var clearedPayload = /* @__PURE__ */ __name((opts) => isV2(opts) ? {
|
|
1798
|
+
flags: "IsComponentsV2",
|
|
1799
|
+
components: []
|
|
1800
|
+
} : {
|
|
1801
|
+
components: []
|
|
1802
|
+
}, "clearedPayload");
|
|
1803
|
+
var decide = /* @__PURE__ */ __name(async (opts, i) => {
|
|
1804
|
+
if (usesResolver(opts)) return opts.resolveDecision(i);
|
|
1805
|
+
if (usesCustomIds(opts)) {
|
|
1806
|
+
const { confirmCustomIds, cancelCustomIds = [] } = opts;
|
|
1807
|
+
if (confirmCustomIds.includes(i.customId)) return true;
|
|
1808
|
+
if (cancelCustomIds.includes(i.customId)) return false;
|
|
1809
|
+
}
|
|
1810
|
+
return false;
|
|
1811
|
+
}, "decide");
|
|
1812
|
+
var shouldDefer = /* @__PURE__ */ __name((ix, opts, isSlash, isContext) => {
|
|
1813
|
+
if (ix.deferred) return false;
|
|
1814
|
+
if (opts.defer === false) return false;
|
|
1815
|
+
return isSlash || isContext;
|
|
1816
|
+
}, "shouldDefer");
|
|
1817
|
+
var maybeDefer = /* @__PURE__ */ __name(async (ix, opts, isSlash, isContext) => {
|
|
1818
|
+
if (!shouldDefer(ix, opts, isSlash, isContext)) return;
|
|
1819
|
+
if (isSlash || isContext) {
|
|
1820
|
+
const { ephemeral = true } = opts;
|
|
1821
|
+
const flags = ephemeral ? {
|
|
1822
|
+
flags: "Ephemeral"
|
|
1823
|
+
} : void 0;
|
|
1824
|
+
if (flags) await ix.deferReply(flags);
|
|
1825
|
+
else await ix.deferReply();
|
|
1826
|
+
} else if (isMessageComponentIx(ix)) {
|
|
1827
|
+
await ix.deferUpdate();
|
|
1828
|
+
} else {
|
|
1829
|
+
await ix.deferReply().catch(() => void 0);
|
|
1830
|
+
}
|
|
1831
|
+
}, "maybeDefer");
|
|
1832
|
+
var sendPrompt = /* @__PURE__ */ __name(async (ix, payload, ephemeral, isSlash, isContext) => {
|
|
1833
|
+
if (isSlash || isContext) {
|
|
1834
|
+
if (ix.deferred) return ix.editReply(payload);
|
|
1835
|
+
const reply = {
|
|
1836
|
+
...payload,
|
|
1837
|
+
...ephemeral ? {
|
|
1838
|
+
flags: "Ephemeral"
|
|
1839
|
+
} : {}
|
|
1840
|
+
};
|
|
1841
|
+
await ix.reply(reply);
|
|
1842
|
+
return ix.fetchReply();
|
|
1843
|
+
}
|
|
1844
|
+
const follow = {
|
|
1845
|
+
...payload,
|
|
1846
|
+
...ephemeral ? {
|
|
1847
|
+
flags: "Ephemeral"
|
|
1848
|
+
} : {}
|
|
1849
|
+
};
|
|
1850
|
+
return ix.followUp(follow);
|
|
1851
|
+
}, "sendPrompt");
|
|
1852
|
+
var awaitComponent = /* @__PURE__ */ __name(async (msg, original, opts) => {
|
|
1853
|
+
const componentType = opts.componentType ?? discord_js.ComponentType.Button;
|
|
1854
|
+
const timeoutMs = opts.timeoutMs ?? 1e4;
|
|
1855
|
+
try {
|
|
1856
|
+
const button = await msg.awaitMessageComponent({
|
|
1857
|
+
componentType,
|
|
1858
|
+
time: timeoutMs,
|
|
1859
|
+
filter: /* @__PURE__ */ __name((c) => {
|
|
1860
|
+
if (c.user.id !== original.user.id) return false;
|
|
1861
|
+
if (usesCustomIds(opts)) {
|
|
1862
|
+
const { confirmCustomIds, cancelCustomIds = [] } = opts;
|
|
1863
|
+
return confirmCustomIds.includes(c.customId) || cancelCustomIds.includes(c.customId);
|
|
1864
|
+
}
|
|
1865
|
+
return true;
|
|
1866
|
+
}, "filter")
|
|
1867
|
+
});
|
|
1868
|
+
return {
|
|
1869
|
+
button,
|
|
1870
|
+
timedOut: false
|
|
1871
|
+
};
|
|
1872
|
+
} catch {
|
|
1873
|
+
return {
|
|
1874
|
+
button: null,
|
|
1875
|
+
timedOut: true
|
|
1876
|
+
};
|
|
1877
|
+
}
|
|
1878
|
+
}, "awaitComponent");
|
|
1879
|
+
var clearUi = /* @__PURE__ */ __name(async (ix, msg, opts, isSlash) => {
|
|
1880
|
+
if (!isSlash) {
|
|
1881
|
+
try {
|
|
1882
|
+
await msg.edit(clearedPayload(opts));
|
|
1883
|
+
} catch {
|
|
1884
|
+
await ix.deleteReply(msg).catch(() => void 0);
|
|
1885
|
+
}
|
|
1886
|
+
return;
|
|
1887
|
+
}
|
|
1888
|
+
await ix.editReply(clearedPayload(opts)).catch(() => void 0);
|
|
1889
|
+
}, "clearUi");
|
|
1890
|
+
var normalizeClassicOutcome = /* @__PURE__ */ __name((payload) => ({
|
|
1891
|
+
...payload,
|
|
1892
|
+
components: payload.components ?? []
|
|
1893
|
+
}), "normalizeClassicOutcome");
|
|
1894
|
+
var outcomeReplacement = /* @__PURE__ */ __name(async (opts, ctx, confirmed, timedOut) => {
|
|
1895
|
+
const outcomes = opts.outcomeUi;
|
|
1896
|
+
if (isV2(opts)) {
|
|
1897
|
+
const v2Outcomes = outcomes;
|
|
1898
|
+
if (timedOut) return await resolveFactory(v2Outcomes.onTimeout, ctx);
|
|
1899
|
+
if (!confirmed) return await resolveFactory(v2Outcomes.onCancel, ctx);
|
|
1900
|
+
if (v2Outcomes.onConfirm) return await resolveFactory(v2Outcomes.onConfirm, ctx);
|
|
1901
|
+
return null;
|
|
1902
|
+
}
|
|
1903
|
+
const classicOutcomes = outcomes;
|
|
1904
|
+
if (timedOut) return normalizeClassicOutcome(await resolveFactory(classicOutcomes.onTimeout, ctx));
|
|
1905
|
+
if (!confirmed) return normalizeClassicOutcome(await resolveFactory(classicOutcomes.onCancel, ctx));
|
|
1906
|
+
if (classicOutcomes.onConfirm) {
|
|
1907
|
+
return normalizeClassicOutcome(await resolveFactory(classicOutcomes.onConfirm, ctx));
|
|
1908
|
+
}
|
|
1909
|
+
return null;
|
|
1910
|
+
}, "outcomeReplacement");
|
|
1911
|
+
function Confirmable(question, options) {
|
|
1912
|
+
return function(_target, _propertyKey, descriptor) {
|
|
1913
|
+
const original = descriptor.value;
|
|
1914
|
+
descriptor.value = async function(...args) {
|
|
1915
|
+
if (!original) throw new services.SeedcordError(services.SeedcordErrorCode.DecoratorMethodNotFound);
|
|
1916
|
+
const ix = this.getEvent();
|
|
1917
|
+
const isSlash = ix.isChatInputCommand();
|
|
1918
|
+
const isContext = ix.isContextMenuCommand();
|
|
1919
|
+
const { ephemeral = true } = options;
|
|
1920
|
+
await maybeDefer(ix, options, isSlash, isContext);
|
|
1921
|
+
const q = typeof question === "function" ? await question.apply(this) : question;
|
|
1922
|
+
const ctx = {
|
|
1923
|
+
handler: this,
|
|
1924
|
+
interaction: ix,
|
|
1925
|
+
question: q
|
|
1926
|
+
};
|
|
1927
|
+
const prompt = await buildPrompt(options, ctx);
|
|
1928
|
+
const promptMsg = await sendPrompt(ix, prompt, ephemeral, isSlash, isContext);
|
|
1929
|
+
const { button, timedOut } = await awaitComponent(promptMsg, ix, options);
|
|
1930
|
+
let confirmed = false;
|
|
1931
|
+
if (button) {
|
|
1932
|
+
await button.deferUpdate().catch(() => void 0);
|
|
1933
|
+
confirmed = await decide(options, button);
|
|
1934
|
+
}
|
|
1935
|
+
const replacement = await outcomeReplacement(options, ctx, confirmed, timedOut);
|
|
1936
|
+
if (replacement) {
|
|
1937
|
+
if (isSlash || isContext) {
|
|
1938
|
+
await ix.editReply(replacement).catch(() => void 0);
|
|
1939
|
+
} else {
|
|
1940
|
+
await promptMsg.edit(replacement).catch(async () => {
|
|
1941
|
+
await ix.deleteReply(promptMsg).catch(() => void 0);
|
|
1942
|
+
await ix.followUp(replacement).catch(() => void 0);
|
|
1943
|
+
});
|
|
1944
|
+
}
|
|
1945
|
+
} else {
|
|
1946
|
+
await clearUi(ix, promptMsg, options, isSlash);
|
|
1947
|
+
}
|
|
1948
|
+
if (options.onResolved) {
|
|
1949
|
+
await options.onResolved({
|
|
1950
|
+
confirmed,
|
|
1951
|
+
timedOut,
|
|
1952
|
+
handler: this,
|
|
1953
|
+
interaction: ix,
|
|
1954
|
+
question: q,
|
|
1955
|
+
...button ? {
|
|
1956
|
+
button
|
|
1957
|
+
} : {}
|
|
1958
|
+
});
|
|
1959
|
+
}
|
|
1960
|
+
if (confirmed) {
|
|
1961
|
+
await original.apply(this, args);
|
|
1962
|
+
}
|
|
1963
|
+
};
|
|
1964
|
+
return descriptor;
|
|
1965
|
+
};
|
|
1966
|
+
}
|
|
1967
|
+
__name(Confirmable, "Confirmable");
|
|
1706
1968
|
|
|
1707
1969
|
// src/bot/errors/Channels.ts
|
|
1708
1970
|
var ChannelNotFoundError = class extends CustomError {
|
|
@@ -2068,7 +2330,9 @@ function checkPermissions(client, roleOrChannel, scope = "all", inverse = false)
|
|
|
2068
2330
|
if (roleOrChannel instanceof discord_js.Role) {
|
|
2069
2331
|
permissions = roleOrChannel.permissions;
|
|
2070
2332
|
} else {
|
|
2071
|
-
if (!client.user)
|
|
2333
|
+
if (!client.user) {
|
|
2334
|
+
throw new services.SeedcordError(services.SeedcordErrorCode.CoreClientUserUnavailable);
|
|
2335
|
+
}
|
|
2072
2336
|
permissions = roleOrChannel.permissionsFor(client.user, true);
|
|
2073
2337
|
}
|
|
2074
2338
|
if (!permissions) {
|
|
@@ -2087,12 +2351,16 @@ function checkPermissions(client, roleOrChannel, scope = "all", inverse = false)
|
|
|
2087
2351
|
}
|
|
2088
2352
|
}
|
|
2089
2353
|
__name(checkPermissions, "checkPermissions");
|
|
2090
|
-
|
|
2091
|
-
// src/bot/utilities/roles/getBotRole.ts
|
|
2092
2354
|
function getBotRole(client, guild) {
|
|
2093
|
-
if (!client.user)
|
|
2355
|
+
if (!client.user) {
|
|
2356
|
+
throw new services.SeedcordError(services.SeedcordErrorCode.CoreClientUserUnavailable);
|
|
2357
|
+
}
|
|
2094
2358
|
const botRole = guild.roles.botRoleFor(client.user);
|
|
2095
|
-
if (!botRole)
|
|
2359
|
+
if (!botRole) {
|
|
2360
|
+
throw new services.SeedcordError(services.SeedcordErrorCode.CoreBotRoleMissing, [
|
|
2361
|
+
guild.id
|
|
2362
|
+
]);
|
|
2363
|
+
}
|
|
2096
2364
|
return botRole;
|
|
2097
2365
|
}
|
|
2098
2366
|
__name(getBotRole, "getBotRole");
|
|
@@ -2221,6 +2489,7 @@ exports.ChannelNotTextChannel = ChannelNotTextChannel;
|
|
|
2221
2489
|
exports.Checkable = Checkable;
|
|
2222
2490
|
exports.CommandMetadataKey = CommandMetadataKey;
|
|
2223
2491
|
exports.CommandRegistry = CommandRegistry;
|
|
2492
|
+
exports.Confirmable = Confirmable;
|
|
2224
2493
|
exports.ContextMenuRoute = ContextMenuRoute;
|
|
2225
2494
|
exports.CouldNotFindChannel = CouldNotFindChannel;
|
|
2226
2495
|
exports.CustomError = CustomError;
|
|
@@ -2230,6 +2499,7 @@ exports.EffectsEmitter = EffectsEmitter;
|
|
|
2230
2499
|
exports.EffectsHandler = EffectsHandler;
|
|
2231
2500
|
exports.EffectsRegistry = EffectsRegistry;
|
|
2232
2501
|
exports.EmojiInjector = EmojiInjector;
|
|
2502
|
+
exports.Emojis = Emojis;
|
|
2233
2503
|
exports.EventCatchable = EventCatchable;
|
|
2234
2504
|
exports.EventController = EventController;
|
|
2235
2505
|
exports.EventHandler = EventHandler;
|