@seedcord/gateway 0.7.4 → 0.8.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -11
- package/dist/index.d.mts +43 -37
- package/dist/index.mjs +199 -180
- package/dist/index.mjs.map +1 -1
- package/package.json +17 -16
package/dist/index.mjs
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
import "reflect-metadata";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { DRAIN_TASK_TIMEOUT_MS, DRAIN_WINDOW_MS, HealthCheck, InFlight, ShutdownPhase, StartupPhase, setEnvaptBaseDir, shutdownOf } from "@seedcord/core/node/internal";
|
|
3
|
+
import { WinstonConsoleSink, WinstonFileSink, installNodeConsole } from "@seedcord/logger/node";
|
|
4
|
+
import { COMMAND_DEPLOY_TIMEOUT_MS, CommandRegistry, EventMetadataKey, EventMiddlewareMetadataKey, FixedScope, GateNotice, GatedMetadataKey, HmrManager, InteractionMetadataKey, InteractionMiddlewareMetadataKey, MiddlewareRegistry, MissingPermissions, NoticeCard, PermissionNames, PublishDefault, SubscriberLoader, accessorStore, attachmentsOf, bindBotColor, busLoggerOf, clearStore, connectDevChannel, decodeComponentRoute, deferFlags, eventResultFor, guardedAccessor, interactionMiddleware, interactionRoutesOf, isEmojiTuple, logUnknownFault, outcomeFor, pickNotice, queuedMsFor, readBotToken, reportDispatch, reportedWrite, resultFor, runAfter, runHandlerGates, sendFlags, slowGateMonitor } from "@seedcord/core/internal";
|
|
4
5
|
import { SeedcordErrorCode, paint } from "@seedcord/errors";
|
|
5
|
-
import { SeedcordError, SeedcordTypeError,
|
|
6
|
+
import { SeedcordError, SeedcordTypeError, throwSingleOrAggregate } from "@seedcord/errors/internal";
|
|
6
7
|
import { ArraySourceBase, BaseHandler as BaseHandler$1, BaseReplySender, BuilderComponent, Bus, CursorSourceBase, CustomId, DispatchContext, Fault, InteractionKind, Notice, PaginatorBase, RepliableHandler as RepliableHandler$1, ResolvedEmoji, RowComponent, Silence, Subscriber as Subscriber$1, WebhookLog as WebhookLog$1, assertPermissions, defineGate } from "@seedcord/core";
|
|
7
|
-
import { Logger
|
|
8
|
+
import { Logger } from "@seedcord/logger";
|
|
8
9
|
import { ButtonStyle, Client, ComponentType, DiscordAPIError, Events, GatewayIntentBits, Guild, GuildMember, IntentsBitField, InteractionContextType, Message, MessageFlags, PermissionFlagsBits, RESTJSONErrorCodes, Role, User } from "discord.js";
|
|
9
10
|
import { ButtonBuilder, TextDisplayBuilder } from "@discordjs/builders";
|
|
10
|
-
import { buildSlashRoute } from "@seedcord/utils/internal";
|
|
11
|
+
import { asError, buildSlashRoute, isStringArray } from "@seedcord/utils/internal";
|
|
11
12
|
import { Plugin as Plugin$1 } from "@seedcord/core/plugin";
|
|
12
|
-
import { CoordinatedShutdown, CoordinatedStartup,
|
|
13
|
-
import { CommandRegistry, DRAIN_TASK_TIMEOUT_MS, DRAIN_WINDOW_MS, HealthCheck, ShutdownPhase, StartupPhase, SubscriberLoader, drainInFlight, shutdownOf } from "@seedcord/core/node/internal";
|
|
13
|
+
import { CoordinatedShutdown, CoordinatedStartup, ServerHost } from "@seedcord/core/node";
|
|
14
14
|
import { MemoryRateLimiter } from "@seedcord/rate-limiter";
|
|
15
15
|
import { HostAugmentTarget, HostVersion, SeedcordBrand } from "@seedcord/types/internal";
|
|
16
16
|
import { Envapter } from "envapt";
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import { formatFilePath, hasKeys } from "@seedcord/utils";
|
|
20
|
-
import { traverseDirectory } from "@seedcord/utils/node";
|
|
17
|
+
import { HmrModuleHandler, HmrModuleHandler as HmrModuleHandler$1 } from "@seedcord/core/hmr";
|
|
18
|
+
import { formatFilePath, hasKeys, importFiles } from "@seedcord/utils";
|
|
21
19
|
import * as crypto from "node:crypto";
|
|
22
20
|
import { prefixOf } from "@seedcord/custom-id";
|
|
23
21
|
|
|
@@ -33,8 +31,12 @@ export * from "@seedcord/utils"
|
|
|
33
31
|
|
|
34
32
|
export * from "@seedcord/event-emitter"
|
|
35
33
|
|
|
34
|
+
//#region src/env-bootstrap.ts
|
|
35
|
+
setEnvaptBaseDir();
|
|
36
|
+
|
|
37
|
+
//#endregion
|
|
36
38
|
//#region src/logger-bootstrap.ts
|
|
37
|
-
|
|
39
|
+
installNodeConsole();
|
|
38
40
|
|
|
39
41
|
//#endregion
|
|
40
42
|
//#region src/bot/decorators/Events.ts
|
|
@@ -147,13 +149,13 @@ function Gated(...gates) {
|
|
|
147
149
|
* }
|
|
148
150
|
* ```
|
|
149
151
|
*
|
|
150
|
-
* @throws A **SeedcordTypeError**
|
|
152
|
+
* @throws A **SeedcordTypeError** when `priority` is not a finite number.
|
|
151
153
|
*/
|
|
152
154
|
function RegisterEventMiddleware(options = {}) {
|
|
153
155
|
return function(ctor) {
|
|
154
156
|
const priority = Number(options.priority ?? 0);
|
|
155
|
-
if (!Number.isFinite(priority)) throw new SeedcordTypeError(SeedcordErrorCode.DecoratorInvalidMiddlewarePriority);
|
|
156
|
-
if (options.events?.length === 0) throw new SeedcordTypeError(SeedcordErrorCode.DecoratorEmptyMiddlewareFilter, ["events"]);
|
|
157
|
+
if (!Number.isFinite(priority)) throw new SeedcordTypeError(SeedcordErrorCode.DecoratorInvalidMiddlewarePriority, [ctor.name, String(options.priority)]);
|
|
158
|
+
if (options.events?.length === 0) throw new SeedcordTypeError(SeedcordErrorCode.DecoratorEmptyMiddlewareFilter, [ctor.name, "events"]);
|
|
157
159
|
const metadata = {
|
|
158
160
|
priority,
|
|
159
161
|
...options.events && { events: options.events }
|
|
@@ -271,7 +273,8 @@ var GatewayEmoji = class extends ResolvedEmoji {
|
|
|
271
273
|
const emojiStorage = accessorStore();
|
|
272
274
|
/**
|
|
273
275
|
* The bot's resolved emojis, keyed by {@link EmojiMap}. Filled by {@link EmojiInjector} during startup.
|
|
274
|
-
*
|
|
276
|
+
*
|
|
277
|
+
* @throws A **SeedcordError** when you read a key the injector did not fill.
|
|
275
278
|
*/
|
|
276
279
|
const Emojis = guardedAccessor("Emojis", emojiStorage);
|
|
277
280
|
var EmojiInjector = class {
|
|
@@ -288,19 +291,25 @@ var EmojiInjector = class {
|
|
|
288
291
|
}
|
|
289
292
|
const configEmojis = this.core.config.bot.emojis;
|
|
290
293
|
await this.core.bot.client.application?.emojis.fetch();
|
|
291
|
-
const
|
|
294
|
+
const problems = [];
|
|
292
295
|
const fetchedGuilds = /* @__PURE__ */ new Set();
|
|
293
|
-
for (const [key, value] of Object.entries(configEmojis)) if (isEmojiTuple(value)) await this.resolveTuple(key, value,
|
|
294
|
-
else if (typeof value === "string") this.resolveString(key, value,
|
|
295
|
-
else
|
|
296
|
-
|
|
296
|
+
for (const [key, value] of Object.entries(configEmojis)) if (isEmojiTuple(value)) await this.resolveTuple(key, value, problems, fetchedGuilds);
|
|
297
|
+
else if (typeof value === "string") this.resolveString(key, value, problems);
|
|
298
|
+
else problems.push(new SeedcordTypeError(SeedcordErrorCode.ConfigEmojiInvalid, [key]));
|
|
299
|
+
throwSingleOrAggregate(problems, SeedcordErrorCode.ConfigEmojiUnresolved);
|
|
297
300
|
this.logger.utils.summary("Loaded emojis", { emojis: Object.keys(emojiStorage).length });
|
|
298
301
|
}
|
|
299
|
-
async resolveTuple(key, value,
|
|
302
|
+
async resolveTuple(key, value, problems, fetchedGuilds) {
|
|
300
303
|
const [emojiName, guildId] = value;
|
|
301
304
|
const guild = this.core.bot.client.guilds.cache.get(guildId);
|
|
302
305
|
if (!guild) {
|
|
303
|
-
|
|
306
|
+
problems.push(new SeedcordError(SeedcordErrorCode.ConfigEmojiSourceUnreadable, [
|
|
307
|
+
key,
|
|
308
|
+
emojiName,
|
|
309
|
+
`guild ${guildId}`,
|
|
310
|
+
"discord.js has no cached guild with that id",
|
|
311
|
+
"Check that the bot is in that guild, and that clientOptions.intents includes GatewayIntentBits.Guilds."
|
|
312
|
+
]));
|
|
304
313
|
return;
|
|
305
314
|
}
|
|
306
315
|
if (!fetchedGuilds.has(guildId)) {
|
|
@@ -309,15 +318,23 @@ var EmojiInjector = class {
|
|
|
309
318
|
}
|
|
310
319
|
const guildEmoji = guild.emojis.cache.find((e) => e.name === emojiName);
|
|
311
320
|
if (!guildEmoji) {
|
|
312
|
-
|
|
321
|
+
problems.push(new SeedcordError(SeedcordErrorCode.ConfigEmojiNotFound, [
|
|
322
|
+
key,
|
|
323
|
+
emojiName,
|
|
324
|
+
`guild ${guildId}`
|
|
325
|
+
]));
|
|
313
326
|
return;
|
|
314
327
|
}
|
|
315
328
|
emojiStorage[key] = new GatewayEmoji(guildEmoji);
|
|
316
329
|
}
|
|
317
|
-
resolveString(key, emojiName,
|
|
330
|
+
resolveString(key, emojiName, problems) {
|
|
318
331
|
const appEmoji = this.core.bot.client.application?.emojis.cache.find((e) => e.name === emojiName);
|
|
319
332
|
if (!appEmoji) {
|
|
320
|
-
|
|
333
|
+
problems.push(new SeedcordError(SeedcordErrorCode.ConfigEmojiNotFound, [
|
|
334
|
+
key,
|
|
335
|
+
emojiName,
|
|
336
|
+
"the application"
|
|
337
|
+
]));
|
|
321
338
|
return;
|
|
322
339
|
}
|
|
323
340
|
emojiStorage[key] = new GatewayEmoji(appEmoji);
|
|
@@ -400,7 +417,8 @@ function botRoleOf(guild) {
|
|
|
400
417
|
* Validates that the bot can assign a target role. Refuses when the target role is above the bot's, is managed, or the bot lacks Manage Roles.
|
|
401
418
|
*
|
|
402
419
|
* @param roleOrOptions - Target role or complete options for the check
|
|
403
|
-
* @throws A
|
|
420
|
+
* @throws A {@link Notice} when the check refuses.
|
|
421
|
+
* @throws A **SeedcordError** when the bot has no role in the guild's role cache.
|
|
404
422
|
*
|
|
405
423
|
* @example
|
|
406
424
|
* ```ts
|
|
@@ -763,16 +781,24 @@ var SlashHandler = class extends InteractionHandler {
|
|
|
763
781
|
async match(arms) {
|
|
764
782
|
const route = slashRouteOf(this.event);
|
|
765
783
|
const arm = Object.hasOwn(arms, route) ? arms[route] : void 0;
|
|
766
|
-
if (!arm) throw new SeedcordTypeError(SeedcordErrorCode.
|
|
784
|
+
if (!arm) throw new SeedcordTypeError(SeedcordErrorCode.MatchArmMissing, [
|
|
785
|
+
this.constructor.name,
|
|
786
|
+
"command route",
|
|
787
|
+
route
|
|
788
|
+
]);
|
|
767
789
|
return await arm(this.options);
|
|
768
790
|
}
|
|
769
791
|
};
|
|
770
792
|
|
|
771
793
|
//#endregion
|
|
772
794
|
//#region src/handlers/interaction/ContextMenuHandler.ts
|
|
773
|
-
function armFor(arms, name) {
|
|
795
|
+
function armFor(handler, arms, name) {
|
|
774
796
|
const arm = Object.hasOwn(arms, name) ? arms[name] : void 0;
|
|
775
|
-
if (typeof arm !== "function") throw new SeedcordTypeError(SeedcordErrorCode.
|
|
797
|
+
if (typeof arm !== "function") throw new SeedcordTypeError(SeedcordErrorCode.MatchArmMissing, [
|
|
798
|
+
handler.constructor.name,
|
|
799
|
+
"context menu command",
|
|
800
|
+
name
|
|
801
|
+
]);
|
|
776
802
|
return arm;
|
|
777
803
|
}
|
|
778
804
|
/**
|
|
@@ -832,7 +858,7 @@ var UserContextMenuHandler = class extends InteractionHandler {
|
|
|
832
858
|
* ```
|
|
833
859
|
*/
|
|
834
860
|
async match(arms) {
|
|
835
|
-
return await armFor(arms, this.event.commandName)(this.target, this.targetMember);
|
|
861
|
+
return await armFor(this, arms, this.event.commandName)(this.target, this.targetMember);
|
|
836
862
|
}
|
|
837
863
|
};
|
|
838
864
|
/**
|
|
@@ -887,7 +913,7 @@ var MessageContextMenuHandler = class extends InteractionHandler {
|
|
|
887
913
|
* ```
|
|
888
914
|
*/
|
|
889
915
|
async match(arms) {
|
|
890
|
-
return await armFor(arms, this.event.commandName)(this.target);
|
|
916
|
+
return await armFor(this, arms, this.event.commandName)(this.target);
|
|
891
917
|
}
|
|
892
918
|
};
|
|
893
919
|
|
|
@@ -952,11 +978,11 @@ var AutocompleteHandler = class extends BaseHandler {
|
|
|
952
978
|
*
|
|
953
979
|
* Provide one arm per autocompletable field across the registered commands, keyed by field name. Each
|
|
954
980
|
* arm receives the focused partial value and a `respond` typed to that field's choice value. The
|
|
955
|
-
* arms must cover every autocompletable field
|
|
956
|
-
* focused field with no arm, only reachable from a stale-deployed command, throws at runtime.
|
|
981
|
+
* arms must cover every autocompletable field. A missing field or an unknown key is a compile error.
|
|
957
982
|
*
|
|
958
983
|
* @param arms - One handler per autocompletable field, keyed by field name.
|
|
959
984
|
* @returns The result of the arm that ran.
|
|
985
|
+
* @throws A **SeedcordTypeError** with `MatchArmMissing` when the focused field has no arm. Only a stale-deployed command can send one.
|
|
960
986
|
*
|
|
961
987
|
* @example
|
|
962
988
|
* ```ts
|
|
@@ -975,7 +1001,11 @@ var AutocompleteHandler = class extends BaseHandler {
|
|
|
975
1001
|
const { name, value } = this.focused;
|
|
976
1002
|
const respond = (choices) => this.respond(choices);
|
|
977
1003
|
const arm = Object.hasOwn(arms, name) ? arms[name] : void 0;
|
|
978
|
-
if (!arm) throw new SeedcordTypeError(SeedcordErrorCode.
|
|
1004
|
+
if (!arm) throw new SeedcordTypeError(SeedcordErrorCode.MatchArmMissing, [
|
|
1005
|
+
this.constructor.name,
|
|
1006
|
+
"focused field",
|
|
1007
|
+
name
|
|
1008
|
+
]);
|
|
979
1009
|
return await arm(value, respond);
|
|
980
1010
|
}
|
|
981
1011
|
/** Send autocomplete suggestions, callback type 8. Prefer {@link match}, which restricts each field's choices to its declared type. */
|
|
@@ -1028,10 +1058,11 @@ var ComponentHandler = class extends InteractionHandler {
|
|
|
1028
1058
|
/**
|
|
1029
1059
|
* The decoded params of the single route this handler is registered for.
|
|
1030
1060
|
*
|
|
1031
|
-
* Reading this decodes `this.event.customId` once
|
|
1032
|
-
*
|
|
1033
|
-
*
|
|
1034
|
-
*
|
|
1061
|
+
* Reading this decodes `this.event.customId` once and caches the result. On a handler registered
|
|
1062
|
+
* for several routes this is `never`. Use {@link match} instead.
|
|
1063
|
+
*
|
|
1064
|
+
* @throws A **StaleCustomId** when the wire was encoded under an older shape. The controller boundary turns it into a reply.
|
|
1065
|
+
* @throws An **InvalidCustomId** when the wire is corrupt. The controller boundary turns it into a reply.
|
|
1035
1066
|
*/
|
|
1036
1067
|
get params() {
|
|
1037
1068
|
return this.route.params;
|
|
@@ -1042,12 +1073,14 @@ var ComponentHandler = class extends InteractionHandler {
|
|
|
1042
1073
|
* handler `this.params` is `never`, leaving match as the only way to read the decoded params.
|
|
1043
1074
|
*
|
|
1044
1075
|
* Provide one arm per registered route, keyed by its prefix, and each arm receives that route's own
|
|
1045
|
-
* decoded params. The arms cover every registered route prefix
|
|
1046
|
-
*
|
|
1047
|
-
* corrupt wire throws before an arm body executes.
|
|
1076
|
+
* decoded params. The compiler checks that the arms cover every registered route prefix. `match`
|
|
1077
|
+
* decodes the wire before it runs an arm.
|
|
1048
1078
|
*
|
|
1049
1079
|
* @param arms - One callback per registered route, keyed by prefix.
|
|
1050
1080
|
* @returns The result of the arm that ran.
|
|
1081
|
+
* @throws A **SeedcordTypeError** with `MatchArmMissing` when the wire's prefix has no arm.
|
|
1082
|
+
* @throws A **StaleCustomId** when the wire was encoded under an older shape.
|
|
1083
|
+
* @throws An **InvalidCustomId** when the wire is corrupt.
|
|
1051
1084
|
*
|
|
1052
1085
|
* @example
|
|
1053
1086
|
* ```ts
|
|
@@ -1065,7 +1098,11 @@ var ComponentHandler = class extends InteractionHandler {
|
|
|
1065
1098
|
async match(arms) {
|
|
1066
1099
|
const { prefix, params } = this.route;
|
|
1067
1100
|
const arm = Object.hasOwn(arms, prefix) ? arms[prefix] : void 0;
|
|
1068
|
-
if (!arm) throw new SeedcordTypeError(SeedcordErrorCode.
|
|
1101
|
+
if (!arm) throw new SeedcordTypeError(SeedcordErrorCode.MatchArmMissing, [
|
|
1102
|
+
this.constructor.name,
|
|
1103
|
+
"component route",
|
|
1104
|
+
prefix
|
|
1105
|
+
]);
|
|
1069
1106
|
return await arm(params);
|
|
1070
1107
|
}
|
|
1071
1108
|
};
|
|
@@ -1353,9 +1390,13 @@ var EventHandler = class extends BaseHandler {
|
|
|
1353
1390
|
*/
|
|
1354
1391
|
async match(arms) {
|
|
1355
1392
|
const name = this.firedEvent;
|
|
1356
|
-
if (name === void 0) throw new
|
|
1393
|
+
if (name === void 0) throw new SeedcordError(SeedcordErrorCode.EventNameUnavailable, [this.constructor.name, "match()"]);
|
|
1357
1394
|
const arm = Object.hasOwn(arms, name) ? arms[name] : void 0;
|
|
1358
|
-
if (typeof arm !== "function") throw new SeedcordTypeError(SeedcordErrorCode.
|
|
1395
|
+
if (typeof arm !== "function") throw new SeedcordTypeError(SeedcordErrorCode.MatchArmMissing, [
|
|
1396
|
+
this.constructor.name,
|
|
1397
|
+
"event",
|
|
1398
|
+
name
|
|
1399
|
+
]);
|
|
1359
1400
|
return await arm(...this.getEvent());
|
|
1360
1401
|
}
|
|
1361
1402
|
};
|
|
@@ -1385,7 +1426,7 @@ var EventMiddleware = class extends BaseHandler {
|
|
|
1385
1426
|
* `this.event` directly and does not need this.
|
|
1386
1427
|
*/
|
|
1387
1428
|
get eventName() {
|
|
1388
|
-
if (this.firedEvent === void 0) throw new SeedcordError(SeedcordErrorCode.
|
|
1429
|
+
if (this.firedEvent === void 0) throw new SeedcordError(SeedcordErrorCode.EventNameUnavailable, [this.constructor.name, "this.eventName"]);
|
|
1389
1430
|
return this.firedEvent;
|
|
1390
1431
|
}
|
|
1391
1432
|
};
|
|
@@ -1492,6 +1533,10 @@ var WebhookLog = class extends WebhookLog$1 {};
|
|
|
1492
1533
|
|
|
1493
1534
|
//#endregion
|
|
1494
1535
|
//#region src/Plugin.ts
|
|
1536
|
+
const GATEWAY_SCOPE = {
|
|
1537
|
+
transport: "gateway",
|
|
1538
|
+
runtime: "server"
|
|
1539
|
+
};
|
|
1495
1540
|
/**
|
|
1496
1541
|
* Base class for a gateway plugin, binding `this.core` to the gateway {@link Core}.
|
|
1497
1542
|
*
|
|
@@ -1500,7 +1545,10 @@ var WebhookLog = class extends WebhookLog$1 {};
|
|
|
1500
1545
|
*
|
|
1501
1546
|
* @typeParam Opts - The transport and runtime the plugin declares.
|
|
1502
1547
|
*/
|
|
1503
|
-
var Plugin = class extends Plugin$1 {
|
|
1548
|
+
var Plugin = class extends Plugin$1 {
|
|
1549
|
+
/** @internal */
|
|
1550
|
+
static [FixedScope] = GATEWAY_SCOPE;
|
|
1551
|
+
};
|
|
1504
1552
|
|
|
1505
1553
|
//#endregion
|
|
1506
1554
|
//#region src/miscellaneous/deriveEventActor.ts
|
|
@@ -1635,15 +1683,8 @@ function reportFault(denial, core, fault, uuid) {
|
|
|
1635
1683
|
metadata: metadataFor(fault)
|
|
1636
1684
|
});
|
|
1637
1685
|
}
|
|
1638
|
-
function causeLine(error) {
|
|
1639
|
-
const { cause } = error;
|
|
1640
|
-
if (!Error.isError(cause)) return "";
|
|
1641
|
-
const [first] = cause.message.split("\n");
|
|
1642
|
-
return `\ncaused by ${cause.name}: ${first ?? cause.message}`;
|
|
1643
|
-
}
|
|
1644
1686
|
function reportRawFault(error, core, fault, uuid) {
|
|
1645
|
-
|
|
1646
|
-
else logger$2.error(`${uuid} | ${error.message}${causeLine(error)}`);
|
|
1687
|
+
logUnknownFault(logger$2, uuid, error, core.config.errors);
|
|
1647
1688
|
core.bus[PublishDefault]("unknownException", {
|
|
1648
1689
|
uuid,
|
|
1649
1690
|
dispatchId: fault.dispatch.id,
|
|
@@ -1783,8 +1824,7 @@ var EventDispatcher = class {
|
|
|
1783
1824
|
middlewares = new MiddlewareRegistry(eventMiddleware);
|
|
1784
1825
|
executedOnceHandlers = /* @__PURE__ */ new Set();
|
|
1785
1826
|
attachedEvents = /* @__PURE__ */ new Set();
|
|
1786
|
-
inFlight =
|
|
1787
|
-
draining = false;
|
|
1827
|
+
inFlight = new InFlight(this.logger, "Events");
|
|
1788
1828
|
loading = false;
|
|
1789
1829
|
loadedHandlers = [];
|
|
1790
1830
|
loadedMiddlewares = [];
|
|
@@ -1794,7 +1834,7 @@ var EventDispatcher = class {
|
|
|
1794
1834
|
const eventsDir = this.core.config.bot.events.path;
|
|
1795
1835
|
if (!eventsDir) throw new SeedcordError(SeedcordErrorCode.CoreControllerPathMissing, ["EventDispatcher", "events"]);
|
|
1796
1836
|
if (!Envapter.isDevelopment && !Envapter.isTest) return;
|
|
1797
|
-
this.hmrHandler = new HmrModuleHandler({
|
|
1837
|
+
this.hmrHandler = new HmrModuleHandler$1({
|
|
1798
1838
|
handlersDir: eventsDir,
|
|
1799
1839
|
...hasKeys(this.core.config.bot.events, ["middlewares"]) && { middlewaresDir: this.core.config.bot.events.middlewares },
|
|
1800
1840
|
isHandler: this.isEventHandlerClass.bind(this),
|
|
@@ -1842,22 +1882,18 @@ var EventDispatcher = class {
|
|
|
1842
1882
|
utils.block("Loaded event handlers", [...utils.entries(this.loadedHandlers), ...utils.counts(perEvent)], "debug");
|
|
1843
1883
|
}
|
|
1844
1884
|
async loadHandlers(dir) {
|
|
1845
|
-
await
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
}
|
|
1851
|
-
});
|
|
1885
|
+
for await (const { fullPath, relativePath, imported } of importFiles(dir)) for (const val of Object.values(imported)) {
|
|
1886
|
+
if (!this.isEventHandlerClass(val)) continue;
|
|
1887
|
+
this.registerHandler(val, relativePath);
|
|
1888
|
+
this.hmrHandler?.trackHandler(fullPath, val);
|
|
1889
|
+
}
|
|
1852
1890
|
}
|
|
1853
1891
|
async loadMiddlewares(dir) {
|
|
1854
|
-
await
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
}
|
|
1860
|
-
});
|
|
1892
|
+
for await (const { fullPath, relativePath, imported } of importFiles(dir)) for (const val of Object.values(imported)) {
|
|
1893
|
+
if (!this.isMiddlewareClass(val)) continue;
|
|
1894
|
+
this.registerMiddleware(val, relativePath);
|
|
1895
|
+
this.hmrHandler?.trackMiddleware(fullPath, val);
|
|
1896
|
+
}
|
|
1861
1897
|
}
|
|
1862
1898
|
/** @internal */
|
|
1863
1899
|
async onHmr(event) {
|
|
@@ -1926,7 +1962,7 @@ var EventDispatcher = class {
|
|
|
1926
1962
|
};
|
|
1927
1963
|
if (Array.isArray(raw)) for (const entry of raw) register(entry.event, entry.frequency);
|
|
1928
1964
|
else {
|
|
1929
|
-
const names =
|
|
1965
|
+
const names = isStringArray(raw) ? raw : typeof raw === "string" ? [raw] : [];
|
|
1930
1966
|
for (const name of names) register(name, "on");
|
|
1931
1967
|
}
|
|
1932
1968
|
const from = formatFilePath(relativePath);
|
|
@@ -1944,21 +1980,20 @@ var EventDispatcher = class {
|
|
|
1944
1980
|
const handlerEntries = this.eventMap.get(eventName);
|
|
1945
1981
|
this.logger.debug(`Attaching ${paint.sky.bold(eventName)} to the client with ${paint.mute(handlerEntries?.length ?? 0)} handler(s)`);
|
|
1946
1982
|
this.core.bot.client.on(eventName, (...args) => {
|
|
1947
|
-
if (this.
|
|
1983
|
+
if (this.inFlight.closed) return;
|
|
1948
1984
|
const run = this.processEvent(eventName, args).catch((caught) => {
|
|
1949
1985
|
const error = asError(caught);
|
|
1950
1986
|
this.logger.error(`[${paint.coral.bold("UNHANDLED ERROR AT ROOT")}] ${error.name}`, error.stack);
|
|
1951
1987
|
this.core.bus[PublishDefault]("unhandledEventError", { error });
|
|
1952
1988
|
});
|
|
1953
|
-
this.inFlight.
|
|
1954
|
-
run.finally(() => this.inFlight.delete(run));
|
|
1989
|
+
this.inFlight.track(run);
|
|
1955
1990
|
});
|
|
1956
1991
|
}
|
|
1957
1992
|
stopAccepting() {
|
|
1958
|
-
this.
|
|
1993
|
+
this.inFlight.close();
|
|
1959
1994
|
}
|
|
1960
1995
|
drain(timeoutMs) {
|
|
1961
|
-
return
|
|
1996
|
+
return this.inFlight.drain(timeoutMs);
|
|
1962
1997
|
}
|
|
1963
1998
|
async processEvent(eventName, args) {
|
|
1964
1999
|
const startedAt = performance.now();
|
|
@@ -2125,8 +2160,7 @@ var InteractionDispatcher = class {
|
|
|
2125
2160
|
handlerFiles = /* @__PURE__ */ new Map();
|
|
2126
2161
|
keysToIgnore = /* @__PURE__ */ new Set();
|
|
2127
2162
|
middlewares = new MiddlewareRegistry(interactionMiddleware);
|
|
2128
|
-
inFlight =
|
|
2129
|
-
draining = false;
|
|
2163
|
+
inFlight = new InFlight(this.logger, "Interactions");
|
|
2130
2164
|
loading = false;
|
|
2131
2165
|
loadedHandlers = [];
|
|
2132
2166
|
loadedMiddlewares = [];
|
|
@@ -2139,7 +2173,7 @@ var InteractionDispatcher = class {
|
|
|
2139
2173
|
const interactionsDir = this.core.config.bot.interactions.path;
|
|
2140
2174
|
if (!interactionsDir) throw new SeedcordError(SeedcordErrorCode.CoreControllerPathMissing, ["InteractionDispatcher", "interactions"]);
|
|
2141
2175
|
if (!Envapter.isDevelopment && !Envapter.isTest) return;
|
|
2142
|
-
this.hmrHandler = new HmrModuleHandler({
|
|
2176
|
+
this.hmrHandler = new HmrModuleHandler$1({
|
|
2143
2177
|
handlersDir: interactionsDir,
|
|
2144
2178
|
...hasKeys(this.core.config.bot.interactions, ["middlewares"]) && this.core.config.bot.interactions.middlewares && { middlewaresDir: this.core.config.bot.interactions.middlewares },
|
|
2145
2179
|
isHandler: this.isHandlerClass.bind(this),
|
|
@@ -2205,22 +2239,18 @@ var InteractionDispatcher = class {
|
|
|
2205
2239
|
})], "debug");
|
|
2206
2240
|
}
|
|
2207
2241
|
async loadHandlers(dir) {
|
|
2208
|
-
await
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
}
|
|
2214
|
-
});
|
|
2242
|
+
for await (const { fullPath, relativePath, imported } of importFiles(dir)) for (const val of Object.values(imported)) {
|
|
2243
|
+
if (!this.isHandlerClass(val)) continue;
|
|
2244
|
+
this.registerHandler(val, relativePath);
|
|
2245
|
+
this.hmrHandler?.trackHandler(fullPath, val);
|
|
2246
|
+
}
|
|
2215
2247
|
}
|
|
2216
2248
|
async loadMiddlewares(dir) {
|
|
2217
|
-
await
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
}
|
|
2223
|
-
});
|
|
2249
|
+
for await (const { fullPath, relativePath, imported } of importFiles(dir)) for (const val of Object.values(imported)) {
|
|
2250
|
+
if (!this.isMiddlewareClass(val)) continue;
|
|
2251
|
+
this.registerMiddleware(val, relativePath);
|
|
2252
|
+
this.hmrHandler?.trackMiddleware(fullPath, val);
|
|
2253
|
+
}
|
|
2224
2254
|
}
|
|
2225
2255
|
registerMiddleware(middlewareCtor, relativePath) {
|
|
2226
2256
|
const metadata = this.middlewares.register(middlewareCtor);
|
|
@@ -2244,10 +2274,10 @@ var InteractionDispatcher = class {
|
|
|
2244
2274
|
const writes = [];
|
|
2245
2275
|
for (const [kind, routes] of interactionRoutesOf(handlerClass)) for (const route of routes) {
|
|
2246
2276
|
const existing = this.maps[kind].get(route);
|
|
2247
|
-
if (existing && existing !== handlerClass) throw new
|
|
2277
|
+
if (existing && existing !== handlerClass) throw new SeedcordTypeError(SeedcordErrorCode.CoreDuplicateName, [
|
|
2278
|
+
"route",
|
|
2248
2279
|
`${kind}:${route}`,
|
|
2249
|
-
`${existing.name} (${this.handlerFiles.get(existing) ?? "unknown file"})`,
|
|
2250
|
-
`${handlerClass.name} (${from})`
|
|
2280
|
+
[`${paint.bold(existing.name)} (${paint.path(this.handlerFiles.get(existing) ?? "unknown file")})`, `${paint.bold(handlerClass.name)} (${paint.path(from)})`]
|
|
2251
2281
|
]);
|
|
2252
2282
|
writes.push({
|
|
2253
2283
|
kind,
|
|
@@ -2274,22 +2304,21 @@ var InteractionDispatcher = class {
|
|
|
2274
2304
|
}
|
|
2275
2305
|
attachToClient() {
|
|
2276
2306
|
this.core.bot.client.on(Events.InteractionCreate, (interaction) => {
|
|
2277
|
-
if (this.
|
|
2307
|
+
if (this.inFlight.closed) return;
|
|
2278
2308
|
this.core.bus[PublishDefault]("anyInteraction", { interaction });
|
|
2279
2309
|
const run = this.handleInteraction(interaction).catch((caught) => {
|
|
2280
2310
|
const error = asError(caught);
|
|
2281
2311
|
this.logger.error(`[${paint.coral.bold("UNHANDLED ERROR AT ROOT")}] ${error.name}`, error.stack);
|
|
2282
2312
|
this.core.bus[PublishDefault]("unhandledInteractionError", { error });
|
|
2283
2313
|
});
|
|
2284
|
-
this.inFlight.
|
|
2285
|
-
run.finally(() => this.inFlight.delete(run));
|
|
2314
|
+
this.inFlight.track(run);
|
|
2286
2315
|
});
|
|
2287
2316
|
}
|
|
2288
2317
|
stopAccepting() {
|
|
2289
|
-
this.
|
|
2318
|
+
this.inFlight.close();
|
|
2290
2319
|
}
|
|
2291
2320
|
drain(timeoutMs) {
|
|
2292
|
-
return
|
|
2321
|
+
return this.inFlight.drain(timeoutMs);
|
|
2293
2322
|
}
|
|
2294
2323
|
async handleCustomIdInteraction(interaction, kind) {
|
|
2295
2324
|
if ([...this.keysToIgnore].some((matcher) => matcher.owns(interaction.customId))) return;
|
|
@@ -2487,16 +2516,7 @@ function assertGuildsIntent(intents, commands) {
|
|
|
2487
2516
|
if ((IntentsBitField.resolve(intents) & GatewayIntentBits.Guilds) !== 0) return;
|
|
2488
2517
|
const needing = commands.filter((command) => reachesGuilds(command)).map((command) => command.name);
|
|
2489
2518
|
if (needing.length === 0) return;
|
|
2490
|
-
throw new SeedcordError(SeedcordErrorCode.MissingGuildsIntent, [needing
|
|
2491
|
-
}
|
|
2492
|
-
|
|
2493
|
-
//#endregion
|
|
2494
|
-
//#region \0@oxc-project+runtime@0.152.0/helpers/esm/decorate.js
|
|
2495
|
-
function __decorate(decorators, target, key, desc) {
|
|
2496
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2497
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2498
|
-
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;
|
|
2499
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2519
|
+
throw new SeedcordError(SeedcordErrorCode.MissingGuildsIntent, [needing]);
|
|
2500
2520
|
}
|
|
2501
2521
|
|
|
2502
2522
|
//#endregion
|
|
@@ -2504,16 +2524,19 @@ function __decorate(decorators, target, key, desc) {
|
|
|
2504
2524
|
const UNBIND_TIMEOUT_MS = 2e3;
|
|
2505
2525
|
const LOGOUT_TIMEOUT_MS = 2e3;
|
|
2506
2526
|
const loggerSlot = Symbol("seedcord:bot:logger");
|
|
2507
|
-
const initSlot = Symbol("seedcord:bot:init");
|
|
2508
2527
|
const controllersSlot = Symbol("seedcord:bot:controllers");
|
|
2509
2528
|
/**
|
|
2510
2529
|
* The Discord client and its controllers. Access it through `core.bot`.
|
|
2511
2530
|
*/
|
|
2512
2531
|
var Bot = class {
|
|
2532
|
+
get botToken() {
|
|
2533
|
+
return readBotToken().value;
|
|
2534
|
+
}
|
|
2513
2535
|
#logger = new Logger("Bot", { channel: "bot" });
|
|
2514
2536
|
/** @internal */
|
|
2515
2537
|
[loggerSlot] = this.#logger;
|
|
2516
2538
|
#isInitialized = false;
|
|
2539
|
+
#readyToDeploy = Promise.withResolvers();
|
|
2517
2540
|
#intents;
|
|
2518
2541
|
#client;
|
|
2519
2542
|
#emojiInjector;
|
|
@@ -2534,6 +2557,7 @@ var Bot = class {
|
|
|
2534
2557
|
if (core.config.bot.events.path) this.#events = new EventDispatcher(core);
|
|
2535
2558
|
if (core.config.bot.commands.path) this.#commandRegistry = new CommandRegistry(core);
|
|
2536
2559
|
this.#emojiInjector = new EmojiInjector(core);
|
|
2560
|
+
this.#registerStartupTasks(core);
|
|
2537
2561
|
this.#registerShutdownTasks(core);
|
|
2538
2562
|
}
|
|
2539
2563
|
/** @internal */
|
|
@@ -2550,6 +2574,16 @@ var Bot = class {
|
|
|
2550
2574
|
if (!application) throw new SeedcordError(SeedcordErrorCode.CoreApplicationUnavailable);
|
|
2551
2575
|
return application.id;
|
|
2552
2576
|
}
|
|
2577
|
+
#registerStartupTasks(core) {
|
|
2578
|
+
core.startup.addTask(StartupPhase.Login, "bot-initialization", async (signal) => {
|
|
2579
|
+
this.#logger.utils.initialization("Bot", "start");
|
|
2580
|
+
await this.#init(signal);
|
|
2581
|
+
this.#logger.utils.initialization("Bot", "end");
|
|
2582
|
+
});
|
|
2583
|
+
const registry = this.#commandRegistry;
|
|
2584
|
+
if (!registry) return;
|
|
2585
|
+
core.startup.addTask(StartupPhase.Login, "command-deploy", (signal) => this.#deployCommands(registry, signal), COMMAND_DEPLOY_TIMEOUT_MS);
|
|
2586
|
+
}
|
|
2553
2587
|
#registerShutdownTasks(core) {
|
|
2554
2588
|
core.shutdown.addTask(ShutdownPhase.Unbind, "stop-dispatch", () => {
|
|
2555
2589
|
this.#stopAccepting();
|
|
@@ -2565,21 +2599,28 @@ var Bot = class {
|
|
|
2565
2599
|
async #drain() {
|
|
2566
2600
|
await Promise.allSettled([this.#interactions?.drain(DRAIN_WINDOW_MS), this.#events?.drain(DRAIN_WINDOW_MS)]);
|
|
2567
2601
|
}
|
|
2568
|
-
|
|
2569
|
-
async [initSlot]() {
|
|
2602
|
+
async #init(signal) {
|
|
2570
2603
|
if (this.#isInitialized) return;
|
|
2571
2604
|
this.#isInitialized = true;
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2605
|
+
signal.addEventListener("abort", () => this.#readyToDeploy.resolve(false), { once: true });
|
|
2606
|
+
try {
|
|
2607
|
+
const token = this.botToken;
|
|
2608
|
+
if (this.#interactions) await this.#interactions.init();
|
|
2609
|
+
if (this.#events) await this.#events.init();
|
|
2610
|
+
await this.#login(token);
|
|
2611
|
+
await this.#emojiInjector.init();
|
|
2612
|
+
} catch (error) {
|
|
2613
|
+
this.#readyToDeploy.resolve(false);
|
|
2614
|
+
throw error;
|
|
2615
|
+
}
|
|
2616
|
+
this.#readyToDeploy.resolve(true);
|
|
2617
|
+
}
|
|
2618
|
+
async #deployCommands(registry, signal) {
|
|
2619
|
+
if (!await this.#readyToDeploy.promise) return;
|
|
2620
|
+
await registry.deploy(signal, {
|
|
2621
|
+
routes: this.#interactions,
|
|
2622
|
+
check: (commands) => assertGuildsIntent(this.#intents, commands)
|
|
2623
|
+
});
|
|
2583
2624
|
}
|
|
2584
2625
|
async #stop() {
|
|
2585
2626
|
this.#client.removeAllListeners();
|
|
@@ -2601,18 +2642,11 @@ var Bot = class {
|
|
|
2601
2642
|
return this.#client;
|
|
2602
2643
|
}
|
|
2603
2644
|
};
|
|
2604
|
-
__decorate([Envapt("DISCORD_BOT_TOKEN", { converter: (raw) => validateDiscordToken(raw) })], Bot.prototype, "botToken", void 0);
|
|
2605
|
-
function botLoggerOf(bot) {
|
|
2606
|
-
return bot[loggerSlot];
|
|
2607
|
-
}
|
|
2608
|
-
function initBot(bot) {
|
|
2609
|
-
return bot[initSlot]();
|
|
2610
|
-
}
|
|
2611
2645
|
|
|
2612
2646
|
//#endregion
|
|
2613
2647
|
//#region src/version.ts
|
|
2614
2648
|
/** Package version */
|
|
2615
|
-
const version = "0.
|
|
2649
|
+
const version = "0.8.0-next.0";
|
|
2616
2650
|
|
|
2617
2651
|
//#endregion
|
|
2618
2652
|
//#region src/Seedcord.ts
|
|
@@ -2620,7 +2654,7 @@ const version = "0.7.4";
|
|
|
2620
2654
|
* The gateway bot host. Opens a discord.js gateway session, discovers handlers, and runs
|
|
2621
2655
|
* coordinated startup and shutdown. Attach plugins with `attach()`.
|
|
2622
2656
|
*/
|
|
2623
|
-
var Seedcord = class
|
|
2657
|
+
var Seedcord = class extends ServerHost {
|
|
2624
2658
|
config;
|
|
2625
2659
|
/** @internal */
|
|
2626
2660
|
[SeedcordBrand] = true;
|
|
@@ -2628,11 +2662,11 @@ var Seedcord = class Seedcord extends Pluggable {
|
|
|
2628
2662
|
[HostAugmentTarget] = "@seedcord/gateway";
|
|
2629
2663
|
/** @internal */
|
|
2630
2664
|
[HostVersion] = version;
|
|
2631
|
-
healthCheck;
|
|
2632
|
-
hmrManager;
|
|
2665
|
+
#healthCheck;
|
|
2666
|
+
#hmrManager;
|
|
2633
2667
|
/** @see {@link Bus} */
|
|
2634
2668
|
bus;
|
|
2635
|
-
subscribers;
|
|
2669
|
+
#subscribers;
|
|
2636
2670
|
/** @see {@link Bot} */
|
|
2637
2671
|
bot;
|
|
2638
2672
|
/** The discord.js client's REST client. Its token is set during the Login phase. */
|
|
@@ -2645,76 +2679,61 @@ var Seedcord = class Seedcord extends Pluggable {
|
|
|
2645
2679
|
rateLimiter;
|
|
2646
2680
|
/**
|
|
2647
2681
|
* @param config - Bot configuration including paths and Discord client options
|
|
2648
|
-
* @throws A **SeedcordError**
|
|
2682
|
+
* @throws A **SeedcordError** when another `Seedcord` exists in this process and has not shut down.
|
|
2683
|
+
* @throws A **SeedcordError** when the running Node or Bun is older than the range in `engines`.
|
|
2649
2684
|
*/
|
|
2650
2685
|
constructor(config) {
|
|
2651
|
-
super(new CoordinatedShutdown(config.lifecycle?.shutdownDeadline), new CoordinatedStartup());
|
|
2686
|
+
super("gateway", new CoordinatedShutdown(config.lifecycle?.shutdownDeadline), new CoordinatedStartup());
|
|
2652
2687
|
this.config = config;
|
|
2653
|
-
installNodeDefaults(config.logger);
|
|
2654
2688
|
bindBotColor(() => this.config.botColor);
|
|
2655
|
-
this
|
|
2656
|
-
this
|
|
2689
|
+
this.#hmrManager = new HmrManager();
|
|
2690
|
+
this.#hmrManager.init(connectDevChannel());
|
|
2657
2691
|
this.bus = new Bus(this);
|
|
2658
|
-
this
|
|
2692
|
+
this.#subscribers = new SubscriberLoader(this.bus, config.subscribers.path);
|
|
2659
2693
|
this.bot = new Bot(this);
|
|
2660
2694
|
this.rest = this.bot.client.rest;
|
|
2661
2695
|
this.rateLimiter = config.store ?? new MemoryRateLimiter();
|
|
2662
|
-
this
|
|
2663
|
-
this
|
|
2696
|
+
this.#healthCheck = HealthCheck.fromOption(shutdownOf(this), config.healthCheck);
|
|
2697
|
+
this.#registerStartupTasks();
|
|
2664
2698
|
}
|
|
2665
2699
|
/** The bot's discord username, populated after login. */
|
|
2666
2700
|
get username() {
|
|
2667
2701
|
return this.bot.client.user?.username;
|
|
2668
2702
|
}
|
|
2669
|
-
|
|
2670
|
-
if (
|
|
2671
|
-
LoggerChannelRegistry.instance.configure({});
|
|
2672
|
-
return true;
|
|
2673
|
-
}
|
|
2674
|
-
registerStartupTasks() {
|
|
2675
|
-
if (Envapter.isDevelopment || Envapter.isTest) this.registerHmrAwareModules();
|
|
2703
|
+
#registerStartupTasks() {
|
|
2704
|
+
if (Envapter.isDevelopment || Envapter.isTest) this.#registerHmrAwareModules();
|
|
2676
2705
|
this.startup.addTask(StartupPhase.Configuration, "bus-initialization", async () => {
|
|
2677
2706
|
busLoggerOf(this.bus).utils.initialization("Subscribers", "start");
|
|
2678
|
-
await this
|
|
2707
|
+
await this.#subscribers.init();
|
|
2679
2708
|
busLoggerOf(this.bus).utils.initialization("Subscribers", "end");
|
|
2680
2709
|
});
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
await healthCheck.init();
|
|
2690
|
-
healthCheck.logger.utils.initialization("HealthCheck", "end");
|
|
2691
|
-
});
|
|
2710
|
+
}
|
|
2711
|
+
/** @internal */
|
|
2712
|
+
async openHealth() {
|
|
2713
|
+
const healthCheck = this.#healthCheck;
|
|
2714
|
+
if (!healthCheck) return;
|
|
2715
|
+
healthCheck.logger.utils.initialization("HealthCheck", "start");
|
|
2716
|
+
await healthCheck.init();
|
|
2717
|
+
healthCheck.logger.utils.initialization("HealthCheck", "end");
|
|
2692
2718
|
}
|
|
2693
2719
|
/**
|
|
2694
2720
|
* Starts the bot and runs all initialization tasks
|
|
2695
2721
|
*
|
|
2696
2722
|
* @returns This Seedcord instance when initialized
|
|
2697
2723
|
*/
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
await super.init();
|
|
2701
|
-
} catch (caught) {
|
|
2702
|
-
await shutdownOf(this).run(1, false);
|
|
2703
|
-
Seedcord.reset(this);
|
|
2704
|
-
throw caught;
|
|
2705
|
-
}
|
|
2706
|
-
return this;
|
|
2724
|
+
start() {
|
|
2725
|
+
return this.init();
|
|
2707
2726
|
}
|
|
2708
|
-
registerHmrAwareModules() {
|
|
2727
|
+
#registerHmrAwareModules() {
|
|
2709
2728
|
this.startup.addTask(StartupPhase.Configuration, "hmr-registration", async () => {
|
|
2710
|
-
this
|
|
2711
|
-
this
|
|
2712
|
-
for (const
|
|
2729
|
+
this.#hmrManager.register(this.bot);
|
|
2730
|
+
this.#hmrManager.register(this.#subscribers);
|
|
2731
|
+
for (const { instance } of attachmentsOf(this)) this.#hmrManager.register(instance);
|
|
2713
2732
|
await Promise.resolve();
|
|
2714
2733
|
});
|
|
2715
2734
|
}
|
|
2716
2735
|
};
|
|
2717
2736
|
|
|
2718
2737
|
//#endregion
|
|
2719
|
-
export { ArraySource, AutocompleteHandler, BaseHandler, ButtonHandler, ChannelMenuHandler, ComponentHandler, CursorSource, Emojis, EventHandler, EventMiddleware, Gated, GatewayEmoji, IgnoreBots, InteractionHandler, InteractionMiddleware, MentionableMenuHandler, MessageContextMenuHandler, ModalHandler, Nsfw, Paginator, Plugin, RegisterEvent, RegisterEventMiddleware, RepliableHandler, ReplySender, RoleMenuHandler, Seedcord, SelectMenuHandler, SlashHandler, StringMenuHandler, Subscriber, UserContextMenuHandler, UserMenuHandler, WebhookLog, WinstonConsoleSink, WinstonFileSink, checkBotPermissions, checkPermissions, getConfirmation, hasPermsToAssign, version };
|
|
2738
|
+
export { ArraySource, AutocompleteHandler, BaseHandler, ButtonHandler, ChannelMenuHandler, ComponentHandler, CursorSource, Emojis, EventHandler, EventMiddleware, Gated, GatewayEmoji, HmrModuleHandler, IgnoreBots, InteractionHandler, InteractionMiddleware, MentionableMenuHandler, MessageContextMenuHandler, ModalHandler, Nsfw, Paginator, Plugin, RegisterEvent, RegisterEventMiddleware, RepliableHandler, ReplySender, RoleMenuHandler, Seedcord, SelectMenuHandler, SlashHandler, StringMenuHandler, Subscriber, UserContextMenuHandler, UserMenuHandler, WebhookLog, WinstonConsoleSink, WinstonFileSink, checkBotPermissions, checkPermissions, getConfirmation, hasPermsToAssign, version };
|
|
2720
2739
|
//# sourceMappingURL=index.mjs.map
|