bakit 1.0.0-beta.9 → 2.0.0-alpha.10
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 +35 -0
- package/bin/bakit.js +39 -0
- package/dist/index.d.ts +391 -73
- package/dist/index.js +730 -1075
- package/package.json +20 -9
- package/dist/BakitClient-D9kRvFS3.d.ts +0 -224
- package/dist/command/index.d.ts +0 -3
- package/dist/command/index.js +0 -473
package/dist/index.js
CHANGED
|
@@ -1,402 +1,213 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
1
|
+
import { GatewayIntentBits, Events, Client, IntentsBitField, Collection, SlashCommandBuilder, SlashCommandStringOption, SlashCommandNumberOption, SlashCommandUserOption, ChatInputCommandInteraction, Message } from 'discord.js';
|
|
2
|
+
import z4, { z } from 'zod';
|
|
3
|
+
import glob from 'tiny-glob';
|
|
4
|
+
import { createJiti } from 'jiti';
|
|
5
|
+
import { inspect } from 'util';
|
|
6
|
+
import { posix, join, dirname } from 'path';
|
|
7
|
+
import { existsSync, mkdirSync, rmSync } from 'fs';
|
|
8
|
+
import { mkdir, writeFile, readFile, rm } from 'fs/promises';
|
|
9
|
+
import { createHash } from 'crypto';
|
|
3
10
|
|
|
4
|
-
// src/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
this.children.set(fullOptions.name, group);
|
|
100
|
-
return group;
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
var CommandGroupEntry = class extends BaseCommandGroupEntry {
|
|
104
|
-
constructor(options, parent) {
|
|
105
|
-
super(options);
|
|
106
|
-
this.parent = parent;
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
var SubcommandEntry = class extends BaseCommandEntry {
|
|
110
|
-
constructor(options, parent) {
|
|
111
|
-
super(options);
|
|
112
|
-
this.parent = parent;
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
// src/command/Command.ts
|
|
117
|
-
var CommandAPI;
|
|
118
|
-
((CommandAPI2) => {
|
|
119
|
-
const rootEntries = /* @__PURE__ */ new WeakMap();
|
|
120
|
-
function use(root) {
|
|
121
|
-
return (target) => {
|
|
122
|
-
root.setTarget(target);
|
|
123
|
-
rootEntries.set(target, root);
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
CommandAPI2.use = use;
|
|
127
|
-
function getRoot(constructor) {
|
|
128
|
-
return rootEntries.get(constructor);
|
|
129
|
-
}
|
|
130
|
-
CommandAPI2.getRoot = getRoot;
|
|
131
|
-
})(CommandAPI || (CommandAPI = {}));
|
|
132
|
-
function CommandFactory(options) {
|
|
133
|
-
if (typeof options === "string") {
|
|
134
|
-
options = { name: options };
|
|
135
|
-
}
|
|
136
|
-
if (!options.description) {
|
|
137
|
-
options.description = options.name;
|
|
138
|
-
}
|
|
139
|
-
return new RootCommandEntry(options);
|
|
11
|
+
// src/config.ts
|
|
12
|
+
var INTENT_GROUPS = {
|
|
13
|
+
[GatewayIntentBits.Guilds]: [
|
|
14
|
+
Events.GuildCreate,
|
|
15
|
+
Events.GuildDelete,
|
|
16
|
+
Events.GuildUpdate,
|
|
17
|
+
Events.GuildUnavailable,
|
|
18
|
+
Events.GuildRoleCreate,
|
|
19
|
+
Events.GuildRoleDelete,
|
|
20
|
+
Events.GuildRoleUpdate,
|
|
21
|
+
Events.ChannelCreate,
|
|
22
|
+
Events.ChannelDelete,
|
|
23
|
+
Events.ChannelUpdate,
|
|
24
|
+
Events.ChannelPinsUpdate,
|
|
25
|
+
Events.ThreadCreate,
|
|
26
|
+
Events.ThreadDelete,
|
|
27
|
+
Events.ThreadUpdate,
|
|
28
|
+
Events.ThreadListSync,
|
|
29
|
+
Events.ThreadMemberUpdate,
|
|
30
|
+
Events.ThreadMembersUpdate,
|
|
31
|
+
Events.StageInstanceCreate,
|
|
32
|
+
Events.StageInstanceUpdate,
|
|
33
|
+
Events.StageInstanceDelete
|
|
34
|
+
],
|
|
35
|
+
[GatewayIntentBits.GuildMembers]: [
|
|
36
|
+
Events.GuildMemberAdd,
|
|
37
|
+
Events.GuildMemberUpdate,
|
|
38
|
+
Events.GuildMemberRemove,
|
|
39
|
+
Events.ThreadMembersUpdate
|
|
40
|
+
],
|
|
41
|
+
[GatewayIntentBits.GuildModeration]: [Events.GuildAuditLogEntryCreate, Events.GuildBanAdd, Events.GuildBanRemove],
|
|
42
|
+
[GatewayIntentBits.GuildExpressions]: [
|
|
43
|
+
Events.GuildEmojiCreate,
|
|
44
|
+
Events.GuildEmojiDelete,
|
|
45
|
+
Events.GuildEmojiUpdate,
|
|
46
|
+
Events.GuildStickerCreate,
|
|
47
|
+
Events.GuildStickerDelete,
|
|
48
|
+
Events.GuildStickerUpdate,
|
|
49
|
+
Events.GuildSoundboardSoundCreate,
|
|
50
|
+
Events.GuildSoundboardSoundUpdate,
|
|
51
|
+
Events.GuildSoundboardSoundDelete,
|
|
52
|
+
Events.GuildSoundboardSoundsUpdate
|
|
53
|
+
],
|
|
54
|
+
[GatewayIntentBits.GuildIntegrations]: [Events.GuildIntegrationsUpdate],
|
|
55
|
+
[GatewayIntentBits.GuildWebhooks]: [Events.WebhooksUpdate],
|
|
56
|
+
[GatewayIntentBits.GuildInvites]: [Events.InviteCreate, Events.InviteDelete],
|
|
57
|
+
[GatewayIntentBits.GuildVoiceStates]: [Events.VoiceStateUpdate],
|
|
58
|
+
[GatewayIntentBits.GuildPresences]: [Events.PresenceUpdate],
|
|
59
|
+
[GatewayIntentBits.GuildMessages]: [
|
|
60
|
+
Events.MessageCreate,
|
|
61
|
+
Events.MessageUpdate,
|
|
62
|
+
Events.MessageDelete,
|
|
63
|
+
Events.MessageBulkDelete
|
|
64
|
+
],
|
|
65
|
+
[GatewayIntentBits.GuildMessageReactions]: [
|
|
66
|
+
Events.MessageReactionAdd,
|
|
67
|
+
Events.MessageReactionRemove,
|
|
68
|
+
Events.MessageReactionRemoveAll,
|
|
69
|
+
Events.MessageReactionRemoveEmoji
|
|
70
|
+
],
|
|
71
|
+
[GatewayIntentBits.GuildMessageTyping]: [Events.TypingStart],
|
|
72
|
+
[GatewayIntentBits.DirectMessages]: [
|
|
73
|
+
Events.MessageCreate,
|
|
74
|
+
Events.MessageUpdate,
|
|
75
|
+
Events.MessageDelete,
|
|
76
|
+
Events.ChannelPinsUpdate
|
|
77
|
+
],
|
|
78
|
+
[GatewayIntentBits.DirectMessageReactions]: [
|
|
79
|
+
Events.MessageReactionAdd,
|
|
80
|
+
Events.MessageReactionRemove,
|
|
81
|
+
Events.MessageReactionRemoveAll,
|
|
82
|
+
Events.MessageReactionRemoveEmoji
|
|
83
|
+
],
|
|
84
|
+
[GatewayIntentBits.DirectMessageTyping]: [Events.TypingStart],
|
|
85
|
+
[GatewayIntentBits.MessageContent]: [Events.MessageCreate, Events.MessageUpdate],
|
|
86
|
+
[GatewayIntentBits.GuildScheduledEvents]: [
|
|
87
|
+
Events.GuildScheduledEventCreate,
|
|
88
|
+
Events.GuildScheduledEventDelete,
|
|
89
|
+
Events.GuildScheduledEventUpdate,
|
|
90
|
+
Events.GuildScheduledEventUserAdd,
|
|
91
|
+
Events.GuildScheduledEventUserRemove
|
|
92
|
+
],
|
|
93
|
+
[GatewayIntentBits.AutoModerationConfiguration]: [
|
|
94
|
+
Events.AutoModerationRuleCreate,
|
|
95
|
+
Events.AutoModerationRuleDelete,
|
|
96
|
+
Events.AutoModerationRuleUpdate
|
|
97
|
+
],
|
|
98
|
+
[GatewayIntentBits.AutoModerationExecution]: [Events.AutoModerationActionExecution],
|
|
99
|
+
[GatewayIntentBits.GuildMessagePolls]: [Events.MessagePollVoteAdd, Events.MessagePollVoteRemove],
|
|
100
|
+
[GatewayIntentBits.DirectMessagePolls]: [Events.MessagePollVoteAdd, Events.MessagePollVoteRemove]
|
|
101
|
+
}, EVENT_INTENT_MAPPING = {};
|
|
102
|
+
for (let [intentStr, events] of Object.entries(INTENT_GROUPS)) {
|
|
103
|
+
let intent = Number(intentStr);
|
|
104
|
+
for (let event of events)
|
|
105
|
+
EVENT_INTENT_MAPPING[event] ??= [], EVENT_INTENT_MAPPING[event].includes(intent) || EVENT_INTENT_MAPPING[event].push(intent);
|
|
140
106
|
}
|
|
141
|
-
var Command = Object.assign(CommandFactory, CommandAPI);
|
|
142
|
-
|
|
143
|
-
// src/command/argument/Argument.ts
|
|
144
|
-
var ArgumentType = /* @__PURE__ */ ((ArgumentType2) => {
|
|
145
|
-
ArgumentType2["String"] = "string";
|
|
146
|
-
ArgumentType2["Integer"] = "integer";
|
|
147
|
-
ArgumentType2["Number"] = "number";
|
|
148
|
-
ArgumentType2["User"] = "user";
|
|
149
|
-
ArgumentType2["Member"] = "member";
|
|
150
|
-
return ArgumentType2;
|
|
151
|
-
})(ArgumentType || {});
|
|
152
107
|
|
|
153
|
-
// src/
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
args = [];
|
|
160
|
-
if (init) {
|
|
161
|
-
Reflect.defineMetadata(ARGS_KEY, args, method);
|
|
162
|
-
cache.set(method, args);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
return init ? args : Object.freeze([...args]);
|
|
166
|
-
}
|
|
167
|
-
function createArgument(type) {
|
|
168
|
-
return function(options) {
|
|
169
|
-
const objOptions = typeof options === "string" ? { name: options } : options;
|
|
170
|
-
const fullOptions = { ...objOptions, type };
|
|
171
|
-
if (!fullOptions.description) {
|
|
172
|
-
fullOptions.description = fullOptions.name;
|
|
173
|
-
}
|
|
174
|
-
if (!("required" in fullOptions)) {
|
|
175
|
-
fullOptions.required = true;
|
|
176
|
-
}
|
|
177
|
-
return function(target, key, _index) {
|
|
178
|
-
const method = Object.getOwnPropertyDescriptor(target, key)?.value;
|
|
179
|
-
if (!method) {
|
|
180
|
-
throw new Error("No method found");
|
|
181
|
-
}
|
|
182
|
-
const args = getMethodArguments(method, true);
|
|
183
|
-
args.unshift(fullOptions);
|
|
184
|
-
};
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
var string = createArgument("string" /* String */);
|
|
188
|
-
var integer = createArgument("integer" /* Integer */);
|
|
189
|
-
var number = createArgument("number" /* Number */);
|
|
190
|
-
var user = createArgument("user" /* User */);
|
|
191
|
-
var member = createArgument("member" /* Member */);
|
|
192
|
-
function describeArgumentExpectation(arg) {
|
|
193
|
-
const parts = [arg.type];
|
|
194
|
-
switch (arg.type) {
|
|
195
|
-
case "string" /* String */: {
|
|
196
|
-
if (arg.minLength && !arg.maxLength) {
|
|
197
|
-
parts.push(`\u2265 ${String(arg.minLength)}`);
|
|
198
|
-
}
|
|
199
|
-
if (!arg.minLength && arg.maxLength) {
|
|
200
|
-
parts.push(`\u2264 ${String(arg.maxLength)}`);
|
|
201
|
-
}
|
|
202
|
-
if (arg.minLength && arg.maxLength) {
|
|
203
|
-
parts.push(`${String(arg.minLength)} - ${String(arg.maxLength)}`);
|
|
204
|
-
}
|
|
205
|
-
break;
|
|
206
|
-
}
|
|
207
|
-
case "number" /* Number */:
|
|
208
|
-
case "integer" /* Integer */: {
|
|
209
|
-
if (arg.minValue !== void 0 && arg.maxValue === void 0) {
|
|
210
|
-
parts.push(`\u2265 ${String(arg.minValue)}`);
|
|
211
|
-
}
|
|
212
|
-
if (arg.minValue === void 0 && arg.maxValue !== void 0) {
|
|
213
|
-
parts.push(`\u2264 ${String(arg.maxValue)}`);
|
|
214
|
-
}
|
|
215
|
-
if (arg.minValue !== void 0 && arg.maxValue !== void 0) {
|
|
216
|
-
parts.push(`${String(arg.minValue)} - ${String(arg.maxValue)}`);
|
|
217
|
-
}
|
|
108
|
+
// src/utils/string.ts
|
|
109
|
+
function tokenize(content) {
|
|
110
|
+
let args = [], current = "", quoteChar = null, isEscaped = false;
|
|
111
|
+
for (let i = 0; i < content.length; i++) {
|
|
112
|
+
let char = content[i];
|
|
113
|
+
if (char === void 0)
|
|
218
114
|
break;
|
|
115
|
+
if (isEscaped) {
|
|
116
|
+
current += char, isEscaped = false;
|
|
117
|
+
continue;
|
|
219
118
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
119
|
+
if (char === "\\") {
|
|
120
|
+
isEscaped = true;
|
|
121
|
+
continue;
|
|
223
122
|
}
|
|
123
|
+
quoteChar ? char === quoteChar ? quoteChar = null : current += char : char === '"' ? quoteChar = char : /\s/.test(char) ? current.length > 0 && (args.push(current), current = "") : current += char;
|
|
224
124
|
}
|
|
225
|
-
return
|
|
125
|
+
return current.length > 0 && args.push(current), args;
|
|
226
126
|
}
|
|
227
|
-
function
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
127
|
+
function extractSnowflakeId(input) {
|
|
128
|
+
if (!input) return null;
|
|
129
|
+
let mentionMatch = /^<@!?(\d{17,20})>$/.exec(input);
|
|
130
|
+
if (mentionMatch?.[1])
|
|
131
|
+
return mentionMatch[1];
|
|
132
|
+
let idMatch = /^(\d{17,20})$/.exec(input);
|
|
133
|
+
return idMatch?.[1] ? idMatch[1] : null;
|
|
233
134
|
}
|
|
234
|
-
var Arg = {
|
|
235
|
-
getMethodArguments,
|
|
236
|
-
createArgument,
|
|
237
|
-
describeArgumentExpectation,
|
|
238
|
-
format,
|
|
239
|
-
string,
|
|
240
|
-
number,
|
|
241
|
-
integer,
|
|
242
|
-
user,
|
|
243
|
-
member
|
|
244
|
-
};
|
|
245
135
|
|
|
246
|
-
// src/
|
|
247
|
-
var
|
|
248
|
-
|
|
249
|
-
|
|
136
|
+
// src/utils/index.ts
|
|
137
|
+
var $jiti = createJiti(import.meta.url);
|
|
138
|
+
|
|
139
|
+
// src/config.ts
|
|
140
|
+
var ProjectConfigSchema = z.object({
|
|
250
141
|
/**
|
|
251
|
-
*
|
|
252
|
-
*
|
|
142
|
+
* The gateway intents to use for the Discord client.
|
|
143
|
+
*
|
|
144
|
+
* - `auto` — automatically determine the required intents.
|
|
145
|
+
* - bigint — a raw bitfield value representing the combined intents.
|
|
146
|
+
* - array — a list of individual intent flags from `GatewayIntentBits`.
|
|
147
|
+
*
|
|
148
|
+
* @defaultvalue `auto`
|
|
253
149
|
*/
|
|
254
|
-
|
|
255
|
-
const root = Command.getRoot(constructor);
|
|
256
|
-
if (!root) {
|
|
257
|
-
throw new Error(`No root found for "${constructor.name}"`);
|
|
258
|
-
}
|
|
259
|
-
const { options } = root;
|
|
260
|
-
this.constructors.set(options.name, constructor);
|
|
261
|
-
this.instances.set(options.name, new constructor());
|
|
262
|
-
}
|
|
150
|
+
intents: z.union([z.literal("auto"), z.bigint(), z.array(z.enum(GatewayIntentBits))]).default("auto"),
|
|
263
151
|
/**
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
152
|
+
* Optional custom client options for Discord.js (excluding `intents`).
|
|
153
|
+
*
|
|
154
|
+
* These are passed directly to the `Client` constructor when initializing the bot.
|
|
155
|
+
*
|
|
156
|
+
* @see {@link https://discord.js.org/docs/packages/discord.js/main/ClientOptions:Interface}
|
|
268
157
|
*/
|
|
269
|
-
|
|
270
|
-
const files = await glob(pattern);
|
|
271
|
-
const loaders = files.map(async (file) => {
|
|
272
|
-
const fileURL = pathToFileURL(file).toString();
|
|
273
|
-
const { default: constructor } = await import(fileURL);
|
|
274
|
-
_CommandRegistry.add(constructor);
|
|
275
|
-
return constructor;
|
|
276
|
-
});
|
|
277
|
-
if (parallel) {
|
|
278
|
-
return await Promise.all(loaders);
|
|
279
|
-
}
|
|
280
|
-
const result = [];
|
|
281
|
-
for (const loader of loaders) {
|
|
282
|
-
result.push(await loader);
|
|
283
|
-
}
|
|
284
|
-
return result;
|
|
285
|
-
}
|
|
158
|
+
clientOptions: z.custom().optional(),
|
|
286
159
|
/**
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
* @
|
|
160
|
+
* The path to the main project source directory.
|
|
161
|
+
*
|
|
162
|
+
* @defaultvalue `src`
|
|
290
163
|
*/
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
const { options } = child;
|
|
324
|
-
const subcommand = new SlashCommandSubcommandBuilder().setName(options.name).setDescription(options.description);
|
|
325
|
-
this.buildSlashCommandOptions(subcommand, [
|
|
326
|
-
...inheritedArgs,
|
|
327
|
-
...this.getMainHookArguments(child)
|
|
328
|
-
]);
|
|
329
|
-
parent.addSubcommand(subcommand);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
static buildSlashCommandOptions(builder, args) {
|
|
334
|
-
const argGroup = Object.groupBy(args, ({ required }) => required ? "required" : "optional");
|
|
335
|
-
const orderedArgs = [...argGroup.required || [], ...argGroup.optional || []];
|
|
336
|
-
for (const arg of orderedArgs) {
|
|
337
|
-
this.attachSlashCommandOption(builder, arg);
|
|
338
|
-
}
|
|
164
|
+
entryDir: z.string().default("src"),
|
|
165
|
+
prefixes: z.array(z.string()).default([]),
|
|
166
|
+
token: z.string()
|
|
167
|
+
});
|
|
168
|
+
function defineConfig(config) {
|
|
169
|
+
return config;
|
|
170
|
+
}
|
|
171
|
+
var _config;
|
|
172
|
+
async function loadConfig(cwd = process.cwd()) {
|
|
173
|
+
if (_config)
|
|
174
|
+
return console.warn("loadConfig() was called more than once. This shouldn't happen."), _config;
|
|
175
|
+
let globPattern = `bakit.config.{${["ts", "js"].join(",")}}`, [configPath, other] = await glob(globPattern, {
|
|
176
|
+
cwd: cwd.replace(/\\/g, "/"),
|
|
177
|
+
// ensure the path uses `/` instead of `\` on Windows
|
|
178
|
+
absolute: true
|
|
179
|
+
});
|
|
180
|
+
if (!configPath)
|
|
181
|
+
throw new Error("Missing config file");
|
|
182
|
+
other && console.warn(`Multiple config files found in ${cwd}. Using ${configPath}.`);
|
|
183
|
+
let config = await $jiti.import(configPath, { default: true });
|
|
184
|
+
return _config = Object.freeze(await ProjectConfigSchema.parseAsync(config)), _config;
|
|
185
|
+
}
|
|
186
|
+
function getConfig() {
|
|
187
|
+
if (!_config)
|
|
188
|
+
throw new Error("Project config is not loaded.");
|
|
189
|
+
return _config;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// src/base/BaseClientManager.ts
|
|
193
|
+
var BaseClientManager = class {
|
|
194
|
+
constructor(client) {
|
|
195
|
+
this.client = client;
|
|
339
196
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
const option = setupOption(data);
|
|
348
|
-
if (arg.maxLength) {
|
|
349
|
-
option.setMaxLength(arg.maxLength);
|
|
350
|
-
}
|
|
351
|
-
if (arg.minLength) {
|
|
352
|
-
option.setMinLength(arg.minLength);
|
|
353
|
-
}
|
|
354
|
-
return option;
|
|
355
|
-
});
|
|
356
|
-
break;
|
|
357
|
-
}
|
|
358
|
-
case "integer" /* Integer */: {
|
|
359
|
-
builder.addIntegerOption((data) => {
|
|
360
|
-
const option = setupOption(data);
|
|
361
|
-
if (arg.maxValue) {
|
|
362
|
-
option.setMaxValue(arg.maxValue);
|
|
363
|
-
}
|
|
364
|
-
if (arg.minValue) {
|
|
365
|
-
option.setMinValue(arg.minValue);
|
|
366
|
-
}
|
|
367
|
-
return option;
|
|
368
|
-
});
|
|
369
|
-
break;
|
|
370
|
-
}
|
|
371
|
-
case "number" /* Number */: {
|
|
372
|
-
builder.addNumberOption((data) => {
|
|
373
|
-
const option = setupOption(data);
|
|
374
|
-
if (arg.maxValue) {
|
|
375
|
-
option.setMaxValue(arg.maxValue);
|
|
376
|
-
}
|
|
377
|
-
if (arg.minValue) {
|
|
378
|
-
option.setMinValue(arg.minValue);
|
|
379
|
-
}
|
|
380
|
-
return option;
|
|
381
|
-
});
|
|
382
|
-
break;
|
|
383
|
-
}
|
|
384
|
-
case "user" /* User */:
|
|
385
|
-
case "member" /* Member */: {
|
|
386
|
-
builder.addUserOption((option) => setupOption(option));
|
|
387
|
-
break;
|
|
388
|
-
}
|
|
389
|
-
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// src/base/lifecycle/Context.ts
|
|
200
|
+
var Context = class {
|
|
201
|
+
canceled = false;
|
|
202
|
+
cancel() {
|
|
203
|
+
this.canceled = true;
|
|
390
204
|
}
|
|
391
205
|
};
|
|
392
206
|
|
|
393
|
-
// src/command/
|
|
394
|
-
|
|
395
|
-
ChatInputCommandInteraction,
|
|
396
|
-
Message
|
|
397
|
-
} from "discord.js";
|
|
398
|
-
var BaseContext = class {
|
|
207
|
+
// src/base/command/CommandContext.ts
|
|
208
|
+
var BaseCommandContext = class extends Context {
|
|
399
209
|
constructor(source) {
|
|
210
|
+
super();
|
|
400
211
|
this.source = source;
|
|
401
212
|
}
|
|
402
213
|
get client() {
|
|
@@ -414,26 +225,25 @@ var BaseContext = class {
|
|
|
414
225
|
get guildId() {
|
|
415
226
|
return this.source.guildId;
|
|
416
227
|
}
|
|
228
|
+
get member() {
|
|
229
|
+
return this.source.member;
|
|
230
|
+
}
|
|
417
231
|
inGuild() {
|
|
418
|
-
return
|
|
232
|
+
return !!this.guildId;
|
|
419
233
|
}
|
|
420
234
|
inCachedGuild() {
|
|
421
|
-
if (this.isChatInput())
|
|
235
|
+
if (this.isChatInput())
|
|
422
236
|
return this.source.inCachedGuild();
|
|
423
|
-
|
|
237
|
+
if (this.isMessage())
|
|
424
238
|
return this.source.inGuild();
|
|
425
|
-
|
|
426
|
-
throw new Error("Invalid source");
|
|
427
|
-
}
|
|
239
|
+
throw new Error("Invalid source");
|
|
428
240
|
}
|
|
429
|
-
get
|
|
430
|
-
if (this.isChatInput())
|
|
241
|
+
get user() {
|
|
242
|
+
if (this.isChatInput())
|
|
431
243
|
return this.source.user;
|
|
432
|
-
|
|
244
|
+
if (this.isMessage())
|
|
433
245
|
return this.source.author;
|
|
434
|
-
|
|
435
|
-
throw new Error("Invalid source");
|
|
436
|
-
}
|
|
246
|
+
throw new Error("Invalid source");
|
|
437
247
|
}
|
|
438
248
|
isChatInput() {
|
|
439
249
|
return this.source instanceof ChatInputCommandInteraction;
|
|
@@ -441,769 +251,614 @@ var BaseContext = class {
|
|
|
441
251
|
isMessage() {
|
|
442
252
|
return this.source instanceof Message;
|
|
443
253
|
}
|
|
444
|
-
}
|
|
445
|
-
var ChatInputContext = class extends BaseContext {
|
|
254
|
+
}, ChatInputContext = class extends BaseCommandContext {
|
|
446
255
|
async send(options) {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
}
|
|
450
|
-
const sendOptions = {
|
|
256
|
+
typeof options == "string" && (options = { content: options });
|
|
257
|
+
let sendOptions = {
|
|
451
258
|
...options,
|
|
452
259
|
withResponse: true
|
|
453
260
|
};
|
|
454
|
-
|
|
455
|
-
return await this.source.followUp(sendOptions);
|
|
456
|
-
}
|
|
457
|
-
const response = await this.source.reply(sendOptions);
|
|
458
|
-
return response.resource?.message;
|
|
261
|
+
return this.source.deferred || this.source.replied ? await this.source.followUp(sendOptions) : (await this.source.reply(sendOptions)).resource?.message;
|
|
459
262
|
}
|
|
460
|
-
}
|
|
461
|
-
var MessageContext = class extends BaseContext {
|
|
263
|
+
}, MessageContext = class extends BaseCommandContext {
|
|
462
264
|
async send(options) {
|
|
463
|
-
|
|
464
|
-
if (!channel?.isSendable())
|
|
265
|
+
let { channel } = this;
|
|
266
|
+
if (!channel?.isSendable())
|
|
465
267
|
throw new Error("Invalid channel or channel is not sendable");
|
|
466
|
-
}
|
|
467
268
|
return await channel.send(options);
|
|
468
269
|
}
|
|
469
270
|
};
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
const idMatch = value.match(/^<@!?(\d+)>$/);
|
|
474
|
-
if (idMatch) {
|
|
475
|
-
return idMatch[1];
|
|
271
|
+
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 {
|
|
272
|
+
constructor(id) {
|
|
273
|
+
this.id = id;
|
|
476
274
|
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
275
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
276
|
+
hooks = {
|
|
277
|
+
MAIN: new Collection(),
|
|
278
|
+
PRE: new Collection(),
|
|
279
|
+
POST: new Collection(),
|
|
280
|
+
ERROR: new Collection()
|
|
281
|
+
};
|
|
282
|
+
getName(name) {
|
|
283
|
+
return `${this.id}:${name}`;
|
|
284
|
+
}
|
|
285
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
286
|
+
setHook(name, state, callback, order = 1 /* Last */) {
|
|
287
|
+
let currentHooks = this.hooks[state], key = this.getName(name);
|
|
288
|
+
if (currentHooks.has(key) && console.warn(`Overriding duplicate hook '${key}' for state '${state}'`), order === 1 /* Last */)
|
|
289
|
+
currentHooks.set(key, callback);
|
|
290
|
+
else {
|
|
291
|
+
let existingEntries = [...currentHooks.entries()].filter(([k]) => k !== key);
|
|
292
|
+
currentHooks.clear(), currentHooks.set(key, callback);
|
|
293
|
+
for (let [k, v] of existingEntries)
|
|
294
|
+
currentHooks.set(k, v);
|
|
295
|
+
}
|
|
296
|
+
return this;
|
|
297
|
+
}
|
|
298
|
+
main(callback) {
|
|
299
|
+
return this.setHook("main", "MAIN" /* Main */, callback);
|
|
300
|
+
}
|
|
301
|
+
pre(callback) {
|
|
302
|
+
return this.setHook("pre", "PRE" /* Pre */, callback);
|
|
303
|
+
}
|
|
304
|
+
post(callback) {
|
|
305
|
+
return this.setHook("post", "POST" /* Post */, callback);
|
|
306
|
+
}
|
|
307
|
+
error(callback) {
|
|
308
|
+
return this.setHook("error", "ERROR" /* Error */, callback);
|
|
309
|
+
}
|
|
310
|
+
async execute(context, ...args) {
|
|
311
|
+
let pipeline = [
|
|
312
|
+
...this.hooks.PRE.values(),
|
|
313
|
+
...this.hooks.MAIN.values(),
|
|
314
|
+
...this.hooks.POST.values()
|
|
315
|
+
], error;
|
|
316
|
+
for (let hook of pipeline) {
|
|
317
|
+
if (context.canceled)
|
|
511
318
|
break;
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
`> Expected: ${expected}`,
|
|
517
|
-
`> Received: ${String(received)}`
|
|
518
|
-
].join("\n");
|
|
319
|
+
try {
|
|
320
|
+
await hook(context, ...args);
|
|
321
|
+
} catch (e) {
|
|
322
|
+
error = e;
|
|
519
323
|
break;
|
|
520
324
|
}
|
|
521
|
-
|
|
522
|
-
|
|
325
|
+
}
|
|
326
|
+
if (!error)
|
|
327
|
+
return;
|
|
328
|
+
if (!this.hooks.ERROR.size)
|
|
329
|
+
throw error;
|
|
330
|
+
for (let [key, callback] of this.hooks.ERROR.entries()) {
|
|
331
|
+
if (context.canceled)
|
|
523
332
|
break;
|
|
333
|
+
try {
|
|
334
|
+
await callback(context, error, ...args);
|
|
335
|
+
} catch (innerError) {
|
|
336
|
+
console.error(`[Lifecycle] Error handler for '${key}' failed:`, innerError);
|
|
524
337
|
}
|
|
525
338
|
}
|
|
526
|
-
super(message);
|
|
527
|
-
this.arg = arg;
|
|
528
|
-
this.type = type;
|
|
529
|
-
this.expected = expected;
|
|
530
|
-
this.received = received;
|
|
531
|
-
Error.captureStackTrace(this, this.constructor);
|
|
532
339
|
}
|
|
533
|
-
|
|
534
|
-
|
|
340
|
+
};
|
|
341
|
+
var ParamUserType = /* @__PURE__ */ ((ParamUserType2) => (ParamUserType2.Bot = "bot", ParamUserType2.Normal = "normal", ParamUserType2.Any = "any", ParamUserType2))(ParamUserType || {}), BaseParamSchema = z.object({
|
|
342
|
+
name: z.string(),
|
|
343
|
+
description: z.string().optional(),
|
|
344
|
+
required: z.boolean().default(true)
|
|
345
|
+
}), StringParamSchema = BaseParamSchema.extend({
|
|
346
|
+
maxLength: z.number().min(1).optional(),
|
|
347
|
+
minLength: z.number().min(1).optional()
|
|
348
|
+
}), NumberParamSchema = BaseParamSchema.extend({
|
|
349
|
+
maxValue: z.number().optional(),
|
|
350
|
+
minValue: z.number().optional()
|
|
351
|
+
}), UserParamSchema = BaseParamSchema.extend({});
|
|
352
|
+
|
|
353
|
+
// src/errors/BakitError.ts
|
|
354
|
+
var BakitError = class extends Error {
|
|
355
|
+
constructor(message) {
|
|
356
|
+
super(message), this.name = this.constructor.name, Object.setPrototypeOf(this, new.target.prototype);
|
|
535
357
|
}
|
|
536
358
|
};
|
|
537
359
|
|
|
538
|
-
// src/
|
|
539
|
-
var
|
|
540
|
-
constructor(
|
|
541
|
-
|
|
360
|
+
// src/errors/ArgumentError.ts
|
|
361
|
+
var ArgumentError = class extends BakitError {
|
|
362
|
+
constructor(target, reason) {
|
|
363
|
+
super(`Invalid argument for '${target}': ${reason}`);
|
|
364
|
+
this.target = target;
|
|
365
|
+
this.reason = reason;
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
// src/base/command/param/Param.ts
|
|
370
|
+
var BaseParam = class {
|
|
371
|
+
constructor(options, schema) {
|
|
372
|
+
this.schema = schema;
|
|
373
|
+
let parsed = schema.parse({
|
|
374
|
+
...options,
|
|
375
|
+
description: options.description ?? options.name
|
|
376
|
+
});
|
|
377
|
+
this.options = parsed;
|
|
378
|
+
}
|
|
379
|
+
options;
|
|
380
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
381
|
+
setOption(key, value) {
|
|
382
|
+
if (value === null)
|
|
383
|
+
return delete this.options[key], this;
|
|
384
|
+
let fieldValidator = this.schema.shape[key];
|
|
385
|
+
if (!fieldValidator)
|
|
386
|
+
return this.options[key] = value, this;
|
|
387
|
+
let parsedValue = fieldValidator.parse(value);
|
|
388
|
+
return this.options[key] = parsedValue, this;
|
|
389
|
+
}
|
|
390
|
+
name(value) {
|
|
391
|
+
return this.setOption("name", value);
|
|
392
|
+
}
|
|
393
|
+
description(value) {
|
|
394
|
+
return this.setOption("description", value);
|
|
395
|
+
}
|
|
396
|
+
required(value) {
|
|
397
|
+
return this.setOption("required", value);
|
|
398
|
+
}
|
|
399
|
+
async resolve(context, value) {
|
|
400
|
+
let { required, name } = this.options;
|
|
401
|
+
if (value === void 0) {
|
|
402
|
+
if (required)
|
|
403
|
+
throw new ArgumentError(name, "is required");
|
|
404
|
+
return null;
|
|
405
|
+
}
|
|
406
|
+
if (context.isChatInput())
|
|
407
|
+
return await this.resolveChatInput(context);
|
|
408
|
+
if (context.isMessage())
|
|
409
|
+
return await this.resolveMessage(context, value);
|
|
410
|
+
throw new Error("Invalid context type provided");
|
|
542
411
|
}
|
|
543
|
-
parsedValues = [];
|
|
544
412
|
/**
|
|
545
|
-
*
|
|
413
|
+
* Helper to normalize string inputs into an options object.
|
|
546
414
|
*/
|
|
547
|
-
|
|
548
|
-
return
|
|
415
|
+
static getOptions(options) {
|
|
416
|
+
return typeof options == "string" ? { name: options } : options;
|
|
417
|
+
}
|
|
418
|
+
}, StringParam = class extends BaseParam {
|
|
419
|
+
constructor(options) {
|
|
420
|
+
super(BaseParam.getOptions(options), StringParamSchema);
|
|
421
|
+
}
|
|
422
|
+
required(value) {
|
|
423
|
+
return super.required(value);
|
|
424
|
+
}
|
|
425
|
+
resolveMessage(_context, value) {
|
|
426
|
+
let { minLength, maxLength, name } = this.options;
|
|
427
|
+
if (minLength && value.length < minLength)
|
|
428
|
+
throw new ArgumentError(name, `must be at least ${minLength} chars long`);
|
|
429
|
+
if (maxLength && value.length > maxLength)
|
|
430
|
+
throw new ArgumentError(name, `must be at most ${maxLength} chars long`);
|
|
431
|
+
return value;
|
|
432
|
+
}
|
|
433
|
+
resolveChatInput(context) {
|
|
434
|
+
let { name, required } = this.options;
|
|
435
|
+
return context.source.options.getString(name, required);
|
|
549
436
|
}
|
|
550
437
|
/**
|
|
551
|
-
*
|
|
438
|
+
* Sets the minimum allowed length for this string.
|
|
439
|
+
* Pass `null` to remove this constraint.
|
|
552
440
|
*/
|
|
553
|
-
|
|
554
|
-
return this.
|
|
441
|
+
min(length) {
|
|
442
|
+
return this.setOption("minLength", length);
|
|
555
443
|
}
|
|
556
444
|
/**
|
|
557
|
-
*
|
|
445
|
+
* Sets the maximum allowed length for this string.
|
|
446
|
+
* Pass `null` to remove this constraint.
|
|
558
447
|
*/
|
|
559
|
-
|
|
560
|
-
return
|
|
448
|
+
max(length) {
|
|
449
|
+
return this.setOption("maxLength", length);
|
|
561
450
|
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
static create(message) {
|
|
566
|
-
const client = message.client;
|
|
567
|
-
const { enableMentionPrefix } = client.options;
|
|
568
|
-
const prefixes = [
|
|
569
|
-
// Custom prefixes specified in options
|
|
570
|
-
...client.options.prefixes ?? [],
|
|
571
|
-
// Use bot mention as prefix if enabled
|
|
572
|
-
...enableMentionPrefix ? [client.user.toString()] : []
|
|
573
|
-
];
|
|
574
|
-
const prefix = prefixes.find((p) => message.content.startsWith(p)) ?? null;
|
|
575
|
-
if (!prefix) {
|
|
576
|
-
return;
|
|
577
|
-
}
|
|
578
|
-
const values = message.content.slice(prefix.length).trim().split(/\s+/);
|
|
579
|
-
return new _ArgumentResolver({
|
|
580
|
-
message,
|
|
581
|
-
startAt: 1,
|
|
582
|
-
// Skip the command trigger
|
|
583
|
-
values,
|
|
584
|
-
args: [],
|
|
585
|
-
prefix
|
|
586
|
-
});
|
|
451
|
+
}, NumberParam = class extends BaseParam {
|
|
452
|
+
constructor(options) {
|
|
453
|
+
super(BaseParam.getOptions(options), NumberParamSchema);
|
|
587
454
|
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
prefix: this.options.prefix,
|
|
591
|
-
message: this.options.message,
|
|
592
|
-
values: this.options.values,
|
|
593
|
-
args,
|
|
594
|
-
startAt: this.options.startAt
|
|
595
|
-
});
|
|
596
|
-
child.parsedValues = [...this.parsedValues];
|
|
597
|
-
if (!child.options.args.length) {
|
|
598
|
-
return child;
|
|
599
|
-
}
|
|
600
|
-
if (this.specifiedAmount >= child.options.args.length) {
|
|
601
|
-
await child.absoluteParse();
|
|
602
|
-
} else {
|
|
603
|
-
await child.dynamicParse();
|
|
604
|
-
}
|
|
605
|
-
return child;
|
|
606
|
-
}
|
|
607
|
-
async absoluteParse() {
|
|
608
|
-
const { args, values, startAt } = this.options;
|
|
609
|
-
let valueIndex = startAt;
|
|
610
|
-
let argIndex = 0;
|
|
611
|
-
while (valueIndex < values.length && argIndex < args.length) {
|
|
612
|
-
const value = values[valueIndex];
|
|
613
|
-
const arg = args[argIndex];
|
|
614
|
-
if (arg.tuple) {
|
|
615
|
-
this.parsedValues.push(...await this.resolveTuple(arg, valueIndex, argIndex));
|
|
616
|
-
break;
|
|
617
|
-
}
|
|
618
|
-
const matchedValue = await this.matchValue(arg, value);
|
|
619
|
-
if (matchedValue === null) {
|
|
620
|
-
throw new CommandSyntaxError({
|
|
621
|
-
arg,
|
|
622
|
-
type: "INVALID_ARGUMENT" /* InvalidArgument */,
|
|
623
|
-
received: value
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
this.parsedValues.push(matchedValue);
|
|
627
|
-
valueIndex++;
|
|
628
|
-
argIndex++;
|
|
629
|
-
}
|
|
455
|
+
required(value) {
|
|
456
|
+
return super.required(value);
|
|
630
457
|
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
break;
|
|
641
|
-
}
|
|
642
|
-
const matchedValue = await this.matchValue(arg, value);
|
|
643
|
-
if (matchedValue !== null) {
|
|
644
|
-
this.parsedValues.push(matchedValue);
|
|
645
|
-
valueIndex++;
|
|
646
|
-
} else if (arg.required) {
|
|
647
|
-
throw new CommandSyntaxError({
|
|
648
|
-
arg,
|
|
649
|
-
type: "MISSING_REQUIRE_ARGUMENT" /* MissingRequireArgument */,
|
|
650
|
-
received: value
|
|
651
|
-
});
|
|
652
|
-
}
|
|
653
|
-
argIndex++;
|
|
654
|
-
}
|
|
655
|
-
while (argIndex < args.length) {
|
|
656
|
-
const arg = args[argIndex];
|
|
657
|
-
if (arg.required) {
|
|
658
|
-
throw new CommandSyntaxError({
|
|
659
|
-
arg,
|
|
660
|
-
type: "MISSING_REQUIRE_ARGUMENT" /* MissingRequireArgument */,
|
|
661
|
-
received: "nothing"
|
|
662
|
-
});
|
|
663
|
-
}
|
|
664
|
-
argIndex++;
|
|
665
|
-
}
|
|
458
|
+
resolveMessage(_context, value) {
|
|
459
|
+
let { minValue, maxValue, name } = this.options, num = Number(value);
|
|
460
|
+
if (isNaN(num))
|
|
461
|
+
throw new ArgumentError(name, "must be a number");
|
|
462
|
+
if (minValue !== void 0 && num < minValue)
|
|
463
|
+
throw new ArgumentError(name, `must be greater than ${minValue}`);
|
|
464
|
+
if (maxValue !== void 0 && num > maxValue)
|
|
465
|
+
throw new ArgumentError(name, `must be less than ${minValue}`);
|
|
466
|
+
return num;
|
|
666
467
|
}
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
throw new SyntaxError("Tuple argument must be the last argument");
|
|
671
|
-
}
|
|
672
|
-
const values = [];
|
|
673
|
-
for (const rest of this.values.slice(startIndex)) {
|
|
674
|
-
const matchedValue = await this.matchValue(arg, rest);
|
|
675
|
-
if (matchedValue === null) {
|
|
676
|
-
throw new CommandSyntaxError({
|
|
677
|
-
arg,
|
|
678
|
-
type: "INVALID_VARIADIC_ARGUMENT_VALUE" /* InvalidVariadicArgumentValue */,
|
|
679
|
-
received: rest
|
|
680
|
-
});
|
|
681
|
-
}
|
|
682
|
-
values.push(matchedValue);
|
|
683
|
-
}
|
|
684
|
-
if (values.length === 0 && arg.required) {
|
|
685
|
-
throw new CommandSyntaxError({
|
|
686
|
-
arg,
|
|
687
|
-
type: "MISSING_REQUIRE_ARGUMENT" /* MissingRequireArgument */,
|
|
688
|
-
received: "nothing"
|
|
689
|
-
});
|
|
690
|
-
}
|
|
691
|
-
return values;
|
|
692
|
-
}
|
|
693
|
-
async matchValue(arg, value) {
|
|
694
|
-
switch (arg.type) {
|
|
695
|
-
case "user" /* User */:
|
|
696
|
-
return await this.matchUserValue(arg, value);
|
|
697
|
-
case "integer" /* Integer */:
|
|
698
|
-
return this.matchIntegerValue(arg, value);
|
|
699
|
-
case "number" /* Number */:
|
|
700
|
-
return this.matchNumberValue(arg, value);
|
|
701
|
-
case "string" /* String */:
|
|
702
|
-
return this.matchStringValue(arg, value);
|
|
703
|
-
default:
|
|
704
|
-
return null;
|
|
705
|
-
}
|
|
468
|
+
resolveChatInput(context) {
|
|
469
|
+
let { name, required } = this.options;
|
|
470
|
+
return context.source.options.getString(name, required);
|
|
706
471
|
}
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
if (!user2) {
|
|
714
|
-
return null;
|
|
715
|
-
}
|
|
716
|
-
return user2;
|
|
472
|
+
/**
|
|
473
|
+
* Sets the minimum allowed value for this number.
|
|
474
|
+
* Pass `null` to remove this constraint.
|
|
475
|
+
*/
|
|
476
|
+
min(value) {
|
|
477
|
+
return this.setOption("minValue", value);
|
|
717
478
|
}
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
return null;
|
|
725
|
-
}
|
|
726
|
-
if (arg.maxValue !== void 0 && intVal > arg.maxValue) {
|
|
727
|
-
return null;
|
|
728
|
-
}
|
|
729
|
-
return intVal;
|
|
479
|
+
/**
|
|
480
|
+
* Sets the maximum allowed value for this number.
|
|
481
|
+
* Pass `null` to remove this constraint.
|
|
482
|
+
*/
|
|
483
|
+
max(value) {
|
|
484
|
+
return this.setOption("maxValue", value);
|
|
730
485
|
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
return null;
|
|
735
|
-
}
|
|
736
|
-
if (arg.minValue !== void 0 && numVal < arg.minValue) {
|
|
737
|
-
return null;
|
|
738
|
-
}
|
|
739
|
-
if (arg.maxValue !== void 0 && numVal > arg.maxValue) {
|
|
740
|
-
return null;
|
|
741
|
-
}
|
|
742
|
-
return numVal;
|
|
486
|
+
}, UserParam = class extends BaseParam {
|
|
487
|
+
constructor(options) {
|
|
488
|
+
super(BaseParam.getOptions(options), UserParamSchema);
|
|
743
489
|
}
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
490
|
+
required(value) {
|
|
491
|
+
return super.required(value);
|
|
492
|
+
}
|
|
493
|
+
async resolveMessage(context, value) {
|
|
494
|
+
let id = extractSnowflakeId(value);
|
|
495
|
+
if (!id)
|
|
749
496
|
return null;
|
|
750
|
-
}
|
|
751
|
-
return
|
|
497
|
+
let { users } = context.client;
|
|
498
|
+
return await users.fetch(id).catch(() => null);
|
|
752
499
|
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
return interaction.options.getString(arg.name, arg.required);
|
|
757
|
-
case "integer" /* Integer */:
|
|
758
|
-
return interaction.options.getInteger(arg.name, arg.required);
|
|
759
|
-
case "number" /* Number */:
|
|
760
|
-
return interaction.options.getNumber(arg.name, arg.required);
|
|
761
|
-
case "user" /* User */:
|
|
762
|
-
return interaction.options.getUser(arg.name, arg.required);
|
|
763
|
-
case "member" /* Member */:
|
|
764
|
-
return interaction.options.getMember(arg.name);
|
|
765
|
-
default:
|
|
766
|
-
return null;
|
|
767
|
-
}
|
|
500
|
+
resolveChatInput(context) {
|
|
501
|
+
let { name, required } = this.options;
|
|
502
|
+
return context.source.options.getUser(name, required);
|
|
768
503
|
}
|
|
769
504
|
};
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
505
|
+
function validateParamsOrder(params) {
|
|
506
|
+
let seenOptional = false;
|
|
507
|
+
for (let param of params)
|
|
508
|
+
if (param.options.required) {
|
|
509
|
+
if (seenOptional)
|
|
510
|
+
return false;
|
|
511
|
+
} else
|
|
512
|
+
seenOptional = true;
|
|
513
|
+
return true;
|
|
514
|
+
}
|
|
515
|
+
var CommandOptionsSchema = z.object({
|
|
516
|
+
name: z.string().readonly(),
|
|
517
|
+
description: z.string().min(1).max(100).optional().readonly(),
|
|
518
|
+
nsfw: z.boolean().default(false).readonly(),
|
|
519
|
+
params: z.array(z.instanceof(BaseParam)).default([]).readonly(),
|
|
520
|
+
quotes: z.boolean().default(true).readonly()
|
|
521
|
+
}).transform((data) => ({
|
|
522
|
+
...data,
|
|
523
|
+
description: data.description ?? `Command ${data.name}`
|
|
524
|
+
})).refine(({ params }) => validateParamsOrder(params), {
|
|
525
|
+
path: ["params"],
|
|
526
|
+
error: "Required params must be placed before optional params"
|
|
527
|
+
}), Command = class extends LifecycleManager {
|
|
528
|
+
constructor(options) {
|
|
529
|
+
let _options = CommandOptionsSchema.parse(typeof options == "string" ? { name: options } : options);
|
|
530
|
+
super(`command:${_options.name}`), this.options = _options, this.setHook("syntaxError", "ERROR" /* Error */, async (ctx, error, ...args) => {
|
|
531
|
+
await this.handleSyntaxError(ctx, error, args);
|
|
532
|
+
});
|
|
782
533
|
}
|
|
783
|
-
|
|
784
|
-
|
|
534
|
+
async handleSyntaxError(context, error, _args) {
|
|
535
|
+
error instanceof BakitError && await context.send(error.message);
|
|
785
536
|
}
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
throw new Error("No active context, cannot wrap function outside a StateBox.run()");
|
|
790
|
-
}
|
|
791
|
-
return () => this.run(fn, currentStore);
|
|
792
|
-
}
|
|
793
|
-
static use(defaultValue) {
|
|
794
|
-
return (target, key) => {
|
|
795
|
-
Object.defineProperty(target, key, {
|
|
796
|
-
get() {
|
|
797
|
-
const states = _StateBox.getState();
|
|
798
|
-
if (!(key in states)) {
|
|
799
|
-
states[key] = defaultValue;
|
|
800
|
-
}
|
|
801
|
-
return states[key];
|
|
802
|
-
},
|
|
803
|
-
set(value) {
|
|
804
|
-
const states = _StateBox.getState();
|
|
805
|
-
states[key] = value;
|
|
806
|
-
},
|
|
807
|
-
enumerable: true,
|
|
808
|
-
configurable: true
|
|
809
|
-
});
|
|
810
|
-
};
|
|
537
|
+
toSlashCommandJSON() {
|
|
538
|
+
let { name, description, nsfw, params } = this.options, builder = new SlashCommandBuilder().setName(name).setDescription(description).setNSFW(nsfw);
|
|
539
|
+
return this.initSlashCommandOptions(builder, params), builder.toJSON();
|
|
811
540
|
}
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
var ListenerEntry = class extends BaseEntry {
|
|
816
|
-
constructor(options) {
|
|
817
|
-
super();
|
|
818
|
-
this.options = options;
|
|
541
|
+
initSlashCommandOptions(builder, params) {
|
|
542
|
+
for (let param of params)
|
|
543
|
+
this.initSlashCommandOption(builder, param);
|
|
819
544
|
}
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
((ListenerAPI2) => {
|
|
825
|
-
ListenerAPI2.ENTRY_KEY = Symbol("entry");
|
|
826
|
-
function use(entry) {
|
|
827
|
-
return (target) => {
|
|
828
|
-
Reflect.defineMetadata(ListenerAPI2.ENTRY_KEY, entry, target);
|
|
545
|
+
initSlashCommandOption(builder, param) {
|
|
546
|
+
let initOption = (builder2) => {
|
|
547
|
+
let { name, description, required } = param.options;
|
|
548
|
+
return builder2.setName(name).setDescription(description).setRequired(required);
|
|
829
549
|
};
|
|
550
|
+
if (param instanceof StringParam) {
|
|
551
|
+
let { maxLength, minLength } = param.options, option = initOption(new SlashCommandStringOption());
|
|
552
|
+
maxLength && option.setMaxLength(maxLength), minLength && option.setMinLength(minLength), builder.addStringOption(option);
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
if (param instanceof NumberParam) {
|
|
556
|
+
let { maxValue, minValue } = param.options, option = initOption(new SlashCommandNumberOption());
|
|
557
|
+
maxValue && option.setMaxValue(maxValue), minValue && option.setMinValue(minValue), builder.addNumberOption(option);
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
if (param instanceof UserParam) {
|
|
561
|
+
let option = initOption(new SlashCommandUserOption());
|
|
562
|
+
builder.addUserOption(option);
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
830
565
|
}
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
}
|
|
835
|
-
ListenerAPI2.getEntry = getEntry;
|
|
836
|
-
})(ListenerAPI || (ListenerAPI = {}));
|
|
837
|
-
function ListenerFactory(options) {
|
|
838
|
-
const fullOptions = typeof options !== "object" ? { name: options, once: false } : { once: false, ...options };
|
|
839
|
-
return new ListenerEntry(fullOptions);
|
|
566
|
+
};
|
|
567
|
+
function defineCommand(options) {
|
|
568
|
+
return new Command(options);
|
|
840
569
|
}
|
|
841
|
-
var Listener = Object.assign(ListenerFactory, ListenerAPI);
|
|
842
570
|
|
|
843
|
-
// src/
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
throw new Error("Client is not ready.");
|
|
571
|
+
// src/base/command/CommandManager.ts
|
|
572
|
+
var CommandManager = class extends BaseClientManager {
|
|
573
|
+
commands = new Collection();
|
|
574
|
+
async loadModules() {
|
|
575
|
+
let entryDir = posix.resolve(getConfig().entryDir), pattern = posix.join(entryDir, "commands", "**/*.{ts,js}"), loads = (await glob(pattern, {
|
|
576
|
+
cwd: process.cwd(),
|
|
577
|
+
absolute: true
|
|
578
|
+
})).map(async (file) => {
|
|
579
|
+
try {
|
|
580
|
+
let command = await $jiti.import(file, { default: !0 });
|
|
581
|
+
if (!command) {
|
|
582
|
+
console.warn(`[Loader] File has no default export: ${file}`);
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
if (!(command instanceof Command)) {
|
|
586
|
+
console.warn(`[Loader] Default export is not a Command: ${file}`);
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
return this.add(command), command;
|
|
590
|
+
} catch (error) {
|
|
591
|
+
console.error(`An error occurred while trying to add command for '${file}':`, error);
|
|
865
592
|
}
|
|
866
|
-
|
|
867
|
-
}
|
|
868
|
-
const instance = new constructor();
|
|
869
|
-
const executor = this.createExecutor(constructor, instance);
|
|
870
|
-
this.constructors.add(constructor);
|
|
871
|
-
this.instances.set(constructor, instance);
|
|
872
|
-
this.executors.set(instance, executor);
|
|
873
|
-
options.emitter[options.once ? "once" : "on"](options.name, (...args) => {
|
|
874
|
-
void executor(...args);
|
|
875
|
-
});
|
|
593
|
+
}), loaded = (await Promise.all(loads)).filter((x) => x !== void 0);
|
|
594
|
+
return console.log(`Loaded ${loaded.length} command(s).`), loaded;
|
|
876
595
|
}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
if (!entry) {
|
|
885
|
-
return false;
|
|
886
|
-
}
|
|
887
|
-
this.constructors.delete(constructor);
|
|
888
|
-
const instance = this.instances.get(constructor);
|
|
889
|
-
if (!instance) {
|
|
890
|
-
return false;
|
|
891
|
-
}
|
|
892
|
-
this.instances.delete(constructor);
|
|
893
|
-
const executor = this.executors.get(instance);
|
|
894
|
-
if (!executor) {
|
|
895
|
-
return false;
|
|
596
|
+
add(command) {
|
|
597
|
+
if (!(command instanceof Command))
|
|
598
|
+
throw new Error("Invalid command provided");
|
|
599
|
+
let { name } = command.options;
|
|
600
|
+
if (this.commands.has(name)) {
|
|
601
|
+
console.warn(`[Loader] Duplicate command registered: '${name}'`);
|
|
602
|
+
return;
|
|
896
603
|
}
|
|
897
|
-
|
|
898
|
-
emitter?.removeListener(name, executor);
|
|
899
|
-
this.executors.delete(instance);
|
|
900
|
-
return true;
|
|
604
|
+
this.commands.set(name, command);
|
|
901
605
|
}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
static removeAll() {
|
|
907
|
-
let removedAmount = 0;
|
|
908
|
-
for (const constructor of this.constructors) {
|
|
909
|
-
if (this.remove(constructor)) {
|
|
910
|
-
removedAmount++;
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
return removedAmount;
|
|
606
|
+
remove(target) {
|
|
607
|
+
let name = typeof target == "string" ? target : target.options.name, existing = this.commands.get(name);
|
|
608
|
+
if (existing)
|
|
609
|
+
return this.commands.delete(name), existing;
|
|
914
610
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
* @param newClient base client to set for the registry.
|
|
918
|
-
*/
|
|
919
|
-
static setClient(newClient) {
|
|
920
|
-
this.client = newClient;
|
|
611
|
+
get(name) {
|
|
612
|
+
return this.commands.get(name);
|
|
921
613
|
}
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
614
|
+
};
|
|
615
|
+
var ListenerOptionsSchema = z4.object({
|
|
616
|
+
name: z4.enum(Events),
|
|
617
|
+
once: z4.boolean().default(false)
|
|
618
|
+
}), Listener = class extends LifecycleManager {
|
|
619
|
+
options;
|
|
620
|
+
constructor(options) {
|
|
621
|
+
let _options = ListenerOptionsSchema.parse(typeof options == "string" ? { name: options } : options);
|
|
622
|
+
super(`listener:${_options.name}`), this.options = _options;
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
function defineListener(options) {
|
|
626
|
+
return new Listener(options);
|
|
627
|
+
}
|
|
628
|
+
var ListenerManager = class extends BaseClientManager {
|
|
629
|
+
listeners = [];
|
|
630
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
631
|
+
executors = /* @__PURE__ */ new WeakMap();
|
|
632
|
+
async loadModules() {
|
|
633
|
+
let entryDir = posix.resolve(getConfig().entryDir), pattern = posix.join(entryDir, "listeners", "**/*.{ts,js}"), loads = (await glob(pattern, {
|
|
634
|
+
cwd: process.cwd(),
|
|
635
|
+
absolute: true
|
|
636
|
+
})).map(async (file) => {
|
|
936
637
|
try {
|
|
937
|
-
|
|
938
|
-
|
|
638
|
+
let listener = await $jiti.import(file, { default: !0 });
|
|
639
|
+
if (!listener) {
|
|
640
|
+
console.warn(`[Loader] File has no default export: ${file}`);
|
|
641
|
+
return;
|
|
939
642
|
}
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
643
|
+
if (!(listener instanceof Listener)) {
|
|
644
|
+
console.warn(`[Loader] Default export is not a Listener: ${file}`);
|
|
645
|
+
return;
|
|
943
646
|
}
|
|
647
|
+
return this.add(listener), listener;
|
|
944
648
|
} catch (error) {
|
|
945
|
-
|
|
946
|
-
await errorHook.method.call(
|
|
947
|
-
instance,
|
|
948
|
-
error,
|
|
949
|
-
...args
|
|
950
|
-
);
|
|
951
|
-
} else {
|
|
952
|
-
throw error;
|
|
953
|
-
}
|
|
649
|
+
console.error(`An error occurred while trying to add listener for '${file}':`, error);
|
|
954
650
|
}
|
|
955
|
-
};
|
|
651
|
+
}), loaded = (await Promise.all(loads)).filter((x) => x !== void 0);
|
|
652
|
+
return console.log(`Loaded ${loaded.length} listener(s).`), loaded;
|
|
956
653
|
}
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
654
|
+
add(listener) {
|
|
655
|
+
if (!(listener instanceof Listener))
|
|
656
|
+
throw new Error("Invalid listener provided");
|
|
657
|
+
let execute = (...args) => {
|
|
658
|
+
listener.execute(new Context(), ...args);
|
|
659
|
+
};
|
|
660
|
+
this.listeners.push(listener), this.executors.set(listener, execute);
|
|
661
|
+
let { once, name } = listener.options;
|
|
662
|
+
this.client[once ? "once" : "on"](name, execute);
|
|
663
|
+
}
|
|
664
|
+
remove(target) {
|
|
665
|
+
let isMatched = (listener) => typeof target == "string" ? listener.options.name === target : listener === target, removed = [];
|
|
666
|
+
return this.listeners = this.listeners.filter((listener) => {
|
|
667
|
+
if (!isMatched(listener))
|
|
668
|
+
return true;
|
|
669
|
+
removed.push(listener);
|
|
670
|
+
let execute = this.executors.get(listener);
|
|
671
|
+
return execute && (this.client.removeListener(listener.options.name, execute), this.executors.delete(listener)), false;
|
|
672
|
+
}), removed;
|
|
673
|
+
}
|
|
674
|
+
getBaseIntents() {
|
|
675
|
+
return new IntentsBitField([GatewayIntentBits.Guilds]);
|
|
676
|
+
}
|
|
677
|
+
getNeededIntents() {
|
|
678
|
+
let result = this.getBaseIntents();
|
|
679
|
+
for (let listener of this.listeners) {
|
|
680
|
+
let eventName = listener.options.name, requiredIntents = EVENT_INTENT_MAPPING[eventName];
|
|
681
|
+
requiredIntents && result.add(requiredIntents);
|
|
977
682
|
}
|
|
978
683
|
return result;
|
|
979
684
|
}
|
|
980
685
|
};
|
|
981
686
|
|
|
982
|
-
// src/BakitClient.ts
|
|
983
|
-
var
|
|
984
|
-
constructor(options) {
|
|
985
|
-
if (options.getSyntaxErrorMessage === void 0) {
|
|
986
|
-
options.getSyntaxErrorMessage = _BakitClient.getSyntaxErrorMessage;
|
|
987
|
-
}
|
|
687
|
+
// src/base/BakitClient.ts
|
|
688
|
+
var BakitClient2 = class extends Client {
|
|
689
|
+
constructor(options, instance) {
|
|
988
690
|
super(options);
|
|
989
|
-
|
|
990
|
-
this.
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
);
|
|
994
|
-
this.on(Events.InteractionCreate, (interaction) => void this.handleInteraction(interaction));
|
|
995
|
-
this.on(Events.MessageCreate, (message) => void this.handleMessage(message));
|
|
996
|
-
}
|
|
997
|
-
static getSyntaxErrorMessage = (command, error, context, args, prefix) => {
|
|
998
|
-
const requiredSyntax = args.map((x) => Arg.format(x)).join(" ");
|
|
999
|
-
const root = Command.getRoot(command.constructor);
|
|
1000
|
-
if (!root) {
|
|
1001
|
-
return;
|
|
1002
|
-
}
|
|
1003
|
-
const content = [
|
|
1004
|
-
codeBlock(error.message),
|
|
1005
|
-
"Required Syntax:",
|
|
1006
|
-
codeBlock(`${prefix}${root.options.name} ${requiredSyntax}`)
|
|
1007
|
-
].join("\n");
|
|
1008
|
-
return {
|
|
1009
|
-
content
|
|
691
|
+
this.instance = instance;
|
|
692
|
+
this.managers = {
|
|
693
|
+
commands: new CommandManager(this),
|
|
694
|
+
listeners: new ListenerManager(this)
|
|
1010
695
|
};
|
|
1011
|
-
};
|
|
1012
|
-
async registerApplicationCommands(client) {
|
|
1013
|
-
const commands = CommandRegistry.constructors.map((c) => CommandRegistry.buildSlashCommand(c));
|
|
1014
|
-
await client.application.commands.set(commands);
|
|
1015
696
|
}
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
if (!resolver) {
|
|
1023
|
-
return;
|
|
1024
|
-
}
|
|
1025
|
-
const { trigger } = resolver;
|
|
1026
|
-
const command = CommandRegistry.instances.get(trigger);
|
|
1027
|
-
if (!command) {
|
|
1028
|
-
return;
|
|
1029
|
-
}
|
|
1030
|
-
await StateBox.run(() => this.handleMessageHooks(context, command, resolver));
|
|
697
|
+
managers;
|
|
698
|
+
/**
|
|
699
|
+
* Check if the client is connected to gateway successfully and finished initialization.
|
|
700
|
+
*/
|
|
701
|
+
isReady() {
|
|
702
|
+
return super.isReady();
|
|
1031
703
|
}
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
return;
|
|
1035
|
-
}
|
|
1036
|
-
const { commandName } = interaction;
|
|
1037
|
-
const command = CommandRegistry.instances.get(commandName);
|
|
1038
|
-
if (!command) {
|
|
1039
|
-
return;
|
|
1040
|
-
}
|
|
1041
|
-
const context = new ChatInputContext(interaction);
|
|
1042
|
-
await StateBox.run(() => this.handleChatInputHooks(context, command));
|
|
1043
|
-
}
|
|
1044
|
-
async handleChatInputHooks(context, instance) {
|
|
1045
|
-
const targetHooks = this.getChatInputTargetHooks(context.source, instance);
|
|
1046
|
-
let inheritedArgs = [];
|
|
1047
|
-
for (const hooks of [targetHooks.root, targetHooks.group, targetHooks.subcommand]) {
|
|
1048
|
-
if (!hooks) {
|
|
1049
|
-
continue;
|
|
1050
|
-
}
|
|
1051
|
-
const newArgs = await this.runChatInputHooks(context, instance, hooks, inheritedArgs);
|
|
1052
|
-
if (newArgs) {
|
|
1053
|
-
inheritedArgs = newArgs;
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
704
|
+
on(event, listener) {
|
|
705
|
+
return super.on(event, listener);
|
|
1056
706
|
}
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
return;
|
|
1060
|
-
}
|
|
1061
|
-
const root = Command.getRoot(instance.constructor);
|
|
1062
|
-
if (!root) {
|
|
1063
|
-
return;
|
|
1064
|
-
}
|
|
1065
|
-
resolver = await this.runMessageHooks(context, instance, root.hooks, resolver);
|
|
1066
|
-
if (!resolver) {
|
|
1067
|
-
return;
|
|
1068
|
-
}
|
|
1069
|
-
await this.handleChildMessageHooks(context, root, instance, resolver);
|
|
707
|
+
once(event, listener) {
|
|
708
|
+
return super.once(event, listener);
|
|
1070
709
|
}
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
return;
|
|
1074
|
-
}
|
|
1075
|
-
const usedValues = resolver.parsedValues.length;
|
|
1076
|
-
const nextTrigger = resolver.values[usedValues + skip];
|
|
1077
|
-
const child = parent.children.get(nextTrigger);
|
|
1078
|
-
if (!child) {
|
|
1079
|
-
return;
|
|
1080
|
-
}
|
|
1081
|
-
resolver = await this.runMessageHooks(context, instance, child.hooks, resolver);
|
|
1082
|
-
if (child instanceof CommandGroupEntry) {
|
|
1083
|
-
await this.handleChildMessageHooks(context, child, instance, resolver, skip + 1);
|
|
1084
|
-
}
|
|
710
|
+
off(event, listener) {
|
|
711
|
+
return super.off(event, listener);
|
|
1085
712
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
if (!mainHook) {
|
|
1089
|
-
return resolver;
|
|
1090
|
-
}
|
|
1091
|
-
const args = Arg.getMethodArguments(mainHook.method);
|
|
1092
|
-
try {
|
|
1093
|
-
resolver = await resolver.resolve(args);
|
|
1094
|
-
} catch (error) {
|
|
1095
|
-
if (error instanceof CommandSyntaxError) {
|
|
1096
|
-
const errorContent = await this.options.getSyntaxErrorMessage?.(
|
|
1097
|
-
instance,
|
|
1098
|
-
error,
|
|
1099
|
-
context,
|
|
1100
|
-
args,
|
|
1101
|
-
resolver.options.prefix
|
|
1102
|
-
);
|
|
1103
|
-
if (errorContent) {
|
|
1104
|
-
await context.send(errorContent);
|
|
1105
|
-
}
|
|
1106
|
-
return null;
|
|
1107
|
-
}
|
|
1108
|
-
throw error;
|
|
1109
|
-
}
|
|
1110
|
-
await this.runHooks(context, instance, hooks, resolver.parsedValues);
|
|
1111
|
-
return resolver;
|
|
713
|
+
removeAllListeners(event) {
|
|
714
|
+
return super.removeAllListeners(event);
|
|
1112
715
|
}
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
716
|
+
removeListener(event, listener) {
|
|
717
|
+
return super.removeListener(event, listener);
|
|
718
|
+
}
|
|
719
|
+
emit(event, ...args) {
|
|
720
|
+
return super.emit(event, ...args);
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Override BakitClient output when using logger for security concern.
|
|
724
|
+
* @returns `BakitClient {}`
|
|
725
|
+
*/
|
|
726
|
+
[inspect.custom]() {
|
|
727
|
+
return `${this.constructor.name} {}`;
|
|
728
|
+
}
|
|
729
|
+
};
|
|
730
|
+
|
|
731
|
+
// src/base/command/param/Params.ts
|
|
732
|
+
function createFactory(ctor) {
|
|
733
|
+
return (...args) => new ctor(...args);
|
|
734
|
+
}
|
|
735
|
+
var Params = {
|
|
736
|
+
string: createFactory(StringParam),
|
|
737
|
+
number: createFactory(NumberParam)
|
|
738
|
+
};
|
|
739
|
+
|
|
740
|
+
// src/defaults/command.ts
|
|
741
|
+
var messageCommandHandler = defineListener(Events.MessageCreate), chatInputCommandHandler = defineListener(Events.InteractionCreate), registerCommandsHandler = defineListener({
|
|
742
|
+
name: Events.ClientReady,
|
|
743
|
+
once: true
|
|
744
|
+
});
|
|
745
|
+
registerCommandsHandler.main(async (_, client) => {
|
|
746
|
+
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);
|
|
747
|
+
if (cachedMeta && cachedMeta.hash === currentHash) {
|
|
748
|
+
let { timestamp, count } = cachedMeta, time = new Date(timestamp).toLocaleString();
|
|
749
|
+
console.log(`${count} command(s) are up to date (Last sync: ${time}). Skipping registration.`);
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
try {
|
|
753
|
+
let result = await client.application.commands.set(payload);
|
|
754
|
+
cache.write(CACHE_KEY, {
|
|
755
|
+
hash: currentHash,
|
|
756
|
+
timestamp: Date.now(),
|
|
757
|
+
count: result.size
|
|
758
|
+
}), cache.write("commands/debug_dump.json", payload), console.log(`Registered ${result.size} application command(s).`);
|
|
759
|
+
} catch (error) {
|
|
760
|
+
console.error("Failed to register commands:", error);
|
|
761
|
+
}
|
|
762
|
+
});
|
|
763
|
+
messageCommandHandler.main(async (_, message) => {
|
|
764
|
+
let config = getConfig();
|
|
765
|
+
if (message.author.bot)
|
|
766
|
+
return;
|
|
767
|
+
let { content } = message, client = message.client, lowerContent = content.toLowerCase(), prefix = config.prefixes.find((p) => lowerContent.startsWith(p));
|
|
768
|
+
if (!prefix)
|
|
769
|
+
return;
|
|
770
|
+
let [name, ...args] = content.slice(prefix.length).trim().split(/\s+/g);
|
|
771
|
+
if (!name)
|
|
772
|
+
return;
|
|
773
|
+
let command = client.managers.commands.get(name);
|
|
774
|
+
if (!command)
|
|
775
|
+
return;
|
|
776
|
+
let context = new MessageContext(message), { params, quotes } = command.options, rawArgs = quotes ? tokenize(args.join(" ")) : args, resolvedArgs = [];
|
|
777
|
+
for (let i = 0; i < params.length; i++) {
|
|
778
|
+
let param = params[i], arg = rawArgs[i];
|
|
779
|
+
if (!param)
|
|
780
|
+
break;
|
|
781
|
+
let resolved = await param.resolve(context, arg);
|
|
782
|
+
resolvedArgs.push(resolved);
|
|
783
|
+
}
|
|
784
|
+
await command.execute(context, ...resolvedArgs);
|
|
785
|
+
});
|
|
786
|
+
chatInputCommandHandler.main(async (_, interaction) => {
|
|
787
|
+
if (!interaction.isChatInputCommand())
|
|
788
|
+
return;
|
|
789
|
+
let { commandName } = interaction, command = interaction.client.managers.commands.get(commandName);
|
|
790
|
+
if (!command)
|
|
791
|
+
return;
|
|
792
|
+
let context = new ChatInputContext(interaction), { params } = command.options, resolvedArgs = [];
|
|
793
|
+
for (let param of params) {
|
|
794
|
+
let resolved = await param.resolve(context);
|
|
795
|
+
resolvedArgs.push(resolved);
|
|
796
|
+
}
|
|
797
|
+
await command.execute(context, ...resolvedArgs);
|
|
798
|
+
});
|
|
799
|
+
var ProjectCacheManager = class {
|
|
800
|
+
rootDir;
|
|
801
|
+
constructor(root = process.cwd()) {
|
|
802
|
+
this.rootDir = join(root, ".bakit"), this.ensureRoot();
|
|
803
|
+
}
|
|
804
|
+
ensureRoot() {
|
|
805
|
+
existsSync(this.rootDir) || mkdirSync(this.rootDir, { recursive: true });
|
|
806
|
+
}
|
|
807
|
+
getHash(data) {
|
|
808
|
+
return createHash("sha256").update(JSON.stringify(data)).digest("hex");
|
|
809
|
+
}
|
|
810
|
+
async write(path, data) {
|
|
811
|
+
let fullPath = join(this.rootDir, path), dir = dirname(fullPath);
|
|
812
|
+
await mkdir(dir, { recursive: true });
|
|
813
|
+
let content = typeof data == "string" ? data : JSON.stringify(data);
|
|
814
|
+
await writeFile(fullPath, content, "utf-8");
|
|
815
|
+
}
|
|
816
|
+
async read(path) {
|
|
817
|
+
let fullPath = join(this.rootDir, path);
|
|
1143
818
|
try {
|
|
1144
|
-
await
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
if (errorHook) {
|
|
1149
|
-
await execute(errorHook, error);
|
|
1150
|
-
} else {
|
|
1151
|
-
throw error;
|
|
1152
|
-
}
|
|
819
|
+
let content = await readFile(fullPath, "utf-8");
|
|
820
|
+
return JSON.parse(content);
|
|
821
|
+
} catch {
|
|
822
|
+
return null;
|
|
1153
823
|
}
|
|
1154
824
|
}
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
throw new Error("No root found.");
|
|
1161
|
-
}
|
|
1162
|
-
let group;
|
|
1163
|
-
if (groupName) {
|
|
1164
|
-
const child = root.children.get(groupName);
|
|
1165
|
-
if (child instanceof CommandGroupEntry) {
|
|
1166
|
-
group = child;
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
let subcommand;
|
|
1170
|
-
if (subcommandName) {
|
|
1171
|
-
const parent = group || root;
|
|
1172
|
-
const child = parent.children.get(subcommandName);
|
|
1173
|
-
if (child instanceof SubcommandEntry) {
|
|
1174
|
-
subcommand = child;
|
|
1175
|
-
}
|
|
1176
|
-
}
|
|
1177
|
-
return {
|
|
1178
|
-
root: root.hooks,
|
|
1179
|
-
group: group?.hooks,
|
|
1180
|
-
subcommand: subcommand?.hooks
|
|
1181
|
-
};
|
|
825
|
+
async clear() {
|
|
826
|
+
await rm(this.rootDir, { recursive: true, force: true });
|
|
827
|
+
}
|
|
828
|
+
clearSync() {
|
|
829
|
+
existsSync(this.rootDir) && rmSync(this.rootDir, { recursive: true, force: true });
|
|
1182
830
|
}
|
|
1183
831
|
};
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
832
|
+
|
|
833
|
+
// src/base/Instance.ts
|
|
834
|
+
var Instance = class {
|
|
835
|
+
client;
|
|
836
|
+
cache;
|
|
837
|
+
constructor() {
|
|
838
|
+
this.cache = new ProjectCacheManager();
|
|
839
|
+
}
|
|
840
|
+
async start() {
|
|
841
|
+
await loadConfig();
|
|
842
|
+
let config = getConfig();
|
|
843
|
+
this.client = new BakitClient2(
|
|
844
|
+
{
|
|
845
|
+
intents: [],
|
|
846
|
+
...config.clientOptions
|
|
847
|
+
},
|
|
848
|
+
this
|
|
849
|
+
), await this.loadModules(), this.initIntents(), await this.client.login(config.token);
|
|
850
|
+
}
|
|
851
|
+
loadModules() {
|
|
852
|
+
let { managers } = this.client, { commands, listeners } = managers;
|
|
853
|
+
return listeners.add(chatInputCommandHandler), listeners.add(messageCommandHandler), listeners.add(registerCommandsHandler), Promise.all([commands.loadModules(), listeners.loadModules()]);
|
|
854
|
+
}
|
|
855
|
+
initIntents() {
|
|
856
|
+
let config = getConfig(), { options, managers } = this.client, { listeners } = managers, intents;
|
|
857
|
+
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;
|
|
858
|
+
}
|
|
1209
859
|
};
|
|
860
|
+
function useApp() {
|
|
861
|
+
return new Instance();
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
export { $jiti, ArgumentError, BakitClient2 as BakitClient, BakitError, BaseClientManager, BaseCommandContext, BaseParam, BaseParamSchema, ChatInputContext, Command, CommandManager, CommandOptionsSchema, Context, EVENT_INTENT_MAPPING, HookOrder, HookState, Instance, LifecycleManager, Listener, ListenerManager, ListenerOptionsSchema, MessageContext, NumberParam, NumberParamSchema, ParamUserType, Params, ProjectConfigSchema, StringParam, StringParamSchema, UserParam, UserParamSchema, defineCommand, defineConfig, defineListener, extractSnowflakeId, getConfig, loadConfig, tokenize, useApp, validateParamsOrder };
|