seyfert 4.4.1 → 5.0.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 +7 -1
- package/lib/api/Routes/cdn.d.ts +2 -2
- package/lib/api/Routes/guilds.d.ts +2 -2
- package/lib/api/Routes/invites.d.ts +2 -2
- package/lib/api/api.d.ts +20 -8
- package/lib/api/api.js +198 -44
- package/lib/api/shared.d.ts +30 -1
- package/lib/api/utils/constants.d.ts +1 -1
- package/lib/api/utils/constants.js +1 -1
- package/lib/api/utils/utils.d.ts +2 -1
- package/lib/api/utils/utils.js +1 -1
- package/lib/builders/Attachment.d.ts +1 -1
- package/lib/builders/Attachment.js +30 -8
- package/lib/builders/MediaGallery.d.ts +2 -2
- package/lib/builders/MediaGallery.js +10 -0
- package/lib/builders/Modal.d.ts +18 -8
- package/lib/builders/Modal.js +36 -7
- package/lib/builders/Poll.js +18 -0
- package/lib/builders/RadioGroup.d.ts +4 -3
- package/lib/builders/RadioGroup.js +24 -3
- package/lib/builders/SelectMenu.d.ts +8 -6
- package/lib/builders/SelectMenu.js +24 -3
- package/lib/builders/types.d.ts +3 -2
- package/lib/cache/adapters/default.d.ts +1 -1
- package/lib/cache/adapters/default.js +23 -26
- package/lib/cache/adapters/limited.d.ts +1 -0
- package/lib/cache/adapters/limited.js +47 -33
- package/lib/cache/index.d.ts +19 -25
- package/lib/cache/index.js +58 -6
- package/lib/cache/resources/bans.d.ts +1 -1
- package/lib/cache/resources/bans.js +4 -4
- package/lib/cache/resources/channels.d.ts +1 -1
- package/lib/cache/resources/channels.js +4 -4
- package/lib/cache/resources/default/base.d.ts +1 -1
- package/lib/cache/resources/default/base.js +8 -8
- package/lib/cache/resources/default/guild-based.d.ts +5 -5
- package/lib/cache/resources/default/guild-based.js +29 -16
- package/lib/cache/resources/default/guild-related.d.ts +5 -5
- package/lib/cache/resources/default/guild-related.js +14 -14
- package/lib/cache/resources/emojis.d.ts +1 -1
- package/lib/cache/resources/emojis.js +4 -4
- package/lib/cache/resources/guilds.js +28 -15
- package/lib/cache/resources/members.d.ts +1 -1
- package/lib/cache/resources/members.js +6 -6
- package/lib/cache/resources/messages.d.ts +7 -2
- package/lib/cache/resources/messages.js +43 -20
- package/lib/cache/resources/overwrites.d.ts +1 -1
- package/lib/cache/resources/overwrites.js +5 -8
- package/lib/cache/resources/roles.d.ts +1 -1
- package/lib/cache/resources/roles.js +4 -4
- package/lib/cache/resources/stickers.d.ts +1 -1
- package/lib/cache/resources/stickers.js +4 -4
- package/lib/cache/resources/users.js +4 -4
- package/lib/cache/resources/voice-states.d.ts +1 -1
- package/lib/cache/resources/voice-states.js +4 -4
- package/lib/client/base.d.ts +83 -24
- package/lib/client/base.js +594 -39
- package/lib/client/client.d.ts +29 -4
- package/lib/client/client.js +38 -13
- package/lib/client/collectors.d.ts +9 -8
- package/lib/client/collectors.js +19 -52
- package/lib/client/httpclient.d.ts +3 -0
- package/lib/client/index.d.ts +3 -1
- package/lib/client/index.js +4 -0
- package/lib/client/intents.d.ts +3 -0
- package/lib/client/intents.js +9 -0
- package/lib/client/plugins/api.d.ts +4 -0
- package/lib/client/plugins/api.js +550 -0
- package/lib/client/plugins/errors.d.ts +25 -0
- package/lib/client/plugins/errors.js +79 -0
- package/lib/client/plugins/order.d.ts +10 -0
- package/lib/client/plugins/order.js +32 -0
- package/lib/client/plugins/registry.d.ts +273 -0
- package/lib/client/plugins/registry.js +868 -0
- package/lib/client/plugins/shared.d.ts +23 -0
- package/lib/client/plugins/shared.js +193 -0
- package/lib/client/plugins/types.d.ts +398 -0
- package/lib/client/plugins/types.js +8 -0
- package/lib/client/plugins.d.ts +78 -0
- package/lib/client/plugins.js +558 -0
- package/lib/client/transformers.d.ts +33 -33
- package/lib/client/workerclient.d.ts +11 -2
- package/lib/client/workerclient.js +33 -22
- package/lib/collection.d.ts +10 -8
- package/lib/collection.js +19 -25
- package/lib/commands/applications/chat.d.ts +20 -18
- package/lib/commands/applications/chat.js +39 -14
- package/lib/commands/applications/chatcontext.d.ts +23 -15
- package/lib/commands/applications/chatcontext.js +23 -2
- package/lib/commands/applications/entryPoint.d.ts +4 -3
- package/lib/commands/applications/entryPoint.js +1 -1
- package/lib/commands/applications/entrycontext.d.ts +7 -9
- package/lib/commands/applications/entrycontext.js +3 -1
- package/lib/commands/applications/menu.d.ts +4 -3
- package/lib/commands/applications/menucontext.d.ts +7 -9
- package/lib/commands/applications/menucontext.js +3 -1
- package/lib/commands/applications/options.d.ts +23 -23
- package/lib/commands/applications/shared.d.ts +39 -17
- package/lib/commands/decorators.d.ts +50 -38
- package/lib/commands/decorators.js +15 -5
- package/lib/commands/handle.d.ts +19 -8
- package/lib/commands/handle.js +224 -143
- package/lib/commands/handler.d.ts +21 -8
- package/lib/commands/handler.js +157 -69
- package/lib/commands/index.d.ts +1 -0
- package/lib/commands/optionresolver.d.ts +2 -2
- package/lib/common/it/colors.js +12 -2
- package/lib/common/it/error.d.ts +9 -0
- package/lib/common/it/error.js +8 -0
- package/lib/common/it/fake-promise.d.ts +4 -0
- package/lib/common/it/fake-promise.js +10 -0
- package/lib/common/it/formatter.d.ts +14 -11
- package/lib/common/it/formatter.js +4 -3
- package/lib/common/it/logger.d.ts +7 -1
- package/lib/common/it/logger.js +24 -6
- package/lib/common/it/utils.d.ts +6 -8
- package/lib/common/it/utils.js +44 -42
- package/lib/common/shorters/application.d.ts +3 -3
- package/lib/common/shorters/application.js +3 -2
- package/lib/common/shorters/bans.d.ts +8 -4
- package/lib/common/shorters/bans.js +13 -5
- package/lib/common/shorters/channels.d.ts +4 -4
- package/lib/common/shorters/channels.js +4 -4
- package/lib/common/shorters/emojis.js +1 -0
- package/lib/common/shorters/guilds.d.ts +8 -8
- package/lib/common/shorters/guilds.js +14 -31
- package/lib/common/shorters/interaction.d.ts +1 -1
- package/lib/common/shorters/invites.d.ts +201 -201
- package/lib/common/shorters/members.d.ts +7 -7
- package/lib/common/shorters/members.js +13 -14
- package/lib/common/shorters/messages.d.ts +2 -2
- package/lib/common/shorters/soundboard.d.ts +5 -5
- package/lib/common/shorters/users.d.ts +1 -1
- package/lib/common/shorters/webhook.d.ts +3 -2
- package/lib/common/shorters/webhook.js +0 -7
- package/lib/common/types/options.d.ts +4 -0
- package/lib/common/types/util.d.ts +8 -0
- package/lib/common/types/write.d.ts +2 -1
- package/lib/components/BaseSelectMenuComponent.d.ts +1 -1
- package/lib/components/BaseSelectMenuComponent.js +1 -1
- package/lib/components/ButtonComponent.d.ts +3 -3
- package/lib/components/ChannelSelectMenuComponent.d.ts +2 -2
- package/lib/components/File.d.ts +1 -1
- package/lib/components/MediaGallery.d.ts +1 -1
- package/lib/components/MentionableSelectMenuComponent.d.ts +1 -1
- package/lib/components/RoleSelectMenuComponent.d.ts +1 -1
- package/lib/components/Separator.d.ts +1 -1
- package/lib/components/StringSelectMenuComponent.d.ts +1 -1
- package/lib/components/TextInputComponent.d.ts +1 -1
- package/lib/components/Thumbnail.d.ts +1 -1
- package/lib/components/UserSelectMenuComponent.d.ts +1 -1
- package/lib/components/componentcommand.d.ts +8 -7
- package/lib/components/componentcontext.d.ts +24 -36
- package/lib/components/componentcontext.js +7 -17
- package/lib/components/handler.d.ts +17 -7
- package/lib/components/handler.js +108 -49
- package/lib/components/index.d.ts +1 -0
- package/lib/components/index.js +1 -0
- package/lib/components/interactioncontext.d.ts +45 -0
- package/lib/components/interactioncontext.js +93 -0
- package/lib/components/modalcommand.d.ts +5 -4
- package/lib/components/modalcontext.d.ts +39 -20
- package/lib/components/modalcontext.js +59 -6
- package/lib/events/event.d.ts +9 -3
- package/lib/events/handler.d.ts +51 -6
- package/lib/events/handler.js +165 -36
- package/lib/events/hooks/application_command.d.ts +1 -1
- package/lib/events/hooks/auto_moderation.d.ts +2 -2
- package/lib/events/hooks/guild.d.ts +150 -150
- package/lib/events/hooks/interactions.d.ts +1 -1
- package/lib/events/hooks/invite.d.ts +20 -20
- package/lib/events/hooks/message.d.ts +27 -27
- package/lib/events/hooks/presence.d.ts +11 -11
- package/lib/events/hooks/soundboard.d.ts +6 -6
- package/lib/events/hooks/stage.d.ts +2 -2
- package/lib/events/hooks/subscriptions.d.ts +3 -3
- package/lib/events/hooks/thread.d.ts +30 -30
- package/lib/events/hooks/voice.d.ts +3 -4
- package/lib/events/hooks/voice.js +2 -1
- package/lib/events/utils.d.ts +4 -0
- package/lib/events/utils.js +59 -0
- package/lib/index.d.ts +9 -4
- package/lib/index.js +14 -8
- package/lib/langs/handler.d.ts +14 -11
- package/lib/langs/handler.js +46 -9
- package/lib/langs/router.d.ts +10 -3
- package/lib/structures/Application.d.ts +1 -1
- package/lib/structures/Emoji.d.ts +3 -3
- package/lib/structures/Emoji.js +2 -2
- package/lib/structures/Guild.d.ts +154 -154
- package/lib/structures/GuildBan.d.ts +4 -4
- package/lib/structures/GuildBan.js +3 -3
- package/lib/structures/GuildMember.d.ts +7 -7
- package/lib/structures/GuildMember.js +28 -7
- package/lib/structures/GuildRole.d.ts +1 -1
- package/lib/structures/GuildRole.js +2 -2
- package/lib/structures/Interaction.d.ts +11 -9
- package/lib/structures/Interaction.js +33 -12
- package/lib/structures/Message.d.ts +21 -14
- package/lib/structures/Message.js +29 -14
- package/lib/structures/User.d.ts +1 -1
- package/lib/structures/VoiceState.d.ts +4 -0
- package/lib/structures/VoiceState.js +13 -1
- package/lib/structures/Webhook.d.ts +9 -1
- package/lib/structures/Webhook.js +4 -1
- package/lib/structures/channels.d.ts +148 -134
- package/lib/structures/channels.js +27 -26
- package/lib/structures/extra/BitField.d.ts +4 -4
- package/lib/structures/extra/BitField.js +20 -4
- package/lib/structures/extra/DiscordBase.js +1 -1
- package/lib/structures/extra/Permissions.d.ts +2 -4
- package/lib/structures/extra/Permissions.js +1 -17
- package/lib/types/payloads/_interactions/responses.d.ts +2 -2
- package/lib/types/payloads/components.d.ts +4 -4
- package/lib/websocket/SharedTypes.d.ts +4 -4
- package/lib/websocket/constants/index.d.ts +1 -1
- package/lib/websocket/constants/index.js +3 -2
- package/lib/websocket/discord/events/memberUpdate.js +2 -2
- package/lib/websocket/discord/heartbeater.d.ts +1 -0
- package/lib/websocket/discord/heartbeater.js +7 -0
- package/lib/websocket/discord/shard.d.ts +2 -2
- package/lib/websocket/discord/shard.js +16 -14
- package/lib/websocket/discord/sharder.d.ts +8 -7
- package/lib/websocket/discord/sharder.js +26 -6
- package/lib/websocket/discord/shared.d.ts +19 -6
- package/lib/websocket/discord/socket/custom.js +5 -0
- package/lib/websocket/discord/worker.d.ts +1 -0
- package/lib/websocket/discord/worker.js +2 -0
- package/lib/websocket/discord/workermanager.d.ts +25 -11
- package/lib/websocket/discord/workermanager.js +41 -10
- package/package.json +13 -17
package/lib/client/base.js
CHANGED
|
@@ -6,6 +6,7 @@ const node_path_1 = require("node:path");
|
|
|
6
6
|
const api_1 = require("../api");
|
|
7
7
|
const utils_1 = require("../api/utils/utils");
|
|
8
8
|
const cache_1 = require("../cache");
|
|
9
|
+
const commands_1 = require("../commands");
|
|
9
10
|
const shared_1 = require("../commands/applications/shared");
|
|
10
11
|
const handle_1 = require("../commands/handle");
|
|
11
12
|
const handler_1 = require("../commands/handler");
|
|
@@ -14,8 +15,29 @@ const utils_2 = require("../common/it/utils");
|
|
|
14
15
|
const bans_1 = require("../common/shorters/bans");
|
|
15
16
|
const soundboard_1 = require("../common/shorters/soundboard");
|
|
16
17
|
const voiceStates_1 = require("../common/shorters/voiceStates");
|
|
18
|
+
const components_1 = require("../components");
|
|
17
19
|
const handler_2 = require("../components/handler");
|
|
20
|
+
const events_1 = require("../events");
|
|
18
21
|
const handler_3 = require("../langs/handler");
|
|
22
|
+
const types_1 = require("../types");
|
|
23
|
+
const intents_1 = require("./intents");
|
|
24
|
+
const plugins_1 = require("./plugins");
|
|
25
|
+
const errors_1 = require("./plugins/errors");
|
|
26
|
+
const order_1 = require("./plugins/order");
|
|
27
|
+
const registry_1 = require("./plugins/registry");
|
|
28
|
+
const shared_2 = require("./plugins/shared");
|
|
29
|
+
const pluginSourceKey = '__seyfertPluginSource';
|
|
30
|
+
function componentIdentity(kind, customId) {
|
|
31
|
+
return `${kind}:${customId}`;
|
|
32
|
+
}
|
|
33
|
+
function capitalizePluginKind(kind) {
|
|
34
|
+
return kind[0].toUpperCase() + kind.slice(1);
|
|
35
|
+
}
|
|
36
|
+
function commandIdentity(command) {
|
|
37
|
+
const guildId = 'guildId' in command ? command.guildId : undefined;
|
|
38
|
+
const guildScope = Array.isArray(guildId) ? [...guildId].sort().join(',') : (guildId ?? '*');
|
|
39
|
+
return `${command.type}:${command.name}:${guildScope}`;
|
|
40
|
+
}
|
|
19
41
|
class BaseClient {
|
|
20
42
|
rest = new api_1.ApiHandler({ token: 'INVALID' });
|
|
21
43
|
cache = new cache_1.Cache(0, new cache_1.MemoryAdapter(), {}, this);
|
|
@@ -50,11 +72,24 @@ class BaseClient {
|
|
|
50
72
|
static getBotIdFromToken(token) {
|
|
51
73
|
return Buffer.from(token.split('.')[0], 'base64').toString('ascii');
|
|
52
74
|
}
|
|
75
|
+
plugins = [];
|
|
76
|
+
shared;
|
|
77
|
+
events = new events_1.CustomEventHandler(this);
|
|
78
|
+
/** @internal */
|
|
79
|
+
pluginRegistry;
|
|
80
|
+
pluginsSetupPromise;
|
|
81
|
+
pluginsClosePromise;
|
|
82
|
+
langBaseValues = {};
|
|
83
|
+
pluginCacheDisabledCache = {};
|
|
84
|
+
pluginBaseGatewayIntents = this.cache.intents;
|
|
85
|
+
pluginComponentsBeforeLoadDepth = 0;
|
|
53
86
|
options;
|
|
54
87
|
/**@internal */
|
|
55
88
|
static _seyfertCfWorkerConfig;
|
|
89
|
+
/**@internal */
|
|
90
|
+
_rcCache;
|
|
56
91
|
constructor(options) {
|
|
57
|
-
|
|
92
|
+
const defaults = {
|
|
58
93
|
commands: {
|
|
59
94
|
defaults: {
|
|
60
95
|
onRunError(context, error) {
|
|
@@ -85,8 +120,8 @@ class BaseClient {
|
|
|
85
120
|
onMiddlewaresError(context, error) {
|
|
86
121
|
context.client.logger.fatal('ComponentCommand.<onMiddlewaresError>', context.author.id, error);
|
|
87
122
|
},
|
|
88
|
-
onInternalError(client, error) {
|
|
89
|
-
client.logger.fatal(error);
|
|
123
|
+
onInternalError(client, component, error) {
|
|
124
|
+
client.logger.fatal(`[${component.customId ?? 'ComponentCommand'}].<onInternalError>`, error);
|
|
90
125
|
},
|
|
91
126
|
},
|
|
92
127
|
},
|
|
@@ -98,12 +133,33 @@ class BaseClient {
|
|
|
98
133
|
onMiddlewaresError(context, error) {
|
|
99
134
|
context.client.logger.fatal('ModalCommand.<onMiddlewaresError>', context.author.id, error);
|
|
100
135
|
},
|
|
101
|
-
onInternalError(client, error) {
|
|
102
|
-
client.logger.fatal(error);
|
|
136
|
+
onInternalError(client, modal, error) {
|
|
137
|
+
client.logger.fatal(`[${modal.customId ?? 'ModalCommand'}].<onInternalError>`, error);
|
|
103
138
|
},
|
|
104
139
|
},
|
|
105
140
|
},
|
|
106
|
-
}
|
|
141
|
+
};
|
|
142
|
+
const resolved = (0, plugins_1.resolveClientPlugins)(defaults, options);
|
|
143
|
+
this.options = resolved.options;
|
|
144
|
+
this.configureLogger({ name: '[Seyfert]' }, this.options.logger);
|
|
145
|
+
this.plugins = resolved.plugins;
|
|
146
|
+
this.pluginRegistry = resolved.registry;
|
|
147
|
+
this.shared = (0, shared_2.createSharedRegistry)(this, this.pluginRegistry);
|
|
148
|
+
this.bindPluginLangReload();
|
|
149
|
+
(0, plugins_1.bindClientPlugins)(this, this.pluginRegistry);
|
|
150
|
+
this.bindPluginRestObserverProvider();
|
|
151
|
+
this.refreshPluginCacheResources();
|
|
152
|
+
}
|
|
153
|
+
configureLogger(defaults, options) {
|
|
154
|
+
const loggerOptions = (0, common_1.MergeOptions)(defaults, options ?? {});
|
|
155
|
+
if (loggerOptions.active !== undefined)
|
|
156
|
+
this.logger.active = loggerOptions.active;
|
|
157
|
+
if (loggerOptions.logLevel !== undefined)
|
|
158
|
+
this.logger.level = loggerOptions.logLevel;
|
|
159
|
+
if (loggerOptions.name !== undefined)
|
|
160
|
+
this.logger.name = loggerOptions.name;
|
|
161
|
+
if (loggerOptions.saveOnFile !== undefined)
|
|
162
|
+
this.logger.saveOnFile = loggerOptions.saveOnFile;
|
|
107
163
|
}
|
|
108
164
|
get proxy() {
|
|
109
165
|
return this.rest.proxy;
|
|
@@ -126,6 +182,7 @@ class BaseClient {
|
|
|
126
182
|
rest.onSuccessRequest ??= this.rest.onSuccessRequest?.bind(rest);
|
|
127
183
|
rest.onFailRequest ??= this.rest.onFailRequest?.bind(rest);
|
|
128
184
|
this.rest = rest;
|
|
185
|
+
this.bindPluginRestObserverProvider();
|
|
129
186
|
}
|
|
130
187
|
if (cache) {
|
|
131
188
|
const caches = [
|
|
@@ -160,16 +217,19 @@ class BaseClient {
|
|
|
160
217
|
}
|
|
161
218
|
if (cache.adapter)
|
|
162
219
|
this.cache.adapter = cache.adapter;
|
|
163
|
-
if (cache.disabledCache)
|
|
164
|
-
this.
|
|
220
|
+
if (cache.disabledCache !== undefined)
|
|
221
|
+
this.refreshPluginCacheResources(disabledCache);
|
|
165
222
|
}
|
|
166
223
|
if (middlewares) {
|
|
167
|
-
this.middlewares = middlewares;
|
|
224
|
+
this.middlewares = { ...(this.middlewares ?? {}), ...middlewares };
|
|
168
225
|
}
|
|
169
226
|
if (langs) {
|
|
170
227
|
this.langs ??= new handler_3.LangsHandler(this.logger);
|
|
228
|
+
this.bindPluginLangReload();
|
|
171
229
|
if (langs.default)
|
|
172
230
|
this.langs.defaultLang = langs.default;
|
|
231
|
+
if (langs.preferGuildLocale !== undefined)
|
|
232
|
+
this.langs.preferGuildLocale = langs.preferGuildLocale;
|
|
173
233
|
if (langs.aliases)
|
|
174
234
|
this.langs.aliases = Object.entries(langs.aliases);
|
|
175
235
|
}
|
|
@@ -185,20 +245,392 @@ class BaseClient {
|
|
|
185
245
|
}
|
|
186
246
|
}
|
|
187
247
|
async start(options = {}) {
|
|
188
|
-
await this.loadLangs(options.langsDir);
|
|
189
|
-
await this.loadCommands(options.commandsDir);
|
|
190
|
-
await this.loadComponents(options.componentsDir);
|
|
191
248
|
const { token: tokenRC, debug } = await this.getRC();
|
|
192
249
|
const token = options.token ?? tokenRC;
|
|
193
|
-
(
|
|
250
|
+
if (typeof token !== 'string' || token.length === 0) {
|
|
251
|
+
throw new common_1.SeyfertError('INVALID_TOKEN', { metadata: { detail: 'token is not a string' } });
|
|
252
|
+
}
|
|
194
253
|
if (this.rest.options.token === 'INVALID')
|
|
195
254
|
this.rest.options.token = token;
|
|
196
|
-
this.rest.debug = debug;
|
|
255
|
+
this.rest.debug = !!debug;
|
|
197
256
|
if (!this.handleCommand)
|
|
198
257
|
this.handleCommand = new handle_1.HandleCommand(this);
|
|
258
|
+
await this.setupPlugins();
|
|
259
|
+
this.refreshPluginCacheResources();
|
|
260
|
+
this.reloadPluginMiddlewares();
|
|
261
|
+
await (0, plugins_1.runPluginHooks)(this, 'plugins:setupComplete', this);
|
|
262
|
+
await (0, plugins_1.runPluginHooks)(this, 'plugins:ready', this);
|
|
199
263
|
// The reason of this method is so for adapters that need to connect somewhere, have time to connect.
|
|
200
264
|
// Or maybe clear cache?
|
|
201
265
|
await this.cache.adapter.start();
|
|
266
|
+
await this.loadLangs(options.langsDir);
|
|
267
|
+
await (0, plugins_1.runPluginHooks)(this, 'commands:beforeLoad', this, options.commandsDir);
|
|
268
|
+
await this.loadCommands(options.commandsDir);
|
|
269
|
+
await this.reloadPluginCommands();
|
|
270
|
+
await (0, plugins_1.runPluginHooks)(this, 'components:beforeLoad', this, options.componentsDir);
|
|
271
|
+
this.pluginComponentsBeforeLoadDepth++;
|
|
272
|
+
try {
|
|
273
|
+
await this.loadComponents(options.componentsDir);
|
|
274
|
+
}
|
|
275
|
+
finally {
|
|
276
|
+
this.pluginComponentsBeforeLoadDepth--;
|
|
277
|
+
}
|
|
278
|
+
await this.reloadPluginComponents();
|
|
279
|
+
}
|
|
280
|
+
async reloadPluginContributions() {
|
|
281
|
+
this.refreshPluginContributions();
|
|
282
|
+
const commandsMetadata = this.createPluginLoadedMetadata('commands', this.loadedCommands);
|
|
283
|
+
await (0, plugins_1.runPluginHooks)(this, 'commands:afterLoad', commandsMetadata);
|
|
284
|
+
await this.emitPluginCustomEvent('commandsLoaded', commandsMetadata);
|
|
285
|
+
const componentsMetadata = this.createPluginLoadedMetadata('components', this.components.commands);
|
|
286
|
+
await (0, plugins_1.runPluginHooks)(this, 'components:afterLoad', componentsMetadata);
|
|
287
|
+
await this.emitPluginCustomEvent('componentsLoaded', componentsMetadata);
|
|
288
|
+
}
|
|
289
|
+
/** @internal */
|
|
290
|
+
refreshPluginContributions() {
|
|
291
|
+
this.reloadPluginMiddlewares();
|
|
292
|
+
this.refreshPluginCacheResources();
|
|
293
|
+
this.applyPluginLangs();
|
|
294
|
+
this.applyPluginCommands();
|
|
295
|
+
this.applyPluginComponents();
|
|
296
|
+
}
|
|
297
|
+
bindPluginRestObserverProvider() {
|
|
298
|
+
this.rest.pluginRestObserverClient = this;
|
|
299
|
+
this.rest.pluginRestObserverProvider = () => (0, order_1.orderedPluginContributions)(this.pluginRegistry.restObservers)
|
|
300
|
+
.filter(contribution => contribution.active)
|
|
301
|
+
.map(contribution => ({
|
|
302
|
+
plugin: contribution.record.identity,
|
|
303
|
+
observer: contribution.observer,
|
|
304
|
+
}));
|
|
305
|
+
}
|
|
306
|
+
bindPluginLangReload() {
|
|
307
|
+
this.langs.onReload = (locale, value) => {
|
|
308
|
+
this.langBaseValues[locale] = cloneRecursive(value);
|
|
309
|
+
this.applyPluginLangs();
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
refreshPluginCacheResources(disabledCache = this.pluginCacheDisabledCache) {
|
|
313
|
+
this.pluginCacheDisabledCache = disabledCache;
|
|
314
|
+
this.cache.intents = (0, plugins_1.resolveClientPluginIntents)(this, this.pluginBaseGatewayIntents);
|
|
315
|
+
this.cache.buildCache(disabledCache, this);
|
|
316
|
+
}
|
|
317
|
+
resolvePluginGatewayIntents(base) {
|
|
318
|
+
this.pluginBaseGatewayIntents = (0, intents_1.resolveGatewayIntents)(base);
|
|
319
|
+
this.cache.intents = (0, plugins_1.resolveClientPluginIntents)(this, this.pluginBaseGatewayIntents);
|
|
320
|
+
return this.cache.intents;
|
|
321
|
+
}
|
|
322
|
+
reloadPluginMiddlewares() {
|
|
323
|
+
(0, registry_1.installPluginMiddlewares)(this, this.pluginRegistry);
|
|
324
|
+
(0, plugins_1.refreshClientPluginOptions)(this, this.pluginRegistry);
|
|
325
|
+
}
|
|
326
|
+
async reloadPluginCommands() {
|
|
327
|
+
this.applyPluginCommands();
|
|
328
|
+
const metadata = this.createPluginLoadedMetadata('commands', this.loadedCommands);
|
|
329
|
+
await (0, plugins_1.runPluginHooks)(this, 'commands:afterLoad', metadata);
|
|
330
|
+
await this.emitPluginCustomEvent('commandsLoaded', metadata);
|
|
331
|
+
}
|
|
332
|
+
async reloadPluginComponents() {
|
|
333
|
+
this.applyPluginComponents();
|
|
334
|
+
const metadata = this.createPluginLoadedMetadata('components', this.components.commands);
|
|
335
|
+
await (0, plugins_1.runPluginHooks)(this, 'components:afterLoad', metadata);
|
|
336
|
+
await this.emitPluginCustomEvent('componentsLoaded', metadata);
|
|
337
|
+
}
|
|
338
|
+
async setupPlugins() {
|
|
339
|
+
if (this.pluginsClosePromise)
|
|
340
|
+
await this.pluginsClosePromise;
|
|
341
|
+
this.pluginsSetupPromise ??= (0, plugins_1.setupClientPlugins)(this, this.plugins);
|
|
342
|
+
try {
|
|
343
|
+
await this.pluginsSetupPromise;
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
this.pluginsSetupPromise = undefined;
|
|
347
|
+
throw error;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Closes resources managed by the plugin lifecycle.
|
|
352
|
+
*
|
|
353
|
+
* This waits for in-flight plugin setup and runs `SeyfertPlugin.teardown`.
|
|
354
|
+
* It does not close the gateway, REST client, or cache adapter.
|
|
355
|
+
*/
|
|
356
|
+
async close() {
|
|
357
|
+
const setup = this.pluginsSetupPromise;
|
|
358
|
+
if (!setup)
|
|
359
|
+
return;
|
|
360
|
+
const close = this.pluginsClosePromise ??
|
|
361
|
+
(async () => {
|
|
362
|
+
await setup;
|
|
363
|
+
await (0, plugins_1.runPluginHooks)(this, 'client:close', this);
|
|
364
|
+
await (0, plugins_1.teardownClientPlugins)(this, this.plugins);
|
|
365
|
+
})();
|
|
366
|
+
this.pluginsClosePromise = close;
|
|
367
|
+
try {
|
|
368
|
+
await close;
|
|
369
|
+
}
|
|
370
|
+
finally {
|
|
371
|
+
if (this.pluginsClosePromise === close) {
|
|
372
|
+
this.pluginsSetupPromise = undefined;
|
|
373
|
+
this.pluginsClosePromise = undefined;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
applyPluginCommands() {
|
|
378
|
+
const contributions = this.pluginRegistry.commands;
|
|
379
|
+
const removals = this.pluginRegistry.commandRemovals;
|
|
380
|
+
const hasPluginCommands = this.commands.values.some(command => pluginSourceKey in command) ||
|
|
381
|
+
!!(this.commands.entryPoint && pluginSourceKey in this.commands.entryPoint);
|
|
382
|
+
if (!(contributions.length || removals.length || hasPluginCommands))
|
|
383
|
+
return;
|
|
384
|
+
this.commands.values = this.commands.values.filter(command => !(pluginSourceKey in command));
|
|
385
|
+
if (this.commands.entryPoint && pluginSourceKey in this.commands.entryPoint)
|
|
386
|
+
this.commands.entryPoint = null;
|
|
387
|
+
const existingCommands = new Map();
|
|
388
|
+
for (const command of this.commands.values)
|
|
389
|
+
existingCommands.set(commandIdentity(command), { command });
|
|
390
|
+
if (this.commands.entryPoint)
|
|
391
|
+
existingCommands.set(commandIdentity(this.commands.entryPoint), { command: this.commands.entryPoint });
|
|
392
|
+
const mutations = (0, order_1.orderedPluginContributions)([
|
|
393
|
+
...contributions.map(contribution => ({ ...contribution, kind: 'add' })),
|
|
394
|
+
...removals.map(contribution => ({ ...contribution, kind: 'remove' })),
|
|
395
|
+
]);
|
|
396
|
+
for (const mutation of mutations) {
|
|
397
|
+
if (mutation.kind === 'remove') {
|
|
398
|
+
for (const name of mutation.names) {
|
|
399
|
+
const matches = [...existingCommands].filter(([, entry]) => entry.command.name === name);
|
|
400
|
+
if (!matches.length)
|
|
401
|
+
continue;
|
|
402
|
+
for (const [key, existing] of matches) {
|
|
403
|
+
(0, registry_1.assertCanMutatePluginContribution)(this.pluginRegistry, mutation.record, 'remove', 'command', name, existing.owner, 'commands.remove');
|
|
404
|
+
existingCommands.delete(key);
|
|
405
|
+
(0, registry_1.recordContributionMutationDiagnostic)(this.pluginRegistry, mutation, 'remove', 'command', name, existing.owner, 'commands.remove');
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
for (const command of mutation.commands) {
|
|
411
|
+
const instance = this.createPluginCommandInstance(command, mutation.record, 'commands.add');
|
|
412
|
+
if (instance instanceof commands_1.SubCommand) {
|
|
413
|
+
throw (0, errors_1.createPluginConflictError)(mutation.record.plugin.name, 'commands.add', mutation.record.index, `SubCommand "${instance.name}" cannot be registered as a top-level plugin command.`, mutation.record.plugin.instanceId);
|
|
414
|
+
}
|
|
415
|
+
if (!instance.name) {
|
|
416
|
+
throw (0, errors_1.createPluginConflictError)(mutation.record.plugin.name, 'commands.add', mutation.record.index, 'Plugin command is missing a name.', mutation.record.plugin.instanceId);
|
|
417
|
+
}
|
|
418
|
+
if (mutation.guilds?.length) {
|
|
419
|
+
if ('guildId' in instance) {
|
|
420
|
+
instance.guildId = [...mutation.guilds];
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
423
|
+
(0, registry_1.addPluginDiagnostic)(this.pluginRegistry, mutation.record, {
|
|
424
|
+
phase: 'commands.add',
|
|
425
|
+
severity: 'warn',
|
|
426
|
+
code: 'command-guild-scope',
|
|
427
|
+
message: `Command "${instance.name}" does not support guild-scoped registration.`,
|
|
428
|
+
data: { command: instance.name, guilds: [...mutation.guilds] },
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
const identity = commandIdentity(instance);
|
|
433
|
+
const existing = existingCommands.get(identity);
|
|
434
|
+
if (existing && !mutation.override) {
|
|
435
|
+
throw (0, errors_1.createPluginConflictError)(mutation.record.plugin.name, 'commands.add', mutation.record.index, `Command "${instance.name}" is already registered.`, mutation.record.plugin.instanceId);
|
|
436
|
+
}
|
|
437
|
+
if (existing) {
|
|
438
|
+
(0, registry_1.assertCanMutatePluginContribution)(this.pluginRegistry, mutation.record, 'override', 'command', instance.name, existing.owner, 'commands.add');
|
|
439
|
+
(0, registry_1.recordContributionMutationDiagnostic)(this.pluginRegistry, mutation, 'override', 'command', instance.name, existing.owner, 'commands.add');
|
|
440
|
+
}
|
|
441
|
+
instance[pluginSourceKey] = mutation.record.identity;
|
|
442
|
+
existingCommands.set(identity, { command: instance, owner: mutation.record });
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
const commands = [...existingCommands.values()]
|
|
446
|
+
.filter(entry => !!entry.owner)
|
|
447
|
+
.map(entry => entry.command);
|
|
448
|
+
this.commands.set(commands, command => {
|
|
449
|
+
const source = command[pluginSourceKey];
|
|
450
|
+
const transformed = this.runPluginHandlerTransformers('command', command);
|
|
451
|
+
if (source)
|
|
452
|
+
transformed[pluginSourceKey] = source;
|
|
453
|
+
return transformed;
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
get loadedCommands() {
|
|
457
|
+
return this.commands.entryPoint ? [...this.commands.values, this.commands.entryPoint] : this.commands.values;
|
|
458
|
+
}
|
|
459
|
+
applyPluginComponents() {
|
|
460
|
+
const contributions = this.pluginRegistry.components;
|
|
461
|
+
const modalContributions = this.pluginRegistry.modals;
|
|
462
|
+
const removals = this.pluginRegistry.componentRemovals;
|
|
463
|
+
const modalRemovals = this.pluginRegistry.modalRemovals;
|
|
464
|
+
const hasPluginComponents = this.components.commands.some(command => pluginSourceKey in command);
|
|
465
|
+
if (!(contributions.length ||
|
|
466
|
+
modalContributions.length ||
|
|
467
|
+
removals.length ||
|
|
468
|
+
modalRemovals.length ||
|
|
469
|
+
hasPluginComponents)) {
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
const existing = this.components.commands.filter(command => !(pluginSourceKey in command));
|
|
473
|
+
this.components.commands.splice(0, this.components.commands.length, ...existing);
|
|
474
|
+
const componentsByCustomId = new Map();
|
|
475
|
+
for (const component of this.components.commands) {
|
|
476
|
+
if (typeof component.customId === 'string') {
|
|
477
|
+
componentsByCustomId.set(componentIdentity(component instanceof components_1.ModalCommand ? 'modal' : 'component', component.customId), {
|
|
478
|
+
component,
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
const dynamicComponents = [];
|
|
483
|
+
const mutations = (0, order_1.orderedPluginContributions)([
|
|
484
|
+
...contributions.map(contribution => ({
|
|
485
|
+
...contribution,
|
|
486
|
+
kind: 'add',
|
|
487
|
+
contributionKind: 'component',
|
|
488
|
+
})),
|
|
489
|
+
...modalContributions.map(contribution => ({
|
|
490
|
+
...contribution,
|
|
491
|
+
kind: 'add',
|
|
492
|
+
contributionKind: 'modal',
|
|
493
|
+
})),
|
|
494
|
+
...removals.map(contribution => ({
|
|
495
|
+
...contribution,
|
|
496
|
+
kind: 'remove',
|
|
497
|
+
contributionKind: 'component',
|
|
498
|
+
})),
|
|
499
|
+
...modalRemovals.map(contribution => ({
|
|
500
|
+
...contribution,
|
|
501
|
+
kind: 'remove',
|
|
502
|
+
contributionKind: 'modal',
|
|
503
|
+
})),
|
|
504
|
+
]);
|
|
505
|
+
for (const mutation of mutations) {
|
|
506
|
+
if (mutation.kind === 'remove') {
|
|
507
|
+
for (const customId of mutation.customIds) {
|
|
508
|
+
const key = componentIdentity(mutation.contributionKind, customId);
|
|
509
|
+
const existing = componentsByCustomId.get(key);
|
|
510
|
+
if (!existing)
|
|
511
|
+
continue;
|
|
512
|
+
(0, registry_1.assertCanMutatePluginContribution)(this.pluginRegistry, mutation.record, 'remove', mutation.contributionKind, customId, existing.owner, `${mutation.contributionKind}s.remove`);
|
|
513
|
+
componentsByCustomId.delete(key);
|
|
514
|
+
(0, registry_1.recordContributionMutationDiagnostic)(this.pluginRegistry, mutation, 'remove', mutation.contributionKind, customId, existing.owner, `${mutation.contributionKind}s.remove`);
|
|
515
|
+
}
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
const constructors = mutation.contributionKind === 'component'
|
|
519
|
+
? mutation.components
|
|
520
|
+
: mutation.modals;
|
|
521
|
+
for (const constructor of constructors) {
|
|
522
|
+
const instance = this.createPluginComponentInstance(constructor, mutation.record, `${mutation.contributionKind}s.add`, mutation.contributionKind);
|
|
523
|
+
instance[pluginSourceKey] = mutation.record.identity;
|
|
524
|
+
if (typeof instance.customId !== 'string') {
|
|
525
|
+
dynamicComponents.push({ component: instance, owner: mutation.record });
|
|
526
|
+
continue;
|
|
527
|
+
}
|
|
528
|
+
const key = componentIdentity(mutation.contributionKind, instance.customId);
|
|
529
|
+
const existing = componentsByCustomId.get(key);
|
|
530
|
+
if (existing && !mutation.override) {
|
|
531
|
+
throw (0, errors_1.createPluginConflictError)(mutation.record.plugin.name, `${mutation.contributionKind}s.add`, mutation.record.index, `${capitalizePluginKind(mutation.contributionKind)} "${instance.customId}" is already registered.`, mutation.record.plugin.instanceId);
|
|
532
|
+
}
|
|
533
|
+
if (existing) {
|
|
534
|
+
(0, registry_1.assertCanMutatePluginContribution)(this.pluginRegistry, mutation.record, 'override', mutation.contributionKind, instance.customId, existing.owner, `${mutation.contributionKind}s.add`);
|
|
535
|
+
(0, registry_1.recordContributionMutationDiagnostic)(this.pluginRegistry, mutation, 'override', mutation.contributionKind, instance.customId, existing.owner, `${mutation.contributionKind}s.add`);
|
|
536
|
+
}
|
|
537
|
+
componentsByCustomId.set(key, { component: instance, owner: mutation.record });
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
const components = [...componentsByCustomId.values(), ...dynamicComponents]
|
|
541
|
+
.filter((entry) => !!entry.owner)
|
|
542
|
+
.map(entry => entry.component);
|
|
543
|
+
this.components.set(components, component => {
|
|
544
|
+
const source = component[pluginSourceKey];
|
|
545
|
+
const transformed = this.runPluginHandlerTransformers(component instanceof components_1.ModalCommand ? 'modal' : 'component', component);
|
|
546
|
+
if (source)
|
|
547
|
+
transformed[pluginSourceKey] = source;
|
|
548
|
+
return transformed;
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
createPluginCommandInstance(command, record, phase) {
|
|
552
|
+
if (typeof command !== 'function')
|
|
553
|
+
return command;
|
|
554
|
+
return this.runPluginHandlerCreators('command', command, () => {
|
|
555
|
+
try {
|
|
556
|
+
return new command();
|
|
557
|
+
}
|
|
558
|
+
catch (error) {
|
|
559
|
+
throw (0, errors_1.wrapPluginError)(record.plugin.name, phase, record.index, error, undefined, record.plugin.instanceId);
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
createPluginComponentInstance(constructor, record, phase, kind) {
|
|
564
|
+
const instance = typeof constructor !== 'function'
|
|
565
|
+
? constructor
|
|
566
|
+
: this.runPluginHandlerCreators(kind, constructor, () => {
|
|
567
|
+
try {
|
|
568
|
+
return new constructor();
|
|
569
|
+
}
|
|
570
|
+
catch (error) {
|
|
571
|
+
throw (0, errors_1.wrapPluginError)(record.plugin.name, phase, record.index, error, undefined, record.plugin.instanceId);
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
if (kind === 'modal' && !(instance instanceof components_1.ModalCommand)) {
|
|
575
|
+
throw (0, errors_1.createPluginConflictError)(record.plugin.name, phase, record.index, 'Plugin modal contribution must be a ModalCommand.', record.plugin.instanceId);
|
|
576
|
+
}
|
|
577
|
+
if (kind === 'component' && !(instance instanceof components_1.ComponentCommand)) {
|
|
578
|
+
throw (0, errors_1.createPluginConflictError)(record.plugin.name, phase, record.index, 'Plugin component contribution must be a ComponentCommand.', record.plugin.instanceId);
|
|
579
|
+
}
|
|
580
|
+
return instance;
|
|
581
|
+
}
|
|
582
|
+
runPluginHandlerCreators(kind, constructor, create) {
|
|
583
|
+
const creators = (0, order_1.orderedPluginContributions)(this.pluginRegistry.handlerCreators).filter(contribution => this.matchesPluginHandlerKind(contribution.kinds, kind));
|
|
584
|
+
const metadata = { kind };
|
|
585
|
+
return creators.reduceRight((next, contribution) => () => {
|
|
586
|
+
try {
|
|
587
|
+
return contribution.creator(constructor, next, metadata);
|
|
588
|
+
}
|
|
589
|
+
catch (error) {
|
|
590
|
+
throw (0, errors_1.wrapPluginError)(contribution.record.plugin.name, `handlers.construct:${kind}`, contribution.record.index, error, undefined, contribution.record.plugin.instanceId);
|
|
591
|
+
}
|
|
592
|
+
}, create)();
|
|
593
|
+
}
|
|
594
|
+
/** @internal */
|
|
595
|
+
runPluginHandlerTransformers(kind, instance) {
|
|
596
|
+
let current = instance;
|
|
597
|
+
const metadata = { kind };
|
|
598
|
+
for (const contribution of (0, order_1.orderedPluginContributions)(this.pluginRegistry.handlerTransformers)) {
|
|
599
|
+
if (!this.matchesPluginHandlerKind(contribution.kinds, kind))
|
|
600
|
+
continue;
|
|
601
|
+
try {
|
|
602
|
+
const transform = contribution.transformer;
|
|
603
|
+
current = (transform(current, metadata) ?? current);
|
|
604
|
+
}
|
|
605
|
+
catch (error) {
|
|
606
|
+
throw (0, errors_1.wrapPluginError)(contribution.record.plugin.name, `handlers.transform:${kind}`, contribution.record.index, error, undefined, contribution.record.plugin.instanceId);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
return current;
|
|
610
|
+
}
|
|
611
|
+
matchesPluginHandlerKind(kinds, kind) {
|
|
612
|
+
return !kinds?.length || kinds.includes(kind);
|
|
613
|
+
}
|
|
614
|
+
createPluginLoadedMetadata(kind, items) {
|
|
615
|
+
const sources = Object.create(null);
|
|
616
|
+
for (const item of items) {
|
|
617
|
+
const source = item[pluginSourceKey];
|
|
618
|
+
if (source)
|
|
619
|
+
sources[source] = (sources[source] ?? 0) + 1;
|
|
620
|
+
}
|
|
621
|
+
const sourceSnapshot = Object.freeze(sources);
|
|
622
|
+
return Object.freeze({
|
|
623
|
+
kind,
|
|
624
|
+
total: items.length,
|
|
625
|
+
items: Object.freeze([...items]),
|
|
626
|
+
plugin: Object.freeze({
|
|
627
|
+
total: Object.values(sources).reduce((sum, value) => sum + value, 0),
|
|
628
|
+
sources: sourceSnapshot,
|
|
629
|
+
}),
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
async emitPluginCustomEvent(name, ...args) {
|
|
633
|
+
await this.events?.runCustom(name, ...args);
|
|
202
634
|
}
|
|
203
635
|
async onPacket(..._packet) {
|
|
204
636
|
throw new common_1.SeyfertError('FUNCTION_NOT_IMPLEMENTED', { metadata: { detail: 'Function not implemented' } });
|
|
@@ -209,8 +641,15 @@ class BaseClient {
|
|
|
209
641
|
* @returns
|
|
210
642
|
*/
|
|
211
643
|
async onInteractionRequest(rawBody) {
|
|
212
|
-
|
|
213
|
-
|
|
644
|
+
if (rawBody.type === types_1.InteractionType.Ping) {
|
|
645
|
+
return {
|
|
646
|
+
headers: { 'Content-Type': 'application/json' },
|
|
647
|
+
response: { type: types_1.InteractionResponseType.Pong },
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
return new Promise((resolve, reject) => {
|
|
651
|
+
this.handleCommand
|
|
652
|
+
.interaction(rawBody, -1, async ({ body, files }) => {
|
|
214
653
|
let response;
|
|
215
654
|
const headers = {};
|
|
216
655
|
if (files) {
|
|
@@ -241,11 +680,12 @@ class BaseClient {
|
|
|
241
680
|
response = body ?? {};
|
|
242
681
|
headers['Content-Type'] = 'application/json';
|
|
243
682
|
}
|
|
244
|
-
|
|
683
|
+
resolve({
|
|
245
684
|
headers,
|
|
246
685
|
response,
|
|
247
686
|
});
|
|
248
|
-
})
|
|
687
|
+
})
|
|
688
|
+
.catch(reject);
|
|
249
689
|
});
|
|
250
690
|
}
|
|
251
691
|
async shouldUploadCommands(cachePath, guildId) {
|
|
@@ -260,6 +700,29 @@ class BaseClient {
|
|
|
260
700
|
.filter(cmd => !('ignore' in cmd) || cmd.ignore !== shared_1.IgnoreCommand.Slash)
|
|
261
701
|
.map(x => x.toJSON())));
|
|
262
702
|
}
|
|
703
|
+
async cachedCommandGuilds(cachePath) {
|
|
704
|
+
const guilds = new Set();
|
|
705
|
+
const cached = await node_fs_1.promises.readFile(cachePath, 'utf8').catch(() => undefined);
|
|
706
|
+
if (!cached)
|
|
707
|
+
return guilds;
|
|
708
|
+
try {
|
|
709
|
+
const commands = JSON.parse(cached);
|
|
710
|
+
for (const command of commands) {
|
|
711
|
+
const guildId = command.guild_id;
|
|
712
|
+
if (Array.isArray(guildId)) {
|
|
713
|
+
for (const id of guildId)
|
|
714
|
+
guilds.add(id);
|
|
715
|
+
}
|
|
716
|
+
else if (typeof guildId === 'string') {
|
|
717
|
+
guilds.add(guildId);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
catch {
|
|
722
|
+
return guilds;
|
|
723
|
+
}
|
|
724
|
+
return guilds;
|
|
725
|
+
}
|
|
263
726
|
async uploadCommands({ applicationId, cachePath } = {}) {
|
|
264
727
|
applicationId ??= await this.getRC().then(x => x.applicationId ?? this.applicationId);
|
|
265
728
|
(0, common_1.assertString)(applicationId, 'applicationId is not a string');
|
|
@@ -268,68 +731,129 @@ class BaseClient {
|
|
|
268
731
|
if (this.commands.entryPoint) {
|
|
269
732
|
filter.expect.push(this.commands.entryPoint);
|
|
270
733
|
}
|
|
271
|
-
|
|
734
|
+
const globalCommands = filter.expect
|
|
735
|
+
.filter(cmd => !('ignore' in cmd) || cmd.ignore !== shared_1.IgnoreCommand.Slash)
|
|
736
|
+
.map(x => x.toJSON());
|
|
737
|
+
const shouldUploadGlobal = !cachePath || (await this.shouldUploadCommands(cachePath));
|
|
738
|
+
if (shouldUploadGlobal) {
|
|
272
739
|
await this.proxy.applications(applicationId).commands.put({
|
|
273
|
-
body:
|
|
274
|
-
.filter(cmd => !('ignore' in cmd) || cmd.ignore !== shared_1.IgnoreCommand.Slash)
|
|
275
|
-
.map(x => x.toJSON()),
|
|
740
|
+
body: globalCommands,
|
|
276
741
|
});
|
|
742
|
+
}
|
|
743
|
+
await this.emitUploadCommandsMetadata({
|
|
744
|
+
applicationId,
|
|
745
|
+
cachePath,
|
|
746
|
+
commands: globalCommands.length,
|
|
747
|
+
reason: cachePath ? (shouldUploadGlobal ? 'cache-miss' : 'cache-hit') : 'forced',
|
|
748
|
+
scope: 'global',
|
|
749
|
+
status: shouldUploadGlobal ? 'uploaded' : 'skipped',
|
|
750
|
+
});
|
|
277
751
|
const guilds = new Set();
|
|
752
|
+
if (cachePath) {
|
|
753
|
+
for (const guildId of await this.cachedCommandGuilds(cachePath))
|
|
754
|
+
guilds.add(guildId);
|
|
755
|
+
}
|
|
278
756
|
for (const command of filter.never) {
|
|
279
757
|
for (const guild_id of command.guildId) {
|
|
280
758
|
guilds.add(guild_id);
|
|
281
759
|
}
|
|
282
760
|
}
|
|
283
761
|
for (const guildId of guilds) {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
.map(x => x.toJSON()),
|
|
762
|
+
const guildCommands = filter.never
|
|
763
|
+
.filter(cmd => cmd.guildId.includes(guildId) && (!('ignore' in cmd) || cmd.ignore !== shared_1.IgnoreCommand.Slash))
|
|
764
|
+
.map(x => x.toJSON());
|
|
765
|
+
const shouldUploadGuild = !cachePath || (await this.shouldUploadCommands(cachePath, guildId));
|
|
766
|
+
if (shouldUploadGuild) {
|
|
767
|
+
await this.proxy.applications(applicationId).guilds(guildId).commands.put({
|
|
768
|
+
body: guildCommands,
|
|
292
769
|
});
|
|
293
770
|
}
|
|
771
|
+
await this.emitUploadCommandsMetadata({
|
|
772
|
+
applicationId,
|
|
773
|
+
cachePath,
|
|
774
|
+
commands: guildCommands.length,
|
|
775
|
+
guildId,
|
|
776
|
+
reason: cachePath ? (shouldUploadGuild ? 'cache-miss' : 'cache-hit') : 'forced',
|
|
777
|
+
scope: 'guild',
|
|
778
|
+
status: shouldUploadGuild ? 'uploaded' : 'skipped',
|
|
779
|
+
});
|
|
294
780
|
}
|
|
295
781
|
if (cachePath)
|
|
296
782
|
await this.syncCachePath(cachePath);
|
|
297
783
|
}
|
|
784
|
+
async emitUploadCommandsMetadata(metadata) {
|
|
785
|
+
await this.emitPluginCustomEvent('uploadCommands', metadata);
|
|
786
|
+
}
|
|
298
787
|
async loadCommands(dir) {
|
|
299
788
|
dir ??= await this.getRC().then(x => x.locations.commands);
|
|
300
789
|
if (dir && this.commands) {
|
|
301
|
-
await this.commands.load(dir, this);
|
|
790
|
+
await this.commands.load(dir, this, this.createPluginCommandLoadOptions());
|
|
302
791
|
this.logger.info('CommandHandler loaded');
|
|
303
792
|
}
|
|
304
793
|
}
|
|
305
794
|
async loadComponents(dir) {
|
|
306
795
|
dir ??= await this.getRC().then(x => x.locations.components);
|
|
796
|
+
if (!this.pluginComponentsBeforeLoadDepth)
|
|
797
|
+
await (0, plugins_1.runPluginHooks)(this, 'components:beforeLoad', this, dir);
|
|
307
798
|
if (dir && this.components) {
|
|
308
|
-
await this.components.load(dir);
|
|
799
|
+
await this.components.load(dir, this.createPluginComponentLoadOptions());
|
|
309
800
|
this.logger.info('ComponentHandler loaded');
|
|
310
801
|
}
|
|
311
802
|
}
|
|
803
|
+
/** @internal */
|
|
804
|
+
createPluginCommandLoadOptions() {
|
|
805
|
+
return {
|
|
806
|
+
create: (constructor, next) => this.runPluginHandlerCreators('command', constructor, next),
|
|
807
|
+
transform: command => this.runPluginHandlerTransformers('command', command),
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
/** @internal */
|
|
811
|
+
createPluginComponentLoadOptions() {
|
|
812
|
+
return {
|
|
813
|
+
create: (kind, constructor, next) => this.runPluginHandlerCreators(kind, constructor, next),
|
|
814
|
+
transform: (kind, component) => this.runPluginHandlerTransformers(kind, component),
|
|
815
|
+
};
|
|
816
|
+
}
|
|
312
817
|
async loadLangs(dir) {
|
|
313
818
|
dir ??= await this.getRC().then(x => x.locations.langs);
|
|
314
819
|
if (dir && this.langs) {
|
|
315
820
|
await this.langs.load(dir);
|
|
316
821
|
this.logger.info('LangsHandler loaded');
|
|
317
822
|
}
|
|
823
|
+
this.langBaseValues = this.langs ? cloneRecursive(this.langs.values) : this.langBaseValues;
|
|
824
|
+
this.applyPluginLangs();
|
|
825
|
+
}
|
|
826
|
+
applyPluginLangs() {
|
|
827
|
+
if (!this.langs)
|
|
828
|
+
return;
|
|
829
|
+
const localeContributions = (0, order_1.orderedPluginContributions)(this.pluginRegistry.langs);
|
|
830
|
+
const values = cloneRecursive(this.langBaseValues);
|
|
831
|
+
for (const contribution of localeContributions) {
|
|
832
|
+
const current = values[contribution.locale] ?? {};
|
|
833
|
+
values[contribution.locale] = (0, common_1.MergeOptions)(current, createNestedLangValues(contribution.prefix, cloneRecursive(contribution.values)));
|
|
834
|
+
}
|
|
835
|
+
this.langs.values = values;
|
|
318
836
|
}
|
|
319
837
|
t(locale) {
|
|
320
838
|
return this.langs.get(locale);
|
|
321
839
|
}
|
|
322
840
|
async getRC() {
|
|
841
|
+
if (this._rcCache)
|
|
842
|
+
return this._rcCache;
|
|
323
843
|
const seyfertConfig = (BaseClient._seyfertCfWorkerConfig ||
|
|
324
844
|
(await this.options?.getRC?.()) ||
|
|
325
845
|
(await Promise.any(['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts'].map(ext => (0, common_1.magicImport)((0, node_path_1.join)(process.cwd(), `seyfert.config${ext}`)).then(x => x.default ?? x))).catch((e) => {
|
|
326
|
-
const errors = e.errors.map((err) => {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
});
|
|
846
|
+
const errors = e.errors.map((err) => ({
|
|
847
|
+
error: err,
|
|
848
|
+
message: err.message.replace(/seyfert\.config\.(js|mjs|cjs|ts|mts|cts)/g, 'seyfert.config'),
|
|
849
|
+
}));
|
|
330
850
|
const uniqueError = errors.find(er => errors.filter(err => err.message === er.message).length === 1);
|
|
331
|
-
if (uniqueError)
|
|
332
|
-
throw
|
|
851
|
+
if (uniqueError) {
|
|
852
|
+
throw new common_1.SeyfertError('SEYFERT_CONFIG_LOAD_ERROR', {
|
|
853
|
+
metadata: { detail: uniqueError.message },
|
|
854
|
+
cause: uniqueError.error,
|
|
855
|
+
});
|
|
856
|
+
}
|
|
333
857
|
throw new common_1.SeyfertError('NO_SEYFERT_CONFIG', {
|
|
334
858
|
metadata: { detail: 'No seyfert.config file found' },
|
|
335
859
|
});
|
|
@@ -349,11 +873,42 @@ class BaseClient {
|
|
|
349
873
|
locationsFullPaths[key] = location;
|
|
350
874
|
}
|
|
351
875
|
const obj = {
|
|
352
|
-
debug: !!debug,
|
|
353
876
|
...env,
|
|
877
|
+
debug: !!debug,
|
|
878
|
+
intents: (0, intents_1.resolveGatewayIntents)('intents' in seyfertConfig ? (seyfertConfig.intents ?? 0) : 0),
|
|
354
879
|
locations: locationsFullPaths,
|
|
355
880
|
};
|
|
881
|
+
this._rcCache = obj;
|
|
356
882
|
return obj;
|
|
357
883
|
}
|
|
358
884
|
}
|
|
359
885
|
exports.BaseClient = BaseClient;
|
|
886
|
+
function createNestedLangValues(prefix, values) {
|
|
887
|
+
const route = prefix.split('.').filter(Boolean);
|
|
888
|
+
const clonedValues = cloneRecursive(values);
|
|
889
|
+
const root = {};
|
|
890
|
+
let current = root;
|
|
891
|
+
for (let i = 0; i < route.length; i++) {
|
|
892
|
+
const key = route[i];
|
|
893
|
+
if (i === route.length - 1) {
|
|
894
|
+
current[key] = clonedValues;
|
|
895
|
+
break;
|
|
896
|
+
}
|
|
897
|
+
const nested = {};
|
|
898
|
+
current[key] = nested;
|
|
899
|
+
current = nested;
|
|
900
|
+
}
|
|
901
|
+
return root;
|
|
902
|
+
}
|
|
903
|
+
function cloneRecursive(value) {
|
|
904
|
+
if (Array.isArray(value))
|
|
905
|
+
return value.map(item => cloneRecursive(item));
|
|
906
|
+
if (!value || typeof value !== 'object')
|
|
907
|
+
return value;
|
|
908
|
+
const entries = value;
|
|
909
|
+
const cloned = {};
|
|
910
|
+
for (const key of Object.keys(entries)) {
|
|
911
|
+
cloned[key] = cloneRecursive(entries[key]);
|
|
912
|
+
}
|
|
913
|
+
return cloned;
|
|
914
|
+
}
|