bakit 2.0.0-alpha.3 → 2.0.0-alpha.31
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/cli.js +77 -0
- package/dist/hooks.js +82 -0
- package/dist/index.d.ts +437 -110
- package/dist/index.js +918 -358
- package/dist/register.js +4 -0
- package/package.json +17 -6
package/dist/index.js
CHANGED
|
@@ -1,12 +1,172 @@
|
|
|
1
|
-
import { GatewayIntentBits, Events, Client, IntentsBitField,
|
|
2
|
-
import z3, { z } from 'zod';
|
|
3
|
-
import { pathToFileURL } from 'url';
|
|
4
|
-
import glob from 'tiny-glob';
|
|
1
|
+
import { GatewayIntentBits, Events, Collection, Client, IntentsBitField, SlashCommandBuilder, SlashCommandStringOption, SlashCommandNumberOption, SlashCommandUserOption, ChatInputCommandInteraction, Message } from 'discord.js';
|
|
5
2
|
import { inspect } from 'util';
|
|
6
|
-
import {
|
|
3
|
+
import { pathToFileURL, fileURLToPath } from 'url';
|
|
4
|
+
import { join, resolve, relative, sep, dirname } from 'path';
|
|
5
|
+
import glob from 'tiny-glob';
|
|
6
|
+
import z2 from 'zod';
|
|
7
|
+
import { register } from 'module';
|
|
8
|
+
import { MessageChannel } from 'worker_threads';
|
|
9
|
+
import { randomUUID, createHash } from 'crypto';
|
|
10
|
+
import EventEmitter from 'events';
|
|
11
|
+
import { existsSync, mkdirSync, rmSync } from 'fs';
|
|
12
|
+
import { mkdir, writeFile, readFile, rm } from 'fs/promises';
|
|
13
|
+
|
|
14
|
+
var __defProp = Object.defineProperty;
|
|
15
|
+
var __export = (target, all) => {
|
|
16
|
+
for (var name in all)
|
|
17
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
18
|
+
};
|
|
19
|
+
var ParamUserType = /* @__PURE__ */ ((ParamUserType2) => (ParamUserType2.Bot = "bot", ParamUserType2.Normal = "normal", ParamUserType2.Any = "any", ParamUserType2))(ParamUserType || {}), BaseParamSchema = z2.object({
|
|
20
|
+
name: z2.string(),
|
|
21
|
+
description: z2.string().optional(),
|
|
22
|
+
required: z2.boolean().default(true)
|
|
23
|
+
}), StringParamSchema = BaseParamSchema.extend({
|
|
24
|
+
maxLength: z2.number().min(1).optional(),
|
|
25
|
+
minLength: z2.number().min(1).optional()
|
|
26
|
+
}), NumberParamSchema = BaseParamSchema.extend({
|
|
27
|
+
maxValue: z2.number().optional(),
|
|
28
|
+
minValue: z2.number().optional()
|
|
29
|
+
}), UserParamSchema = BaseParamSchema.extend({});
|
|
30
|
+
var INTENT_GROUPS = {
|
|
31
|
+
[GatewayIntentBits.Guilds]: [
|
|
32
|
+
Events.GuildCreate,
|
|
33
|
+
Events.GuildDelete,
|
|
34
|
+
Events.GuildUpdate,
|
|
35
|
+
Events.GuildUnavailable,
|
|
36
|
+
Events.GuildRoleCreate,
|
|
37
|
+
Events.GuildRoleDelete,
|
|
38
|
+
Events.GuildRoleUpdate,
|
|
39
|
+
Events.ChannelCreate,
|
|
40
|
+
Events.ChannelDelete,
|
|
41
|
+
Events.ChannelUpdate,
|
|
42
|
+
Events.ChannelPinsUpdate,
|
|
43
|
+
Events.ThreadCreate,
|
|
44
|
+
Events.ThreadDelete,
|
|
45
|
+
Events.ThreadUpdate,
|
|
46
|
+
Events.ThreadListSync,
|
|
47
|
+
Events.ThreadMemberUpdate,
|
|
48
|
+
Events.ThreadMembersUpdate,
|
|
49
|
+
Events.StageInstanceCreate,
|
|
50
|
+
Events.StageInstanceUpdate,
|
|
51
|
+
Events.StageInstanceDelete
|
|
52
|
+
],
|
|
53
|
+
[GatewayIntentBits.GuildMembers]: [
|
|
54
|
+
Events.GuildMemberAdd,
|
|
55
|
+
Events.GuildMemberUpdate,
|
|
56
|
+
Events.GuildMemberRemove,
|
|
57
|
+
Events.ThreadMembersUpdate
|
|
58
|
+
],
|
|
59
|
+
[GatewayIntentBits.GuildModeration]: [Events.GuildAuditLogEntryCreate, Events.GuildBanAdd, Events.GuildBanRemove],
|
|
60
|
+
[GatewayIntentBits.GuildExpressions]: [
|
|
61
|
+
Events.GuildEmojiCreate,
|
|
62
|
+
Events.GuildEmojiDelete,
|
|
63
|
+
Events.GuildEmojiUpdate,
|
|
64
|
+
Events.GuildStickerCreate,
|
|
65
|
+
Events.GuildStickerDelete,
|
|
66
|
+
Events.GuildStickerUpdate,
|
|
67
|
+
Events.GuildSoundboardSoundCreate,
|
|
68
|
+
Events.GuildSoundboardSoundUpdate,
|
|
69
|
+
Events.GuildSoundboardSoundDelete,
|
|
70
|
+
Events.GuildSoundboardSoundsUpdate
|
|
71
|
+
],
|
|
72
|
+
[GatewayIntentBits.GuildIntegrations]: [Events.GuildIntegrationsUpdate],
|
|
73
|
+
[GatewayIntentBits.GuildWebhooks]: [Events.WebhooksUpdate],
|
|
74
|
+
[GatewayIntentBits.GuildInvites]: [Events.InviteCreate, Events.InviteDelete],
|
|
75
|
+
[GatewayIntentBits.GuildVoiceStates]: [Events.VoiceStateUpdate],
|
|
76
|
+
[GatewayIntentBits.GuildPresences]: [Events.PresenceUpdate],
|
|
77
|
+
[GatewayIntentBits.GuildMessages]: [
|
|
78
|
+
Events.MessageCreate,
|
|
79
|
+
Events.MessageUpdate,
|
|
80
|
+
Events.MessageDelete,
|
|
81
|
+
Events.MessageBulkDelete
|
|
82
|
+
],
|
|
83
|
+
[GatewayIntentBits.GuildMessageReactions]: [
|
|
84
|
+
Events.MessageReactionAdd,
|
|
85
|
+
Events.MessageReactionRemove,
|
|
86
|
+
Events.MessageReactionRemoveAll,
|
|
87
|
+
Events.MessageReactionRemoveEmoji
|
|
88
|
+
],
|
|
89
|
+
[GatewayIntentBits.GuildMessageTyping]: [Events.TypingStart],
|
|
90
|
+
[GatewayIntentBits.DirectMessages]: [
|
|
91
|
+
Events.MessageCreate,
|
|
92
|
+
Events.MessageUpdate,
|
|
93
|
+
Events.MessageDelete,
|
|
94
|
+
Events.ChannelPinsUpdate
|
|
95
|
+
],
|
|
96
|
+
[GatewayIntentBits.DirectMessageReactions]: [
|
|
97
|
+
Events.MessageReactionAdd,
|
|
98
|
+
Events.MessageReactionRemove,
|
|
99
|
+
Events.MessageReactionRemoveAll,
|
|
100
|
+
Events.MessageReactionRemoveEmoji
|
|
101
|
+
],
|
|
102
|
+
[GatewayIntentBits.DirectMessageTyping]: [Events.TypingStart],
|
|
103
|
+
[GatewayIntentBits.MessageContent]: [Events.MessageCreate, Events.MessageUpdate],
|
|
104
|
+
[GatewayIntentBits.GuildScheduledEvents]: [
|
|
105
|
+
Events.GuildScheduledEventCreate,
|
|
106
|
+
Events.GuildScheduledEventDelete,
|
|
107
|
+
Events.GuildScheduledEventUpdate,
|
|
108
|
+
Events.GuildScheduledEventUserAdd,
|
|
109
|
+
Events.GuildScheduledEventUserRemove
|
|
110
|
+
],
|
|
111
|
+
[GatewayIntentBits.AutoModerationConfiguration]: [
|
|
112
|
+
Events.AutoModerationRuleCreate,
|
|
113
|
+
Events.AutoModerationRuleDelete,
|
|
114
|
+
Events.AutoModerationRuleUpdate
|
|
115
|
+
],
|
|
116
|
+
[GatewayIntentBits.AutoModerationExecution]: [Events.AutoModerationActionExecution],
|
|
117
|
+
[GatewayIntentBits.GuildMessagePolls]: [Events.MessagePollVoteAdd, Events.MessagePollVoteRemove],
|
|
118
|
+
[GatewayIntentBits.DirectMessagePolls]: [Events.MessagePollVoteAdd, Events.MessagePollVoteRemove]
|
|
119
|
+
}, EVENT_INTENT_MAPPING = {};
|
|
120
|
+
for (let [intentStr, events] of Object.entries(INTENT_GROUPS)) {
|
|
121
|
+
let intent = Number(intentStr);
|
|
122
|
+
for (let event of events)
|
|
123
|
+
EVENT_INTENT_MAPPING[event] ??= [], EVENT_INTENT_MAPPING[event].includes(intent) || EVENT_INTENT_MAPPING[event].push(intent);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/lib/errors/BakitError.ts
|
|
127
|
+
var BakitError = class extends Error {
|
|
128
|
+
constructor(message) {
|
|
129
|
+
super(message), this.name = this.constructor.name, Object.setPrototypeOf(this, new.target.prototype);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// src/lib/errors/ArgumentError.ts
|
|
134
|
+
var ArgumentError = class extends BakitError {
|
|
135
|
+
constructor(target, reason) {
|
|
136
|
+
super(`Invalid argument for '${target}': ${reason}`);
|
|
137
|
+
this.target = target;
|
|
138
|
+
this.reason = reason;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
7
141
|
|
|
8
|
-
// src/
|
|
9
|
-
|
|
142
|
+
// src/lib/utils/string.ts
|
|
143
|
+
function tokenize(content) {
|
|
144
|
+
let args = [], current = "", quoteChar = null, isEscaped = false;
|
|
145
|
+
for (let i = 0; i < content.length; i++) {
|
|
146
|
+
let char = content[i];
|
|
147
|
+
if (char === void 0)
|
|
148
|
+
break;
|
|
149
|
+
if (isEscaped) {
|
|
150
|
+
current += char, isEscaped = false;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (char === "\\") {
|
|
154
|
+
isEscaped = true;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
quoteChar ? char === quoteChar ? quoteChar = null : current += char : char === '"' ? quoteChar = char : /\s/.test(char) ? current.length > 0 && (args.push(current), current = "") : current += char;
|
|
158
|
+
}
|
|
159
|
+
return current.length > 0 && args.push(current), args;
|
|
160
|
+
}
|
|
161
|
+
function extractSnowflakeId(input) {
|
|
162
|
+
if (!input) return null;
|
|
163
|
+
let mentionMatch = /^<@!?(\d{17,20})>$/.exec(input);
|
|
164
|
+
if (mentionMatch?.[1])
|
|
165
|
+
return mentionMatch[1];
|
|
166
|
+
let idMatch = /^(\d{17,20})$/.exec(input);
|
|
167
|
+
return idMatch?.[1] ? idMatch[1] : null;
|
|
168
|
+
}
|
|
169
|
+
var CONFIG_EXTENSIONS = ["ts", "js"], ProjectConfigSchema = z2.object({
|
|
10
170
|
/**
|
|
11
171
|
* The gateway intents to use for the Discord client.
|
|
12
172
|
*
|
|
@@ -16,7 +176,7 @@ var ProjectConfigSchema = z.object({
|
|
|
16
176
|
*
|
|
17
177
|
* @defaultvalue `auto`
|
|
18
178
|
*/
|
|
19
|
-
intents:
|
|
179
|
+
intents: z2.union([z2.literal("auto"), z2.bigint(), z2.array(z2.enum(GatewayIntentBits))]).default("auto"),
|
|
20
180
|
/**
|
|
21
181
|
* Optional custom client options for Discord.js (excluding `intents`).
|
|
22
182
|
*
|
|
@@ -24,15 +184,20 @@ var ProjectConfigSchema = z.object({
|
|
|
24
184
|
*
|
|
25
185
|
* @see {@link https://discord.js.org/docs/packages/discord.js/main/ClientOptions:Interface}
|
|
26
186
|
*/
|
|
27
|
-
clientOptions:
|
|
187
|
+
clientOptions: z2.custom().optional(),
|
|
28
188
|
/**
|
|
29
|
-
*
|
|
30
|
-
|
|
189
|
+
* Your bot prefixes to trigger the commands.
|
|
190
|
+
*/
|
|
191
|
+
prefixes: z2.array(z2.string()).default([]),
|
|
192
|
+
/**
|
|
193
|
+
* Your Discord bot token.
|
|
194
|
+
*/
|
|
195
|
+
token: z2.string(),
|
|
196
|
+
/**
|
|
197
|
+
* The main source directory.
|
|
31
198
|
* @defaultvalue `src`
|
|
32
199
|
*/
|
|
33
|
-
|
|
34
|
-
prefixes: z.array(z.string()).default([]),
|
|
35
|
-
token: z.string()
|
|
200
|
+
entryDirectory: z2.string().default("src")
|
|
36
201
|
});
|
|
37
202
|
function defineConfig(config) {
|
|
38
203
|
return config;
|
|
@@ -41,7 +206,7 @@ var _config;
|
|
|
41
206
|
async function loadConfig(cwd = process.cwd()) {
|
|
42
207
|
if (_config)
|
|
43
208
|
return console.warn("loadConfig() was called more than once. This shouldn't happen."), _config;
|
|
44
|
-
let globPattern = `bakit.config.{${
|
|
209
|
+
let globPattern = `bakit.config.{${CONFIG_EXTENSIONS.join(",")}}`, [configPath, other] = await glob(globPattern, {
|
|
45
210
|
cwd: cwd.replace(/\\/g, "/"),
|
|
46
211
|
// ensure the path uses `/` instead of `\` on Windows
|
|
47
212
|
absolute: true
|
|
@@ -49,7 +214,7 @@ async function loadConfig(cwd = process.cwd()) {
|
|
|
49
214
|
if (!configPath)
|
|
50
215
|
throw new Error("Missing config file");
|
|
51
216
|
other && console.warn(`Multiple config files found in ${cwd}. Using ${configPath}.`);
|
|
52
|
-
let
|
|
217
|
+
let config = (await import(pathToFileURL(configPath).href)).default;
|
|
53
218
|
return _config = Object.freeze(await ProjectConfigSchema.parseAsync(config)), _config;
|
|
54
219
|
}
|
|
55
220
|
function getConfig() {
|
|
@@ -57,175 +222,262 @@ function getConfig() {
|
|
|
57
222
|
throw new Error("Project config is not loaded.");
|
|
58
223
|
return _config;
|
|
59
224
|
}
|
|
225
|
+
function getTopLevelDirectory(path, entryDir) {
|
|
226
|
+
return relative(entryDir, path).split(sep)[0] ?? null;
|
|
227
|
+
}
|
|
228
|
+
function getEntryDirectory() {
|
|
229
|
+
return resolve(getConfig().entryDirectory);
|
|
230
|
+
}
|
|
231
|
+
function getEntryFile() {
|
|
232
|
+
return process.env.BAKIT_ENTRY_FILE;
|
|
233
|
+
}
|
|
60
234
|
|
|
61
|
-
// src/
|
|
62
|
-
var
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
235
|
+
// src/lib/loader/loader.ts
|
|
236
|
+
var loader_exports = {};
|
|
237
|
+
__export(loader_exports, {
|
|
238
|
+
addHotReloader: () => addHotReloader,
|
|
239
|
+
containsEntryFile: () => containsEntryFile,
|
|
240
|
+
containsHotModule: () => containsHotModule,
|
|
241
|
+
getDependencyChain: () => getDependencyChain,
|
|
242
|
+
getImporters: () => getImporters,
|
|
243
|
+
getImports: () => getImports,
|
|
244
|
+
hotReloaders: () => hotReloaders,
|
|
245
|
+
importsAny: () => importsAny,
|
|
246
|
+
init: () => init,
|
|
247
|
+
isEntryFile: () => isEntryFile,
|
|
248
|
+
isImported: () => isImported,
|
|
249
|
+
isImportedBy: () => isImportedBy,
|
|
250
|
+
isInHotDirectory: () => isInHotDirectory,
|
|
251
|
+
restartProcess: () => restartProcess,
|
|
252
|
+
unload: () => unload
|
|
253
|
+
});
|
|
254
|
+
var RPC_RESPONSE_MARK = "$DONE:", RPC_RESPONSE_TIMEOUT = 5e3, RPC = class extends EventEmitter {
|
|
255
|
+
constructor(transport) {
|
|
72
256
|
super();
|
|
73
|
-
this.
|
|
74
|
-
|
|
75
|
-
get client() {
|
|
76
|
-
return this.source.client;
|
|
77
|
-
}
|
|
78
|
-
get channel() {
|
|
79
|
-
return this.source.channel;
|
|
80
|
-
}
|
|
81
|
-
get channelId() {
|
|
82
|
-
return this.source.channelId;
|
|
83
|
-
}
|
|
84
|
-
get guild() {
|
|
85
|
-
return this.source.guild;
|
|
86
|
-
}
|
|
87
|
-
get guildId() {
|
|
88
|
-
return this.source.guildId;
|
|
89
|
-
}
|
|
90
|
-
get member() {
|
|
91
|
-
return this.source.member;
|
|
92
|
-
}
|
|
93
|
-
inGuild() {
|
|
94
|
-
return !!this.guildId;
|
|
95
|
-
}
|
|
96
|
-
inCachedGuild() {
|
|
97
|
-
if (this.isChatInput())
|
|
98
|
-
return this.source.inCachedGuild();
|
|
99
|
-
if (this.isMessage())
|
|
100
|
-
return this.source.inGuild();
|
|
101
|
-
throw new Error("Invalid source");
|
|
102
|
-
}
|
|
103
|
-
get user() {
|
|
104
|
-
if (this.isChatInput())
|
|
105
|
-
return this.source.user;
|
|
106
|
-
if (this.isMessage())
|
|
107
|
-
return this.source.author;
|
|
108
|
-
throw new Error("Invalid source");
|
|
109
|
-
}
|
|
110
|
-
isChatInput() {
|
|
111
|
-
return this.source instanceof ChatInputCommandInteraction;
|
|
112
|
-
}
|
|
113
|
-
isMessage() {
|
|
114
|
-
return this.source instanceof Message;
|
|
115
|
-
}
|
|
116
|
-
}, ChatInputContext = class extends BaseCommandContext {
|
|
117
|
-
async send(options) {
|
|
118
|
-
typeof options == "string" && (options = { content: options });
|
|
119
|
-
let sendOptions = {
|
|
120
|
-
...options,
|
|
121
|
-
withResponse: true
|
|
122
|
-
};
|
|
123
|
-
return this.source.deferred || this.source.replied ? await this.source.followUp(sendOptions) : (await this.source.reply(sendOptions)).resource?.message;
|
|
124
|
-
}
|
|
125
|
-
}, MessageContext = class extends BaseCommandContext {
|
|
126
|
-
async send(options) {
|
|
127
|
-
let { channel } = this;
|
|
128
|
-
if (!channel?.isSendable())
|
|
129
|
-
throw new Error("Invalid channel or channel is not sendable");
|
|
130
|
-
return await channel.send(options);
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
var LifecycleManager = class {
|
|
134
|
-
constructor(id) {
|
|
135
|
-
this.id = id;
|
|
257
|
+
this.transport = transport;
|
|
258
|
+
this.transport.on("message", (message) => this.onMessage(message));
|
|
136
259
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
POST: new Collection(),
|
|
142
|
-
ERROR: new Collection()
|
|
143
|
-
};
|
|
144
|
-
getName(name) {
|
|
145
|
-
return `${this.id}:${name}`;
|
|
260
|
+
requests = /* @__PURE__ */ new Map();
|
|
261
|
+
postMessage(message) {
|
|
262
|
+
let { transport } = this;
|
|
263
|
+
"send" in transport ? transport.send(message) : "postMessage" in transport ? transport.postMessage(message) : console.warn(`${transport.constructor.name} doesn't support IPC`);
|
|
146
264
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
for (let [k, v] of existingEntries)
|
|
156
|
-
currentHooks.set(k, v);
|
|
265
|
+
onMessage(message) {
|
|
266
|
+
if (message.id.startsWith(RPC_RESPONSE_MARK)) {
|
|
267
|
+
this.handleResponseMessage(message);
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
if ("type" in message) {
|
|
271
|
+
this.handleRequestMessage(message);
|
|
272
|
+
return;
|
|
157
273
|
}
|
|
158
|
-
return this;
|
|
159
|
-
}
|
|
160
|
-
main(callback) {
|
|
161
|
-
return this.setHook("main", "MAIN" /* Main */, callback);
|
|
162
274
|
}
|
|
163
|
-
|
|
164
|
-
|
|
275
|
+
handleResponseMessage(message) {
|
|
276
|
+
let id = message.id.slice(RPC_RESPONSE_MARK.length), request = this.requests.get(id);
|
|
277
|
+
if (!request)
|
|
278
|
+
return;
|
|
279
|
+
let { reject, resolve: resolve6, timeout } = request;
|
|
280
|
+
this.requests.delete(id), clearTimeout(timeout), "data" in message ? resolve6(message.data) : reject(new Error(message.error));
|
|
165
281
|
}
|
|
166
|
-
|
|
167
|
-
|
|
282
|
+
handleRequestMessage(message) {
|
|
283
|
+
this.emit("message", message), this.emit(message.type, message.id, message.data);
|
|
168
284
|
}
|
|
169
|
-
|
|
170
|
-
|
|
285
|
+
send(type, data = {}, id = randomUUID()) {
|
|
286
|
+
let message = {
|
|
287
|
+
id,
|
|
288
|
+
type,
|
|
289
|
+
data
|
|
290
|
+
};
|
|
291
|
+
this.postMessage(message);
|
|
171
292
|
}
|
|
172
|
-
|
|
173
|
-
let
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
for (let hook of pipeline) {
|
|
179
|
-
if (context.canceled)
|
|
180
|
-
break;
|
|
181
|
-
try {
|
|
182
|
-
await hook(context, ...args);
|
|
183
|
-
} catch (e) {
|
|
184
|
-
error = e;
|
|
185
|
-
break;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
if (!error)
|
|
189
|
-
return;
|
|
190
|
-
if (!this.hooks.ERROR.size)
|
|
191
|
-
throw error;
|
|
192
|
-
for (let [key, callback] of this.hooks.ERROR.entries()) {
|
|
193
|
-
if (context.canceled)
|
|
194
|
-
break;
|
|
195
|
-
try {
|
|
196
|
-
await callback(context, error, ...args);
|
|
197
|
-
} catch (innerError) {
|
|
198
|
-
console.error(`[Lifecycle] Error handler for '${key}' failed:`, innerError);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
293
|
+
success(id, data) {
|
|
294
|
+
let message = {
|
|
295
|
+
id: `${RPC_RESPONSE_MARK}${id}`,
|
|
296
|
+
data
|
|
297
|
+
};
|
|
298
|
+
this.postMessage(message);
|
|
201
299
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
300
|
+
error(id, error) {
|
|
301
|
+
let message = {
|
|
302
|
+
id: `${RPC_RESPONSE_MARK}${id}`,
|
|
303
|
+
error
|
|
304
|
+
};
|
|
305
|
+
this.postMessage(message);
|
|
306
|
+
}
|
|
307
|
+
request(type, data, id = randomUUID()) {
|
|
308
|
+
return new Promise((resolve6, reject) => {
|
|
309
|
+
let timeout = setTimeout(() => {
|
|
310
|
+
this.requests.delete(id) && reject(new Error("Request timed out"));
|
|
311
|
+
}, RPC_RESPONSE_TIMEOUT);
|
|
312
|
+
this.requests.set(id, {
|
|
313
|
+
resolve: resolve6,
|
|
314
|
+
reject,
|
|
315
|
+
timeout
|
|
316
|
+
}), this.send(type, data, id);
|
|
317
|
+
});
|
|
208
318
|
}
|
|
209
319
|
};
|
|
210
320
|
|
|
211
|
-
// src/
|
|
212
|
-
var
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}
|
|
321
|
+
// src/lib/loader/loader.ts
|
|
322
|
+
var hooksRPC, processRPC, hotReloaders = new Collection(), reverseDependencyGraph = new Collection(), forwardDependencyGraph = new Collection();
|
|
323
|
+
function init() {
|
|
324
|
+
initProcess(), initHooks();
|
|
325
|
+
}
|
|
326
|
+
function initProcess() {
|
|
327
|
+
processRPC = new RPC(process), processRPC.on("fileChange", (_, path) => onFileChange(path)), processRPC.on("fileRemove", (_, path) => onFileRemove(path));
|
|
328
|
+
}
|
|
329
|
+
function initHooks() {
|
|
330
|
+
let { port1, port2 } = new MessageChannel(), hookPath = new URL("./hooks.js", import.meta.url).href;
|
|
331
|
+
register(hookPath, import.meta.url, {
|
|
332
|
+
data: { port: port1 },
|
|
333
|
+
transferList: [port1]
|
|
334
|
+
}), hooksRPC = new RPC(port2), hooksRPC.on("dependencyAdd", (_, data) => onDependencyAdd(data)), port2.unref();
|
|
335
|
+
}
|
|
336
|
+
function addHotReloader(reloader) {
|
|
337
|
+
hotReloaders.set(reloader.entryDirectory, reloader);
|
|
338
|
+
}
|
|
339
|
+
function unload(path) {
|
|
340
|
+
if (!hooksRPC)
|
|
341
|
+
throw new Error("Loader isn't initialized");
|
|
342
|
+
return hooksRPC.request("unload", resolve(path));
|
|
343
|
+
}
|
|
344
|
+
function getImporters(path, createNew = false) {
|
|
345
|
+
path = resolve(path);
|
|
346
|
+
let entry = reverseDependencyGraph.get(path);
|
|
347
|
+
return createNew && !entry && (entry = /* @__PURE__ */ new Set(), reverseDependencyGraph.set(path, entry)), entry;
|
|
348
|
+
}
|
|
349
|
+
function getImports(path) {
|
|
350
|
+
path = resolve(path);
|
|
351
|
+
let imports = [];
|
|
352
|
+
for (let [target, importers] of reverseDependencyGraph)
|
|
353
|
+
importers.has(path) && imports.push(target);
|
|
354
|
+
return imports;
|
|
355
|
+
}
|
|
356
|
+
function getDependencyChain(path) {
|
|
357
|
+
path = resolve(path);
|
|
358
|
+
let queue = [path], visited = /* @__PURE__ */ new Set();
|
|
359
|
+
for (; queue.length > 0; ) {
|
|
360
|
+
let current = queue.shift();
|
|
361
|
+
if (!current || visited.has(current) || (visited.add(current), current.includes("/node_modules/")))
|
|
362
|
+
continue;
|
|
363
|
+
let parents = getImporters(current);
|
|
364
|
+
if (!parents)
|
|
365
|
+
continue;
|
|
366
|
+
for (let parent of parents)
|
|
367
|
+
visited.has(parent) || queue.push(parent);
|
|
368
|
+
let children = getImports(current);
|
|
369
|
+
for (let child of children)
|
|
370
|
+
visited.has(child) || importsAny(child, visited) && queue.push(child);
|
|
371
|
+
}
|
|
372
|
+
return Array.from(visited);
|
|
373
|
+
}
|
|
374
|
+
function importsAny(path, targets) {
|
|
375
|
+
return getImports(path).some((imp) => targets.has(imp));
|
|
376
|
+
}
|
|
377
|
+
function isImported(path) {
|
|
378
|
+
return !!getImporters(path)?.size;
|
|
379
|
+
}
|
|
380
|
+
function isImportedBy(path, matcher) {
|
|
381
|
+
return getDependencyChain(path).slice(1).some((p) => {
|
|
382
|
+
let isMatch = false;
|
|
383
|
+
return typeof matcher == "string" && (isMatch = resolve(matcher) === p), typeof matcher == "function" && (isMatch = matcher(p)), matcher instanceof RegExp && (isMatch = matcher.test(p)), isMatch;
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
function onDependencyAdd(data) {
|
|
387
|
+
let { url, parentURL } = data, path = fileURLToPath(url), parentPath = fileURLToPath(parentURL);
|
|
388
|
+
if (parentPath.includes("/node_modules/"))
|
|
389
|
+
return;
|
|
390
|
+
let reverseEntry = reverseDependencyGraph.get(path);
|
|
391
|
+
reverseEntry || (reverseEntry = /* @__PURE__ */ new Set(), reverseDependencyGraph.set(path, reverseEntry)), reverseEntry.add(parentPath);
|
|
392
|
+
let forwardEntry = forwardDependencyGraph.get(parentPath);
|
|
393
|
+
forwardEntry || (forwardEntry = /* @__PURE__ */ new Set(), forwardDependencyGraph.set(parentPath, forwardEntry)), forwardEntry.add(path);
|
|
394
|
+
}
|
|
395
|
+
function isInHotDirectory(path) {
|
|
396
|
+
let sourceRoot = getEntryDirectory();
|
|
397
|
+
if (!path.startsWith(sourceRoot))
|
|
398
|
+
return false;
|
|
399
|
+
let topLevelDir = getTopLevelDirectory(path, sourceRoot);
|
|
400
|
+
if (!topLevelDir)
|
|
401
|
+
return;
|
|
402
|
+
let entryDirectory = join(sourceRoot, topLevelDir);
|
|
403
|
+
return hotReloaders.some((m) => m.entryDirectory === entryDirectory);
|
|
404
|
+
}
|
|
405
|
+
function isEntryFile(path) {
|
|
406
|
+
return path === getEntryFile();
|
|
407
|
+
}
|
|
408
|
+
function containsEntryFile(chain) {
|
|
409
|
+
return chain.some((x) => isEntryFile(x));
|
|
410
|
+
}
|
|
411
|
+
function containsHotModule(chain) {
|
|
412
|
+
return chain.some((x) => isInHotDirectory(x));
|
|
413
|
+
}
|
|
414
|
+
function restartProcess() {
|
|
415
|
+
processRPC?.send("restart");
|
|
416
|
+
}
|
|
417
|
+
async function unloadModule(path, reload = false) {
|
|
418
|
+
let topLevel = getTopLevelDirectory(path, getEntryDirectory());
|
|
419
|
+
if (!topLevel)
|
|
420
|
+
return;
|
|
421
|
+
let directory = resolve(getEntryDirectory(), topLevel), reloader = hotReloaders.get(directory);
|
|
422
|
+
if (!reloader) {
|
|
423
|
+
await unload(path);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
reloader[reload ? "reload" : "unload"](path);
|
|
427
|
+
}
|
|
428
|
+
async function onFileRemove(path) {
|
|
429
|
+
if (isEntryFile(path)) {
|
|
430
|
+
restartProcess();
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
if (!isImported(path))
|
|
434
|
+
return;
|
|
435
|
+
let chain = getDependencyChain(path);
|
|
436
|
+
if (containsEntryFile(chain)) {
|
|
437
|
+
restartProcess();
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
if (containsHotModule(chain))
|
|
441
|
+
for (let path2 of chain.reverse())
|
|
442
|
+
await unloadModule(path2);
|
|
443
|
+
}
|
|
444
|
+
async function onFileChange(path) {
|
|
445
|
+
if (isEntryFile(path)) {
|
|
446
|
+
restartProcess();
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
if (!isImported(path))
|
|
450
|
+
return;
|
|
451
|
+
let chain = getDependencyChain(path);
|
|
452
|
+
if (containsEntryFile(chain)) {
|
|
453
|
+
restartProcess();
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
if (containsHotModule(chain))
|
|
457
|
+
for (let path2 of chain.toReversed())
|
|
458
|
+
await unloadModule(path2, true);
|
|
459
|
+
}
|
|
219
460
|
|
|
220
|
-
// src/
|
|
461
|
+
// src/core/structures/param/Param.ts
|
|
221
462
|
var BaseParam = class {
|
|
222
|
-
options
|
|
223
|
-
|
|
224
|
-
|
|
463
|
+
constructor(options, schema) {
|
|
464
|
+
this.schema = schema;
|
|
465
|
+
let parsed = schema.parse({
|
|
466
|
+
...options,
|
|
467
|
+
description: options.description ?? options.name
|
|
468
|
+
});
|
|
469
|
+
this.options = parsed;
|
|
225
470
|
}
|
|
471
|
+
options;
|
|
226
472
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
227
473
|
setOption(key, value) {
|
|
228
|
-
|
|
474
|
+
if (value === null)
|
|
475
|
+
return delete this.options[key], this;
|
|
476
|
+
let fieldValidator = this.schema.shape[key];
|
|
477
|
+
if (!fieldValidator)
|
|
478
|
+
return this.options[key] = value, this;
|
|
479
|
+
let parsedValue = fieldValidator.parse(value);
|
|
480
|
+
return this.options[key] = parsedValue, this;
|
|
229
481
|
}
|
|
230
482
|
name(value) {
|
|
231
483
|
return this.setOption("name", value);
|
|
@@ -239,8 +491,15 @@ var BaseParam = class {
|
|
|
239
491
|
async resolve(context, value) {
|
|
240
492
|
if (context.isChatInput())
|
|
241
493
|
return await this.resolveChatInput(context);
|
|
242
|
-
if (context.isMessage())
|
|
494
|
+
if (context.isMessage()) {
|
|
495
|
+
let { required, name } = this.options;
|
|
496
|
+
if (value === void 0) {
|
|
497
|
+
if (required)
|
|
498
|
+
throw new ArgumentError(name, "is required");
|
|
499
|
+
return null;
|
|
500
|
+
}
|
|
243
501
|
return await this.resolveMessage(context, value);
|
|
502
|
+
}
|
|
244
503
|
throw new Error("Invalid context type provided");
|
|
245
504
|
}
|
|
246
505
|
/**
|
|
@@ -251,18 +510,13 @@ var BaseParam = class {
|
|
|
251
510
|
}
|
|
252
511
|
}, StringParam = class extends BaseParam {
|
|
253
512
|
constructor(options) {
|
|
254
|
-
super(BaseParam.getOptions(options));
|
|
513
|
+
super(BaseParam.getOptions(options), StringParamSchema);
|
|
255
514
|
}
|
|
256
515
|
required(value) {
|
|
257
516
|
return super.required(value);
|
|
258
517
|
}
|
|
259
518
|
resolveMessage(_context, value) {
|
|
260
|
-
let {
|
|
261
|
-
if (value === void 0) {
|
|
262
|
-
if (required)
|
|
263
|
-
throw new ArgumentError(name, "is required");
|
|
264
|
-
return null;
|
|
265
|
-
}
|
|
519
|
+
let { minLength, maxLength, name } = this.options;
|
|
266
520
|
if (minLength && value.length < minLength)
|
|
267
521
|
throw new ArgumentError(name, `must be at least ${minLength} chars long`);
|
|
268
522
|
if (maxLength && value.length > maxLength)
|
|
@@ -289,19 +543,13 @@ var BaseParam = class {
|
|
|
289
543
|
}
|
|
290
544
|
}, NumberParam = class extends BaseParam {
|
|
291
545
|
constructor(options) {
|
|
292
|
-
super(BaseParam.getOptions(options));
|
|
546
|
+
super(BaseParam.getOptions(options), NumberParamSchema);
|
|
293
547
|
}
|
|
294
548
|
required(value) {
|
|
295
549
|
return super.required(value);
|
|
296
550
|
}
|
|
297
|
-
resolveMessage(
|
|
298
|
-
let {
|
|
299
|
-
if (value === void 0) {
|
|
300
|
-
if (required)
|
|
301
|
-
throw new ArgumentError(name, "is required");
|
|
302
|
-
return null;
|
|
303
|
-
}
|
|
304
|
-
let num = Number(value);
|
|
551
|
+
resolveMessage(_context, value) {
|
|
552
|
+
let { minValue, maxValue, name } = this.options, num = Number(value);
|
|
305
553
|
if (isNaN(num))
|
|
306
554
|
throw new ArgumentError(name, "must be a number");
|
|
307
555
|
if (minValue !== void 0 && num < minValue)
|
|
@@ -328,18 +576,120 @@ var BaseParam = class {
|
|
|
328
576
|
max(value) {
|
|
329
577
|
return this.setOption("maxValue", value);
|
|
330
578
|
}
|
|
579
|
+
}, UserParam = class extends BaseParam {
|
|
580
|
+
constructor(options) {
|
|
581
|
+
super(BaseParam.getOptions(options), UserParamSchema);
|
|
582
|
+
}
|
|
583
|
+
required(value) {
|
|
584
|
+
return super.required(value);
|
|
585
|
+
}
|
|
586
|
+
async resolveMessage(context, value) {
|
|
587
|
+
let id = extractSnowflakeId(value);
|
|
588
|
+
if (!id)
|
|
589
|
+
return null;
|
|
590
|
+
let { users } = context.client;
|
|
591
|
+
return await users.fetch(id).catch(() => null);
|
|
592
|
+
}
|
|
593
|
+
resolveChatInput(context) {
|
|
594
|
+
let { name, required } = this.options;
|
|
595
|
+
return context.source.options.getUser(name, required);
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
var HookState = /* @__PURE__ */ ((HookState2) => (HookState2.Pre = "PRE", HookState2.Main = "MAIN", HookState2.Post = "POST", HookState2.Error = "ERROR", HookState2))(HookState || {}), HookOrder = /* @__PURE__ */ ((HookOrder2) => (HookOrder2[HookOrder2.First = 0] = "First", HookOrder2[HookOrder2.Last = 1] = "Last", HookOrder2))(HookOrder || {}), LifecycleManager = class {
|
|
599
|
+
constructor(id) {
|
|
600
|
+
this.id = id;
|
|
601
|
+
}
|
|
602
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
603
|
+
hooks = {
|
|
604
|
+
MAIN: new Collection(),
|
|
605
|
+
PRE: new Collection(),
|
|
606
|
+
POST: new Collection(),
|
|
607
|
+
ERROR: new Collection()
|
|
608
|
+
};
|
|
609
|
+
getName(name) {
|
|
610
|
+
return `${this.id}:${name}`;
|
|
611
|
+
}
|
|
612
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
613
|
+
setHook(name, state, callback, order = 1 /* Last */) {
|
|
614
|
+
let currentHooks = this.hooks[state], key = this.getName(name);
|
|
615
|
+
if (currentHooks.has(key) && console.warn(`Overriding duplicate hook '${key}' for state '${state}'`), order === 1 /* Last */)
|
|
616
|
+
currentHooks.set(key, callback);
|
|
617
|
+
else {
|
|
618
|
+
let existingEntries = [...currentHooks.entries()].filter(([k]) => k !== key);
|
|
619
|
+
currentHooks.clear(), currentHooks.set(key, callback);
|
|
620
|
+
for (let [k, v] of existingEntries)
|
|
621
|
+
currentHooks.set(k, v);
|
|
622
|
+
}
|
|
623
|
+
return this;
|
|
624
|
+
}
|
|
625
|
+
main(callback) {
|
|
626
|
+
return this.setHook("main", "MAIN" /* Main */, callback);
|
|
627
|
+
}
|
|
628
|
+
pre(callback) {
|
|
629
|
+
return this.setHook("pre", "PRE" /* Pre */, callback);
|
|
630
|
+
}
|
|
631
|
+
post(callback) {
|
|
632
|
+
return this.setHook("post", "POST" /* Post */, callback);
|
|
633
|
+
}
|
|
634
|
+
error(callback) {
|
|
635
|
+
return this.setHook("error", "ERROR" /* Error */, callback);
|
|
636
|
+
}
|
|
637
|
+
async execute(context, ...args) {
|
|
638
|
+
let pipeline = [
|
|
639
|
+
...this.hooks.PRE.values(),
|
|
640
|
+
...this.hooks.MAIN.values(),
|
|
641
|
+
...this.hooks.POST.values()
|
|
642
|
+
], error;
|
|
643
|
+
for (let hook of pipeline) {
|
|
644
|
+
if (context.canceled)
|
|
645
|
+
break;
|
|
646
|
+
try {
|
|
647
|
+
await hook(context, ...args);
|
|
648
|
+
} catch (e) {
|
|
649
|
+
error = e;
|
|
650
|
+
break;
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
if (!error)
|
|
654
|
+
return;
|
|
655
|
+
if (!this.hooks.ERROR.size)
|
|
656
|
+
throw error;
|
|
657
|
+
for (let [key, callback] of this.hooks.ERROR.entries()) {
|
|
658
|
+
if (context.canceled)
|
|
659
|
+
break;
|
|
660
|
+
try {
|
|
661
|
+
await callback(context, error, ...args);
|
|
662
|
+
} catch (innerError) {
|
|
663
|
+
console.error(`[Lifecycle] Error handler for '${key}' failed:`, innerError);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
}
|
|
331
667
|
};
|
|
332
668
|
|
|
333
|
-
// src/
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
669
|
+
// src/core/structures/Command.ts
|
|
670
|
+
function validateParamsOrder(params) {
|
|
671
|
+
let seenOptional = false;
|
|
672
|
+
for (let param of params)
|
|
673
|
+
if (param.options.required) {
|
|
674
|
+
if (seenOptional)
|
|
675
|
+
return false;
|
|
676
|
+
} else
|
|
677
|
+
seenOptional = true;
|
|
678
|
+
return true;
|
|
679
|
+
}
|
|
680
|
+
var CommandOptionsSchema = z2.object({
|
|
681
|
+
name: z2.string().readonly(),
|
|
682
|
+
description: z2.string().min(1).max(100).optional().readonly(),
|
|
683
|
+
nsfw: z2.boolean().default(false).readonly(),
|
|
684
|
+
params: z2.array(z2.instanceof(BaseParam)).default([]).readonly(),
|
|
685
|
+
quotes: z2.boolean().default(true).readonly()
|
|
339
686
|
}).transform((data) => ({
|
|
340
687
|
...data,
|
|
341
688
|
description: data.description ?? `Command ${data.name}`
|
|
342
|
-
}))
|
|
689
|
+
})).refine(({ params }) => validateParamsOrder(params), {
|
|
690
|
+
path: ["params"],
|
|
691
|
+
error: "Required params must be placed before optional params"
|
|
692
|
+
}), Command = class extends LifecycleManager {
|
|
343
693
|
constructor(options) {
|
|
344
694
|
let _options = CommandOptionsSchema.parse(typeof options == "string" ? { name: options } : options);
|
|
345
695
|
super(`command:${_options.name}`), this.options = _options, this.setHook("syntaxError", "ERROR" /* Error */, async (ctx, error, ...args) => {
|
|
@@ -349,42 +699,100 @@ var CommandOptionsSchema = z.object({
|
|
|
349
699
|
async handleSyntaxError(context, error, _args) {
|
|
350
700
|
error instanceof BakitError && await context.send(error.message);
|
|
351
701
|
}
|
|
702
|
+
toSlashCommandJSON() {
|
|
703
|
+
let { name, description, nsfw, params } = this.options, builder = new SlashCommandBuilder().setName(name).setDescription(description).setNSFW(nsfw);
|
|
704
|
+
return this.initSlashCommandOptions(builder, params), builder.toJSON();
|
|
705
|
+
}
|
|
706
|
+
initSlashCommandOptions(builder, params) {
|
|
707
|
+
for (let param of params)
|
|
708
|
+
this.initSlashCommandOption(builder, param);
|
|
709
|
+
}
|
|
710
|
+
initSlashCommandOption(builder, param) {
|
|
711
|
+
let initOption = (builder2) => {
|
|
712
|
+
let { name, description, required } = param.options;
|
|
713
|
+
return builder2.setName(name).setDescription(description).setRequired(required);
|
|
714
|
+
};
|
|
715
|
+
if (param instanceof StringParam) {
|
|
716
|
+
let { maxLength, minLength } = param.options, option = initOption(new SlashCommandStringOption());
|
|
717
|
+
maxLength && option.setMaxLength(maxLength), minLength && option.setMinLength(minLength), builder.addStringOption(option);
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
if (param instanceof NumberParam) {
|
|
721
|
+
let { maxValue, minValue } = param.options, option = initOption(new SlashCommandNumberOption());
|
|
722
|
+
maxValue && option.setMaxValue(maxValue), minValue && option.setMinValue(minValue), builder.addNumberOption(option);
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
if (param instanceof UserParam) {
|
|
726
|
+
let option = initOption(new SlashCommandUserOption());
|
|
727
|
+
builder.addUserOption(option);
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
352
731
|
};
|
|
353
732
|
function defineCommand(options) {
|
|
354
733
|
return new Command(options);
|
|
355
734
|
}
|
|
735
|
+
var HotReloadable2 = class {
|
|
736
|
+
constructor(entryDirectory) {
|
|
737
|
+
this.entryDirectory = entryDirectory;
|
|
738
|
+
entryDirectory = resolve(entryDirectory);
|
|
739
|
+
}
|
|
740
|
+
unloadFile(path) {
|
|
741
|
+
return loader_exports.unload(path);
|
|
742
|
+
}
|
|
743
|
+
};
|
|
356
744
|
|
|
357
|
-
// src/
|
|
358
|
-
var
|
|
745
|
+
// src/core/managers/CommandManager.ts
|
|
746
|
+
var CommandManager = class extends HotReloadable2 {
|
|
359
747
|
constructor(client) {
|
|
748
|
+
super(join(getEntryDirectory(), "commands"));
|
|
360
749
|
this.client = client;
|
|
361
750
|
}
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
// src/command/CommandManager.ts
|
|
365
|
-
var CommandManager = class extends BaseClientManager {
|
|
366
751
|
commands = new Collection();
|
|
752
|
+
entries = new Collection();
|
|
367
753
|
async loadModules() {
|
|
368
|
-
let
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
|
|
754
|
+
let pattern = join(this.entryDirectory, "**/*.{ts,js}"), files = await glob(pattern, { cwd: process.cwd(), absolute: true }), filtered = (await Promise.all(files.map((file) => this.load(file)))).filter((c) => !!c);
|
|
755
|
+
return console.log(`[Loader] Loaded ${filtered.length}/${files.length} command(s)`), filtered;
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
* Load the file and add the command to the registry.
|
|
759
|
+
* @param path The path to the command file.
|
|
760
|
+
* @returns The command object if added successfully.
|
|
761
|
+
*/
|
|
762
|
+
async load(path) {
|
|
763
|
+
path = resolve(path);
|
|
764
|
+
let command = (await import(pathToFileURL(path).href)).default;
|
|
765
|
+
if (!command) {
|
|
766
|
+
console.warn(`[Loader] File has no default export: ${path}`);
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
if (!(command instanceof Command)) {
|
|
770
|
+
console.warn(`[Loader] Default export is not a Command: ${path}`);
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
return this.add(command), this.entries.set(path, command), command;
|
|
387
774
|
}
|
|
775
|
+
/**
|
|
776
|
+
* Unload the file and remove the command from the registry.
|
|
777
|
+
* @param path The path to the command file.
|
|
778
|
+
* @returns The command object if unloaded successfully.
|
|
779
|
+
*/
|
|
780
|
+
async unload(path) {
|
|
781
|
+
path = resolve(path);
|
|
782
|
+
let command = this.entries.get(path);
|
|
783
|
+
if (this.entries.delete(path), await this.unloadFile(path), !!command)
|
|
784
|
+
return this.remove(command);
|
|
785
|
+
}
|
|
786
|
+
async reload(path) {
|
|
787
|
+
path = resolve(path), await this.unload(path);
|
|
788
|
+
let command = await this.load(path);
|
|
789
|
+
if (command)
|
|
790
|
+
return console.log(`[Loader] Reloaded command '${command.options.name}' at '${path}'`), command;
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Add a command to the registry.
|
|
794
|
+
* @param command Command to add.
|
|
795
|
+
*/
|
|
388
796
|
add(command) {
|
|
389
797
|
if (!(command instanceof Command))
|
|
390
798
|
throw new Error("Invalid command provided");
|
|
@@ -395,18 +803,30 @@ var CommandManager = class extends BaseClientManager {
|
|
|
395
803
|
}
|
|
396
804
|
this.commands.set(name, command);
|
|
397
805
|
}
|
|
806
|
+
/**
|
|
807
|
+
* Remove a command from the registry.
|
|
808
|
+
* @param target Command name or object to remove.
|
|
809
|
+
* @returns The command object if removed successfully.
|
|
810
|
+
*/
|
|
398
811
|
remove(target) {
|
|
812
|
+
if (typeof target != "string" && !(target instanceof Command))
|
|
813
|
+
return;
|
|
399
814
|
let name = typeof target == "string" ? target : target.options.name, existing = this.commands.get(name);
|
|
400
815
|
if (existing)
|
|
401
816
|
return this.commands.delete(name), existing;
|
|
402
817
|
}
|
|
818
|
+
/**
|
|
819
|
+
* Get a command using its name.
|
|
820
|
+
* @param name The command to get.
|
|
821
|
+
* @returns The command object.
|
|
822
|
+
*/
|
|
403
823
|
get(name) {
|
|
404
824
|
return this.commands.get(name);
|
|
405
825
|
}
|
|
406
826
|
};
|
|
407
|
-
var ListenerOptionsSchema =
|
|
408
|
-
name:
|
|
409
|
-
once:
|
|
827
|
+
var ListenerOptionsSchema = z2.object({
|
|
828
|
+
name: z2.enum(Events),
|
|
829
|
+
once: z2.boolean().default(false)
|
|
410
830
|
}), Listener = class extends LifecycleManager {
|
|
411
831
|
options;
|
|
412
832
|
constructor(options) {
|
|
@@ -417,138 +837,80 @@ var ListenerOptionsSchema = z3.object({
|
|
|
417
837
|
function defineListener(options) {
|
|
418
838
|
return new Listener(options);
|
|
419
839
|
}
|
|
420
|
-
var INTENT_GROUPS = {
|
|
421
|
-
[GatewayIntentBits.Guilds]: [
|
|
422
|
-
Events.GuildCreate,
|
|
423
|
-
Events.GuildDelete,
|
|
424
|
-
Events.GuildUpdate,
|
|
425
|
-
Events.GuildUnavailable,
|
|
426
|
-
Events.GuildRoleCreate,
|
|
427
|
-
Events.GuildRoleDelete,
|
|
428
|
-
Events.GuildRoleUpdate,
|
|
429
|
-
Events.ChannelCreate,
|
|
430
|
-
Events.ChannelDelete,
|
|
431
|
-
Events.ChannelUpdate,
|
|
432
|
-
Events.ChannelPinsUpdate,
|
|
433
|
-
Events.ThreadCreate,
|
|
434
|
-
Events.ThreadDelete,
|
|
435
|
-
Events.ThreadUpdate,
|
|
436
|
-
Events.ThreadListSync,
|
|
437
|
-
Events.ThreadMemberUpdate,
|
|
438
|
-
Events.ThreadMembersUpdate,
|
|
439
|
-
Events.StageInstanceCreate,
|
|
440
|
-
Events.StageInstanceUpdate,
|
|
441
|
-
Events.StageInstanceDelete
|
|
442
|
-
],
|
|
443
|
-
[GatewayIntentBits.GuildMembers]: [
|
|
444
|
-
Events.GuildMemberAdd,
|
|
445
|
-
Events.GuildMemberUpdate,
|
|
446
|
-
Events.GuildMemberRemove,
|
|
447
|
-
Events.ThreadMembersUpdate
|
|
448
|
-
],
|
|
449
|
-
[GatewayIntentBits.GuildModeration]: [Events.GuildAuditLogEntryCreate, Events.GuildBanAdd, Events.GuildBanRemove],
|
|
450
|
-
[GatewayIntentBits.GuildExpressions]: [
|
|
451
|
-
Events.GuildEmojiCreate,
|
|
452
|
-
Events.GuildEmojiDelete,
|
|
453
|
-
Events.GuildEmojiUpdate,
|
|
454
|
-
Events.GuildStickerCreate,
|
|
455
|
-
Events.GuildStickerDelete,
|
|
456
|
-
Events.GuildStickerUpdate,
|
|
457
|
-
Events.GuildSoundboardSoundCreate,
|
|
458
|
-
Events.GuildSoundboardSoundUpdate,
|
|
459
|
-
Events.GuildSoundboardSoundDelete,
|
|
460
|
-
Events.GuildSoundboardSoundsUpdate
|
|
461
|
-
],
|
|
462
|
-
[GatewayIntentBits.GuildIntegrations]: [Events.GuildIntegrationsUpdate],
|
|
463
|
-
[GatewayIntentBits.GuildWebhooks]: [Events.WebhooksUpdate],
|
|
464
|
-
[GatewayIntentBits.GuildInvites]: [Events.InviteCreate, Events.InviteDelete],
|
|
465
|
-
[GatewayIntentBits.GuildVoiceStates]: [Events.VoiceStateUpdate],
|
|
466
|
-
[GatewayIntentBits.GuildPresences]: [Events.PresenceUpdate],
|
|
467
|
-
[GatewayIntentBits.GuildMessages]: [
|
|
468
|
-
Events.MessageCreate,
|
|
469
|
-
Events.MessageUpdate,
|
|
470
|
-
Events.MessageDelete,
|
|
471
|
-
Events.MessageBulkDelete
|
|
472
|
-
],
|
|
473
|
-
[GatewayIntentBits.GuildMessageReactions]: [
|
|
474
|
-
Events.MessageReactionAdd,
|
|
475
|
-
Events.MessageReactionRemove,
|
|
476
|
-
Events.MessageReactionRemoveAll,
|
|
477
|
-
Events.MessageReactionRemoveEmoji
|
|
478
|
-
],
|
|
479
|
-
[GatewayIntentBits.GuildMessageTyping]: [Events.TypingStart],
|
|
480
|
-
[GatewayIntentBits.DirectMessages]: [
|
|
481
|
-
Events.MessageCreate,
|
|
482
|
-
Events.MessageUpdate,
|
|
483
|
-
Events.MessageDelete,
|
|
484
|
-
Events.ChannelPinsUpdate
|
|
485
|
-
],
|
|
486
|
-
[GatewayIntentBits.DirectMessageReactions]: [
|
|
487
|
-
Events.MessageReactionAdd,
|
|
488
|
-
Events.MessageReactionRemove,
|
|
489
|
-
Events.MessageReactionRemoveAll,
|
|
490
|
-
Events.MessageReactionRemoveEmoji
|
|
491
|
-
],
|
|
492
|
-
[GatewayIntentBits.DirectMessageTyping]: [Events.TypingStart],
|
|
493
|
-
[GatewayIntentBits.MessageContent]: [Events.MessageCreate, Events.MessageUpdate],
|
|
494
|
-
[GatewayIntentBits.GuildScheduledEvents]: [
|
|
495
|
-
Events.GuildScheduledEventCreate,
|
|
496
|
-
Events.GuildScheduledEventDelete,
|
|
497
|
-
Events.GuildScheduledEventUpdate,
|
|
498
|
-
Events.GuildScheduledEventUserAdd,
|
|
499
|
-
Events.GuildScheduledEventUserRemove
|
|
500
|
-
],
|
|
501
|
-
[GatewayIntentBits.AutoModerationConfiguration]: [
|
|
502
|
-
Events.AutoModerationRuleCreate,
|
|
503
|
-
Events.AutoModerationRuleDelete,
|
|
504
|
-
Events.AutoModerationRuleUpdate
|
|
505
|
-
],
|
|
506
|
-
[GatewayIntentBits.AutoModerationExecution]: [Events.AutoModerationActionExecution],
|
|
507
|
-
[GatewayIntentBits.GuildMessagePolls]: [Events.MessagePollVoteAdd, Events.MessagePollVoteRemove],
|
|
508
|
-
[GatewayIntentBits.DirectMessagePolls]: [Events.MessagePollVoteAdd, Events.MessagePollVoteRemove]
|
|
509
|
-
}, EVENT_INTENT_MAPPING = {};
|
|
510
|
-
for (let [intentStr, events] of Object.entries(INTENT_GROUPS)) {
|
|
511
|
-
let intent = Number(intentStr);
|
|
512
|
-
for (let event of events)
|
|
513
|
-
EVENT_INTENT_MAPPING[event] ??= [], EVENT_INTENT_MAPPING[event].includes(intent) || EVENT_INTENT_MAPPING[event].push(intent);
|
|
514
|
-
}
|
|
515
840
|
|
|
516
|
-
// src/
|
|
517
|
-
var
|
|
841
|
+
// src/core/context/Context.ts
|
|
842
|
+
var Context = class {
|
|
843
|
+
canceled = false;
|
|
844
|
+
cancel() {
|
|
845
|
+
this.canceled = true;
|
|
846
|
+
}
|
|
847
|
+
};
|
|
848
|
+
|
|
849
|
+
// src/core/managers/ListenerManager.ts
|
|
850
|
+
var ListenerManager = class extends HotReloadable2 {
|
|
851
|
+
constructor(client) {
|
|
852
|
+
super(join(getEntryDirectory(), "listeners"));
|
|
853
|
+
this.client = client;
|
|
854
|
+
}
|
|
518
855
|
listeners = [];
|
|
519
|
-
|
|
856
|
+
entries = new Collection();
|
|
520
857
|
executors = /* @__PURE__ */ new WeakMap();
|
|
521
858
|
async loadModules() {
|
|
522
|
-
let
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
|
|
859
|
+
let pattern = join(this.entryDirectory, "**/*.{ts,js}"), files = await glob(pattern, { cwd: process.cwd(), absolute: true }), filtered = (await Promise.all(files.map((file) => this.load(file)))).filter((l) => !!l);
|
|
860
|
+
return console.log(`[Loader] Loaded ${filtered.length}/${files.length} listener(s)`), filtered;
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* Load the file and add the listener to the registry.
|
|
864
|
+
* @param path The path to the listener file.
|
|
865
|
+
* @returns The listener object if added successfully.
|
|
866
|
+
*/
|
|
867
|
+
async load(path) {
|
|
868
|
+
path = resolve(path);
|
|
869
|
+
let listener = (await import(pathToFileURL(path).href)).default;
|
|
870
|
+
if (!listener) {
|
|
871
|
+
console.warn(`[Loader] File has no default export: ${path}`);
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
874
|
+
if (!(listener instanceof Listener)) {
|
|
875
|
+
console.warn(`[Loader] Default export is not a Listener: ${path}`);
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
return this.add(listener), this.entries.set(path, listener), listener;
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Unload the file and remove the listener from the registry.
|
|
882
|
+
* @param path The path to the listener file.
|
|
883
|
+
* @returns The listener object if unloaded successfully.
|
|
884
|
+
*/
|
|
885
|
+
async unload(path) {
|
|
886
|
+
path = resolve(path);
|
|
887
|
+
let listener = this.entries.get(path);
|
|
888
|
+
if (this.entries.delete(path), await this.unloadFile(path), !!listener)
|
|
889
|
+
return this.remove(listener)?.[0];
|
|
890
|
+
}
|
|
891
|
+
async reload(path) {
|
|
892
|
+
path = resolve(path), await this.unload(path);
|
|
893
|
+
let listener = await this.load(path);
|
|
894
|
+
if (listener)
|
|
895
|
+
return console.log(`[Loader] Reloaded listener '${listener.options.name}' at '${path}'`), listener;
|
|
541
896
|
}
|
|
897
|
+
/**
|
|
898
|
+
* Add a listener to the registry and create a listener for client.
|
|
899
|
+
* @param listener Listener to add.
|
|
900
|
+
*/
|
|
542
901
|
add(listener) {
|
|
543
902
|
if (!(listener instanceof Listener))
|
|
544
903
|
throw new Error("Invalid listener provided");
|
|
545
|
-
let execute = (...args) => {
|
|
904
|
+
let { once, name } = listener.options, execute = (...args) => {
|
|
546
905
|
listener.execute(new Context(), ...args);
|
|
547
906
|
};
|
|
548
|
-
this.listeners.push(listener), this.executors.set(listener, execute);
|
|
549
|
-
let { once, name } = listener.options;
|
|
550
|
-
this.client[once ? "once" : "on"](name, execute);
|
|
907
|
+
this.listeners.push(listener), this.executors.set(listener, execute), this.client[once ? "once" : "on"](name, execute);
|
|
551
908
|
}
|
|
909
|
+
/**
|
|
910
|
+
* Remove a listener from the registry and client.
|
|
911
|
+
* @param target Listener name or object to remove.
|
|
912
|
+
* @returns The list of listener objects if removed successfully.
|
|
913
|
+
*/
|
|
552
914
|
remove(target) {
|
|
553
915
|
let isMatched = (listener) => typeof target == "string" ? listener.options.name === target : listener === target, removed = [];
|
|
554
916
|
return this.listeners = this.listeners.filter((listener) => {
|
|
@@ -559,9 +921,17 @@ var ListenerManager = class extends BaseClientManager {
|
|
|
559
921
|
return execute && (this.client.removeListener(listener.options.name, execute), this.executors.delete(listener)), false;
|
|
560
922
|
}), removed;
|
|
561
923
|
}
|
|
924
|
+
/**
|
|
925
|
+
* Get a list of required intents for Bakit to run correctly.
|
|
926
|
+
* @returns Used intents.
|
|
927
|
+
*/
|
|
562
928
|
getBaseIntents() {
|
|
563
929
|
return new IntentsBitField([GatewayIntentBits.Guilds]);
|
|
564
930
|
}
|
|
931
|
+
/**
|
|
932
|
+
* Get a list of needed intents based on registered listeners to receive needed events.
|
|
933
|
+
* @returns Used intents.
|
|
934
|
+
*/
|
|
565
935
|
getNeededIntents() {
|
|
566
936
|
let result = this.getBaseIntents();
|
|
567
937
|
for (let listener of this.listeners) {
|
|
@@ -572,15 +942,17 @@ var ListenerManager = class extends BaseClientManager {
|
|
|
572
942
|
}
|
|
573
943
|
};
|
|
574
944
|
|
|
575
|
-
// src/BakitClient.ts
|
|
576
|
-
var
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
945
|
+
// src/core/client/BakitClient.ts
|
|
946
|
+
var BakitClient = class extends Client {
|
|
947
|
+
constructor(options, instance) {
|
|
948
|
+
super(options);
|
|
949
|
+
this.instance = instance;
|
|
950
|
+
this.managers = {
|
|
580
951
|
commands: new CommandManager(this),
|
|
581
952
|
listeners: new ListenerManager(this)
|
|
582
953
|
};
|
|
583
954
|
}
|
|
955
|
+
managers;
|
|
584
956
|
/**
|
|
585
957
|
* Check if the client is connected to gateway successfully and finished initialization.
|
|
586
958
|
*/
|
|
@@ -613,25 +985,213 @@ var BakitClient3 = class extends Client {
|
|
|
613
985
|
return `${this.constructor.name} {}`;
|
|
614
986
|
}
|
|
615
987
|
};
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
988
|
+
|
|
989
|
+
// src/core/managers/BaseClientManager.ts
|
|
990
|
+
var BaseClientManager = class {
|
|
991
|
+
constructor(client) {
|
|
992
|
+
this.client = client;
|
|
993
|
+
}
|
|
994
|
+
};
|
|
995
|
+
var BaseCommandContext = class extends Context {
|
|
996
|
+
constructor(source) {
|
|
997
|
+
super();
|
|
998
|
+
this.source = source;
|
|
999
|
+
}
|
|
1000
|
+
get client() {
|
|
1001
|
+
return this.source.client;
|
|
1002
|
+
}
|
|
1003
|
+
get channel() {
|
|
1004
|
+
return this.source.channel;
|
|
1005
|
+
}
|
|
1006
|
+
get channelId() {
|
|
1007
|
+
return this.source.channelId;
|
|
1008
|
+
}
|
|
1009
|
+
get guild() {
|
|
1010
|
+
return this.source.guild;
|
|
1011
|
+
}
|
|
1012
|
+
get guildId() {
|
|
1013
|
+
return this.source.guildId;
|
|
1014
|
+
}
|
|
1015
|
+
get member() {
|
|
1016
|
+
return this.source.member;
|
|
1017
|
+
}
|
|
1018
|
+
inGuild() {
|
|
1019
|
+
return !!this.guildId;
|
|
1020
|
+
}
|
|
1021
|
+
inCachedGuild() {
|
|
1022
|
+
if (this.isChatInput())
|
|
1023
|
+
return this.source.inCachedGuild();
|
|
1024
|
+
if (this.isMessage())
|
|
1025
|
+
return this.source.inGuild();
|
|
1026
|
+
throw new Error("Invalid source");
|
|
1027
|
+
}
|
|
1028
|
+
get user() {
|
|
1029
|
+
if (this.isChatInput())
|
|
1030
|
+
return this.source.user;
|
|
1031
|
+
if (this.isMessage())
|
|
1032
|
+
return this.source.author;
|
|
1033
|
+
throw new Error("Invalid source");
|
|
1034
|
+
}
|
|
1035
|
+
isChatInput() {
|
|
1036
|
+
return this.source instanceof ChatInputCommandInteraction;
|
|
1037
|
+
}
|
|
1038
|
+
isMessage() {
|
|
1039
|
+
return this.source instanceof Message;
|
|
1040
|
+
}
|
|
1041
|
+
}, ChatInputContext = class extends BaseCommandContext {
|
|
1042
|
+
async send(options) {
|
|
1043
|
+
typeof options == "string" && (options = { content: options });
|
|
1044
|
+
let sendOptions = {
|
|
1045
|
+
...options,
|
|
1046
|
+
withResponse: true
|
|
1047
|
+
};
|
|
1048
|
+
return this.source.deferred || this.source.replied ? await this.source.followUp(sendOptions) : (await this.source.reply(sendOptions)).resource?.message;
|
|
1049
|
+
}
|
|
1050
|
+
}, MessageContext = class extends BaseCommandContext {
|
|
1051
|
+
async send(options) {
|
|
1052
|
+
let { channel } = this;
|
|
1053
|
+
if (!channel?.isSendable())
|
|
1054
|
+
throw new Error("Invalid channel or channel is not sendable");
|
|
1055
|
+
return await channel.send(options);
|
|
1056
|
+
}
|
|
1057
|
+
};
|
|
1058
|
+
var ProjectCacheManager = class {
|
|
1059
|
+
rootDir;
|
|
1060
|
+
constructor(root = process.cwd()) {
|
|
1061
|
+
this.rootDir = join(root, ".bakit"), this.ensureRoot();
|
|
1062
|
+
}
|
|
1063
|
+
ensureRoot() {
|
|
1064
|
+
existsSync(this.rootDir) || mkdirSync(this.rootDir, { recursive: true });
|
|
1065
|
+
}
|
|
1066
|
+
getHash(data) {
|
|
1067
|
+
return createHash("sha256").update(JSON.stringify(data)).digest("hex");
|
|
1068
|
+
}
|
|
1069
|
+
async write(path, data) {
|
|
1070
|
+
let fullPath = join(this.rootDir, path), dir = dirname(fullPath);
|
|
1071
|
+
await mkdir(dir, { recursive: true });
|
|
1072
|
+
let content = typeof data == "string" ? data : JSON.stringify(data);
|
|
1073
|
+
await writeFile(fullPath, content, "utf-8");
|
|
1074
|
+
}
|
|
1075
|
+
async read(path) {
|
|
1076
|
+
let fullPath = join(this.rootDir, path);
|
|
1077
|
+
try {
|
|
1078
|
+
let content = await readFile(fullPath, "utf-8");
|
|
1079
|
+
return JSON.parse(content);
|
|
1080
|
+
} catch {
|
|
1081
|
+
return null;
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
async clear() {
|
|
1085
|
+
await rm(this.rootDir, { recursive: true, force: true });
|
|
1086
|
+
}
|
|
1087
|
+
clearSync() {
|
|
1088
|
+
existsSync(this.rootDir) && rmSync(this.rootDir, { recursive: true, force: true });
|
|
1089
|
+
}
|
|
1090
|
+
};
|
|
1091
|
+
var messageCommandHandler = defineListener(Events.MessageCreate), chatInputCommandHandler = defineListener(Events.InteractionCreate), registerCommandsHandler = defineListener({
|
|
1092
|
+
name: Events.ClientReady,
|
|
1093
|
+
once: true
|
|
626
1094
|
});
|
|
1095
|
+
registerCommandsHandler.main(async (_, client) => {
|
|
1096
|
+
let { managers, instance } = client, { commands } = managers, { cache } = instance, payload = commands.commands.map((cmd) => cmd.toSlashCommandJSON()).sort((a, b) => a.name.localeCompare(b.name)), currentHash = cache.getHash(payload), CACHE_KEY = "commands/meta.json", cachedMeta = await cache.read(CACHE_KEY);
|
|
1097
|
+
if (cachedMeta && cachedMeta.hash === currentHash) {
|
|
1098
|
+
let { timestamp, count } = cachedMeta, time = new Date(timestamp).toLocaleString();
|
|
1099
|
+
console.log(`${count} command(s) are up to date (Last sync: ${time}). Skipping registration.`);
|
|
1100
|
+
return;
|
|
1101
|
+
}
|
|
1102
|
+
try {
|
|
1103
|
+
let result = await client.application.commands.set(payload);
|
|
1104
|
+
cache.write(CACHE_KEY, {
|
|
1105
|
+
hash: currentHash,
|
|
1106
|
+
timestamp: Date.now(),
|
|
1107
|
+
count: result.size
|
|
1108
|
+
}), cache.write("commands/debug_dump.json", payload), console.log(`Registered ${result.size} application command(s).`);
|
|
1109
|
+
} catch (error) {
|
|
1110
|
+
console.error("Failed to register commands:", error);
|
|
1111
|
+
}
|
|
1112
|
+
});
|
|
1113
|
+
messageCommandHandler.main(async (_, message) => {
|
|
1114
|
+
let config = getConfig();
|
|
1115
|
+
if (message.author.bot)
|
|
1116
|
+
return;
|
|
1117
|
+
let { content } = message, client = message.client, lowerContent = content.toLowerCase(), prefix = config.prefixes.find((p) => lowerContent.startsWith(p));
|
|
1118
|
+
if (!prefix)
|
|
1119
|
+
return;
|
|
1120
|
+
let [name, ...args] = content.slice(prefix.length).trim().split(/\s+/g);
|
|
1121
|
+
if (!name)
|
|
1122
|
+
return;
|
|
1123
|
+
let command = client.managers.commands.get(name);
|
|
1124
|
+
if (!command)
|
|
1125
|
+
return;
|
|
1126
|
+
let context = new MessageContext(message), { params, quotes } = command.options, rawArgs = quotes ? tokenize(args.join(" ")) : args, resolvedArgs = [];
|
|
1127
|
+
for (let i = 0; i < params.length; i++) {
|
|
1128
|
+
let param = params[i], arg = rawArgs[i];
|
|
1129
|
+
if (!param)
|
|
1130
|
+
break;
|
|
1131
|
+
let resolved = await param.resolve(context, arg);
|
|
1132
|
+
resolvedArgs.push(resolved);
|
|
1133
|
+
}
|
|
1134
|
+
await command.execute(context, ...resolvedArgs);
|
|
1135
|
+
});
|
|
1136
|
+
chatInputCommandHandler.main(async (_, interaction) => {
|
|
1137
|
+
if (!interaction.isChatInputCommand())
|
|
1138
|
+
return;
|
|
1139
|
+
let { commandName } = interaction, command = interaction.client.managers.commands.get(commandName);
|
|
1140
|
+
if (!command)
|
|
1141
|
+
return;
|
|
1142
|
+
let context = new ChatInputContext(interaction), { params } = command.options, resolvedArgs = [];
|
|
1143
|
+
for (let param of params) {
|
|
1144
|
+
let resolved = await param.resolve(context);
|
|
1145
|
+
resolvedArgs.push(resolved);
|
|
1146
|
+
}
|
|
1147
|
+
await command.execute(context, ...resolvedArgs);
|
|
1148
|
+
});
|
|
1149
|
+
|
|
1150
|
+
// src/core/internal/Instance.ts
|
|
1151
|
+
var Instance = class {
|
|
1152
|
+
client;
|
|
1153
|
+
cache;
|
|
1154
|
+
constructor() {
|
|
1155
|
+
this.cache = new ProjectCacheManager();
|
|
1156
|
+
}
|
|
1157
|
+
async start() {
|
|
1158
|
+
await loadConfig();
|
|
1159
|
+
let config = getConfig();
|
|
1160
|
+
this.client = new BakitClient(
|
|
1161
|
+
{
|
|
1162
|
+
intents: [],
|
|
1163
|
+
...config.clientOptions
|
|
1164
|
+
},
|
|
1165
|
+
this
|
|
1166
|
+
), await this.loadModules(), this.initIntents(), await this.client.login(config.token), this.initProcess();
|
|
1167
|
+
}
|
|
1168
|
+
initProcess() {
|
|
1169
|
+
process.on("SIGINT", () => this.shutdown()), process.on("SIGTERM", () => this.shutdown());
|
|
1170
|
+
}
|
|
1171
|
+
loadModules() {
|
|
1172
|
+
let { managers } = this.client, { commands, listeners } = managers;
|
|
1173
|
+
return listeners.add(chatInputCommandHandler), listeners.add(messageCommandHandler), listeners.add(registerCommandsHandler), addHotReloader(commands), addHotReloader(listeners), Promise.all([commands.loadModules(), listeners.loadModules()]);
|
|
1174
|
+
}
|
|
1175
|
+
initIntents() {
|
|
1176
|
+
let config = getConfig(), { options, managers } = this.client, { listeners } = managers, intents;
|
|
1177
|
+
config.intents === "auto" ? intents = listeners.getNeededIntents() : (intents = listeners.getBaseIntents(), typeof config.intents == "bigint" ? intents.bitfield = Number(config.intents) : intents.add(...config.intents)), options.intents = intents;
|
|
1178
|
+
}
|
|
1179
|
+
async shutdown() {
|
|
1180
|
+
this.client && await this.client.destroy().catch(() => null), process.exit(0);
|
|
1181
|
+
}
|
|
1182
|
+
};
|
|
1183
|
+
function useApp() {
|
|
1184
|
+
return new Instance();
|
|
1185
|
+
}
|
|
627
1186
|
|
|
628
|
-
// src/
|
|
1187
|
+
// src/core/structures/param/Params.ts
|
|
629
1188
|
function createFactory(ctor) {
|
|
630
1189
|
return (...args) => new ctor(...args);
|
|
631
1190
|
}
|
|
632
1191
|
var Params = {
|
|
633
1192
|
string: createFactory(StringParam),
|
|
634
|
-
number: createFactory(NumberParam)
|
|
1193
|
+
number: createFactory(NumberParam),
|
|
1194
|
+
user: createFactory(UserParam)
|
|
635
1195
|
};
|
|
636
1196
|
|
|
637
|
-
export {
|
|
1197
|
+
export { ArgumentError, BakitClient, BakitError, BaseClientManager, BaseCommandContext, BaseParam, BaseParamSchema, ChatInputContext, Command, CommandManager, CommandOptionsSchema, Context, EVENT_INTENT_MAPPING, HookOrder, HookState, HotReloadable2 as HotReloadable, Instance, LifecycleManager, Listener, ListenerManager, ListenerOptionsSchema, loader_exports as Loader, MessageContext, NumberParam, NumberParamSchema, ParamUserType, Params, ProjectCacheManager, ProjectConfigSchema, RPC, RPC_RESPONSE_MARK, RPC_RESPONSE_TIMEOUT, StringParam, StringParamSchema, UserParam, UserParamSchema, chatInputCommandHandler, defineCommand, defineConfig, defineListener, extractSnowflakeId, getConfig, getEntryDirectory, getEntryFile, getTopLevelDirectory, loadConfig, messageCommandHandler, registerCommandsHandler, tokenize, useApp, validateParamsOrder };
|