bakit 1.0.0-beta.9 → 2.0.0-alpha.2
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/dist/index.d.ts +304 -68
- package/dist/index.js +351 -1093
- package/package.json +16 -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,73 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
1
|
+
import { GatewayIntentBits, Events, Client, Collection, ChatInputCommandInteraction, Message } from 'discord.js';
|
|
2
|
+
import z3, { z } from 'zod';
|
|
3
|
+
import { pathToFileURL } from 'url';
|
|
4
|
+
import glob from 'tiny-glob';
|
|
5
|
+
import { inspect } from 'util';
|
|
6
|
+
import { posix } from 'path';
|
|
3
7
|
|
|
4
|
-
// src/
|
|
5
|
-
|
|
6
|
-
Client,
|
|
7
|
-
codeBlock,
|
|
8
|
-
Events
|
|
9
|
-
} from "discord.js";
|
|
10
|
-
|
|
11
|
-
// src/command/CommandRegistry.ts
|
|
12
|
-
import {
|
|
13
|
-
Collection as Collection2,
|
|
14
|
-
SlashCommandBuilder,
|
|
15
|
-
SlashCommandSubcommandBuilder,
|
|
16
|
-
SlashCommandSubcommandGroupBuilder
|
|
17
|
-
} from "discord.js";
|
|
18
|
-
import glob from "tiny-glob";
|
|
19
|
-
import { pathToFileURL } from "url";
|
|
20
|
-
|
|
21
|
-
// src/command/CommandEntry.ts
|
|
22
|
-
import { Collection } from "discord.js";
|
|
23
|
-
|
|
24
|
-
// src/base/BaseEntry.ts
|
|
25
|
-
var BaseEntry = class {
|
|
26
|
-
target;
|
|
27
|
-
hooks = {
|
|
28
|
-
["MAIN" /* Main */]: void 0,
|
|
29
|
-
["ERROR" /* Error */]: void 0,
|
|
30
|
-
["POST" /* Post */]: void 0,
|
|
31
|
-
["PRE" /* Pre */]: void 0
|
|
32
|
-
};
|
|
33
|
-
main;
|
|
34
|
-
pre;
|
|
35
|
-
post;
|
|
36
|
-
error;
|
|
37
|
-
constructor() {
|
|
38
|
-
this.main = this.createMainHookDecorator("MAIN" /* Main */);
|
|
39
|
-
this.pre = this.createMainHookDecorator("PRE" /* Pre */);
|
|
40
|
-
this.post = this.createMainHookDecorator("POST" /* Post */);
|
|
41
|
-
this.error = this.createMainHookDecorator("ERROR" /* Error */);
|
|
42
|
-
}
|
|
43
|
-
setTarget(target) {
|
|
44
|
-
this.target = target;
|
|
45
|
-
}
|
|
46
|
-
createMainHookDecorator(state) {
|
|
47
|
-
return (target, _key, descriptor) => {
|
|
48
|
-
this.addHook(state, target, descriptor);
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
createErrorHookDecorator(state) {
|
|
52
|
-
return (target, _key, descriptor) => {
|
|
53
|
-
this.addHook(state, target, descriptor);
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
addHook(state, target, descriptor) {
|
|
57
|
-
if (this.target && this.target !== target.constructor) {
|
|
58
|
-
throw new Error("Hook is used at wrong constructor.");
|
|
59
|
-
}
|
|
60
|
-
const { value: method } = descriptor;
|
|
61
|
-
if (typeof method !== "function") {
|
|
62
|
-
throw new Error("Invalid target method for hook.");
|
|
63
|
-
}
|
|
64
|
-
const hook = {
|
|
65
|
-
state,
|
|
66
|
-
method,
|
|
67
|
-
entry: this
|
|
68
|
-
};
|
|
69
|
-
this.hooks[state] = hook;
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
// src/command/CommandEntry.ts
|
|
74
|
-
var BaseCommandEntry = class extends BaseEntry {
|
|
75
|
-
constructor(options) {
|
|
76
|
-
super();
|
|
77
|
-
this.options = options;
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
var BaseCommandGroupEntry = class extends BaseCommandEntry {
|
|
81
|
-
children = new Collection();
|
|
82
|
-
subcommand(options) {
|
|
83
|
-
const fullOptions = typeof options === "string" ? { name: options, description: `${options} command` } : { description: `${options.name} command`, ...options };
|
|
84
|
-
if (this.children.has(fullOptions.name)) {
|
|
85
|
-
throw new Error(`Entry "${fullOptions.name}" is already existed.`);
|
|
86
|
-
}
|
|
87
|
-
const subcommand = new SubcommandEntry(fullOptions, this);
|
|
88
|
-
this.children.set(fullOptions.name, subcommand);
|
|
89
|
-
return subcommand;
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
var RootCommandEntry = class extends BaseCommandGroupEntry {
|
|
93
|
-
group(options) {
|
|
94
|
-
const fullOptions = typeof options === "string" ? { name: options, description: `${options} command` } : { description: `${options.name} command`, ...options };
|
|
95
|
-
if (this.children.has(fullOptions.name)) {
|
|
96
|
-
throw new Error(`Entry "${fullOptions.name}" is already existed.`);
|
|
97
|
-
}
|
|
98
|
-
const group = new CommandGroupEntry(fullOptions, this);
|
|
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);
|
|
140
|
-
}
|
|
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
|
-
|
|
153
|
-
// src/command/argument/Arg.ts
|
|
154
|
-
var ARGS_KEY = Symbol("args");
|
|
155
|
-
var cache = /* @__PURE__ */ new WeakMap();
|
|
156
|
-
function getMethodArguments(method, init = false) {
|
|
157
|
-
let args = cache.get(method) ?? Reflect.getMetadata(ARGS_KEY, method);
|
|
158
|
-
if (!args) {
|
|
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
|
-
}
|
|
218
|
-
break;
|
|
219
|
-
}
|
|
220
|
-
case "user" /* User */:
|
|
221
|
-
case "member" /* Member */: {
|
|
222
|
-
break;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
return parts.join(", ");
|
|
226
|
-
}
|
|
227
|
-
function format(arg) {
|
|
228
|
-
const { name, required, tuple } = arg;
|
|
229
|
-
const opening = required ? "<" : "[";
|
|
230
|
-
const closing = required ? ">" : "]";
|
|
231
|
-
const prefix = tuple ? "..." : "";
|
|
232
|
-
return `${opening}${prefix}${name}: ${describeArgumentExpectation(arg)}${closing}`;
|
|
233
|
-
}
|
|
234
|
-
var Arg = {
|
|
235
|
-
getMethodArguments,
|
|
236
|
-
createArgument,
|
|
237
|
-
describeArgumentExpectation,
|
|
238
|
-
format,
|
|
239
|
-
string,
|
|
240
|
-
number,
|
|
241
|
-
integer,
|
|
242
|
-
user,
|
|
243
|
-
member
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
// src/command/CommandRegistry.ts
|
|
247
|
-
var CommandRegistry = class _CommandRegistry {
|
|
248
|
-
static constructors = new Collection2();
|
|
249
|
-
static instances = new Collection2();
|
|
8
|
+
// src/config.ts
|
|
9
|
+
var ProjectConfigSchema = z.object({
|
|
250
10
|
/**
|
|
251
|
-
*
|
|
252
|
-
*
|
|
11
|
+
* The gateway intents to use for the Discord client.
|
|
12
|
+
*
|
|
13
|
+
* - `auto` — automatically determine the required intents.
|
|
14
|
+
* - bigint — a raw bitfield value representing the combined intents.
|
|
15
|
+
* - array — a list of individual intent flags from `GatewayIntentBits`.
|
|
16
|
+
*
|
|
17
|
+
* @defaultvalue `auto`
|
|
253
18
|
*/
|
|
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
|
-
}
|
|
19
|
+
intents: z.union([z.literal("auto"), z.bigint(), z.array(z.enum(GatewayIntentBits))]).default("auto"),
|
|
263
20
|
/**
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
21
|
+
* Optional custom client options for Discord.js (excluding `intents`).
|
|
22
|
+
*
|
|
23
|
+
* These are passed directly to the `Client` constructor when initializing the bot.
|
|
24
|
+
*
|
|
25
|
+
* @see {@link https://discord.js.org/docs/packages/discord.js/main/ClientOptions:Interface}
|
|
268
26
|
*/
|
|
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
|
-
}
|
|
27
|
+
clientOptions: z.custom().optional(),
|
|
286
28
|
/**
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
* @
|
|
29
|
+
* The path to the main project source directory.
|
|
30
|
+
*
|
|
31
|
+
* @defaultvalue `src`
|
|
290
32
|
*/
|
|
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
|
-
} else if (child instanceof SubcommandEntry) {
|
|
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
|
-
}
|
|
339
|
-
}
|
|
340
|
-
static attachSlashCommandOption(builder, arg) {
|
|
341
|
-
const setupOption = (option) => {
|
|
342
|
-
return option.setName(arg.name).setDescription(arg.description || arg.name).setRequired(Boolean(arg.required));
|
|
343
|
-
};
|
|
344
|
-
switch (arg.type) {
|
|
345
|
-
case "string" /* String */: {
|
|
346
|
-
builder.addStringOption((data) => {
|
|
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
|
-
}
|
|
33
|
+
entryDir: z.string().default("src")
|
|
34
|
+
});
|
|
35
|
+
function defineConfig(config) {
|
|
36
|
+
return config;
|
|
37
|
+
}
|
|
38
|
+
var _config;
|
|
39
|
+
async function loadConfig(cwd = process.cwd()) {
|
|
40
|
+
if (_config)
|
|
41
|
+
return console.warn("loadConfig() was called more than once. This shouldn't happen."), _config;
|
|
42
|
+
let globPattern = `bakit.config.{${["ts", "js"].join(",")}}`, [configPath, other] = await glob(globPattern, {
|
|
43
|
+
cwd: cwd.replace(/\\/g, "/"),
|
|
44
|
+
// ensure the path uses `/` instead of `\` on Windows
|
|
45
|
+
absolute: true
|
|
46
|
+
});
|
|
47
|
+
if (!configPath)
|
|
48
|
+
throw new Error("Missing config file");
|
|
49
|
+
other && console.warn(`Multiple config files found in ${cwd}. Using ${configPath}.`);
|
|
50
|
+
let configFileURL = pathToFileURL(configPath).toString(), { default: config } = await import(configFileURL);
|
|
51
|
+
return _config = Object.freeze(await ProjectConfigSchema.parseAsync(config)), _config;
|
|
52
|
+
}
|
|
53
|
+
function getConfig() {
|
|
54
|
+
if (!_config)
|
|
55
|
+
throw new Error("Project config is not loaded.");
|
|
56
|
+
return _config;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/base/lifecycle/Context.ts
|
|
60
|
+
var Context = class {
|
|
61
|
+
canceled = false;
|
|
62
|
+
cancel() {
|
|
63
|
+
this.canceled = true;
|
|
390
64
|
}
|
|
391
65
|
};
|
|
392
66
|
|
|
393
|
-
// src/command/
|
|
394
|
-
|
|
395
|
-
ChatInputCommandInteraction,
|
|
396
|
-
Message
|
|
397
|
-
} from "discord.js";
|
|
398
|
-
var BaseContext = class {
|
|
67
|
+
// src/command/CommandContext.ts
|
|
68
|
+
var BaseCommandContext = class extends Context {
|
|
399
69
|
constructor(source) {
|
|
70
|
+
super();
|
|
400
71
|
this.source = source;
|
|
401
72
|
}
|
|
402
73
|
get client() {
|
|
@@ -414,26 +85,25 @@ var BaseContext = class {
|
|
|
414
85
|
get guildId() {
|
|
415
86
|
return this.source.guildId;
|
|
416
87
|
}
|
|
88
|
+
get member() {
|
|
89
|
+
return this.source.member;
|
|
90
|
+
}
|
|
417
91
|
inGuild() {
|
|
418
|
-
return
|
|
92
|
+
return !!this.guildId;
|
|
419
93
|
}
|
|
420
94
|
inCachedGuild() {
|
|
421
|
-
if (this.isChatInput())
|
|
95
|
+
if (this.isChatInput())
|
|
422
96
|
return this.source.inCachedGuild();
|
|
423
|
-
|
|
97
|
+
if (this.isMessage())
|
|
424
98
|
return this.source.inGuild();
|
|
425
|
-
|
|
426
|
-
throw new Error("Invalid source");
|
|
427
|
-
}
|
|
99
|
+
throw new Error("Invalid source");
|
|
428
100
|
}
|
|
429
|
-
get
|
|
430
|
-
if (this.isChatInput())
|
|
101
|
+
get user() {
|
|
102
|
+
if (this.isChatInput())
|
|
431
103
|
return this.source.user;
|
|
432
|
-
|
|
104
|
+
if (this.isMessage())
|
|
433
105
|
return this.source.author;
|
|
434
|
-
|
|
435
|
-
throw new Error("Invalid source");
|
|
436
|
-
}
|
|
106
|
+
throw new Error("Invalid source");
|
|
437
107
|
}
|
|
438
108
|
isChatInput() {
|
|
439
109
|
return this.source instanceof ChatInputCommandInteraction;
|
|
@@ -441,769 +111,357 @@ var BaseContext = class {
|
|
|
441
111
|
isMessage() {
|
|
442
112
|
return this.source instanceof Message;
|
|
443
113
|
}
|
|
444
|
-
}
|
|
445
|
-
var ChatInputContext = class extends BaseContext {
|
|
114
|
+
}, ChatInputContext = class extends BaseCommandContext {
|
|
446
115
|
async send(options) {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
}
|
|
450
|
-
const sendOptions = {
|
|
116
|
+
typeof options == "string" && (options = { content: options });
|
|
117
|
+
let sendOptions = {
|
|
451
118
|
...options,
|
|
452
119
|
withResponse: true
|
|
453
120
|
};
|
|
454
|
-
|
|
455
|
-
return await this.source.followUp(sendOptions);
|
|
456
|
-
}
|
|
457
|
-
const response = await this.source.reply(sendOptions);
|
|
458
|
-
return response.resource?.message;
|
|
121
|
+
return this.source.deferred || this.source.replied ? await this.source.followUp(sendOptions) : (await this.source.reply(sendOptions)).resource?.message;
|
|
459
122
|
}
|
|
460
|
-
}
|
|
461
|
-
var MessageContext = class extends BaseContext {
|
|
123
|
+
}, MessageContext = class extends BaseCommandContext {
|
|
462
124
|
async send(options) {
|
|
463
|
-
|
|
464
|
-
if (!channel?.isSendable())
|
|
125
|
+
let { channel } = this;
|
|
126
|
+
if (!channel?.isSendable())
|
|
465
127
|
throw new Error("Invalid channel or channel is not sendable");
|
|
466
|
-
}
|
|
467
128
|
return await channel.send(options);
|
|
468
129
|
}
|
|
469
130
|
};
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
const idMatch = value.match(/^<@!?(\d+)>$/);
|
|
474
|
-
if (idMatch) {
|
|
475
|
-
return idMatch[1];
|
|
476
|
-
}
|
|
477
|
-
const numericMatch = value.match(/^(\d{17,19})$/);
|
|
478
|
-
if (numericMatch) {
|
|
479
|
-
return numericMatch[1];
|
|
131
|
+
var LifecycleManager = class {
|
|
132
|
+
constructor(id) {
|
|
133
|
+
this.id = id;
|
|
480
134
|
}
|
|
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
|
-
|
|
135
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
136
|
+
hooks = {
|
|
137
|
+
MAIN: new Collection(),
|
|
138
|
+
PRE: new Collection(),
|
|
139
|
+
POST: new Collection(),
|
|
140
|
+
ERROR: new Collection()
|
|
141
|
+
};
|
|
142
|
+
getName(name) {
|
|
143
|
+
return `${this.id}:${name}`;
|
|
144
|
+
}
|
|
145
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
146
|
+
setHook(name, state, callback, order = 1 /* Last */) {
|
|
147
|
+
let currentHooks = this.hooks[state], key = this.getName(name);
|
|
148
|
+
if (currentHooks.has(key) && console.warn(`Overriding duplicate hook '${key}' for state '${state}'`), order === 1 /* Last */)
|
|
149
|
+
currentHooks.set(key, callback);
|
|
150
|
+
else {
|
|
151
|
+
let existingEntries = [...currentHooks.entries()].filter(([k]) => k !== key);
|
|
152
|
+
currentHooks.clear(), currentHooks.set(key, callback);
|
|
153
|
+
for (let [k, v] of existingEntries)
|
|
154
|
+
currentHooks.set(k, v);
|
|
155
|
+
}
|
|
156
|
+
return this;
|
|
157
|
+
}
|
|
158
|
+
main(callback) {
|
|
159
|
+
return this.setHook("main", "MAIN" /* Main */, callback);
|
|
160
|
+
}
|
|
161
|
+
pre(callback) {
|
|
162
|
+
return this.setHook("pre", "PRE" /* Pre */, callback);
|
|
163
|
+
}
|
|
164
|
+
post(callback) {
|
|
165
|
+
return this.setHook("post", "POST" /* Post */, callback);
|
|
166
|
+
}
|
|
167
|
+
error(callback) {
|
|
168
|
+
return this.setHook("error", "ERROR" /* Error */, callback);
|
|
169
|
+
}
|
|
170
|
+
async execute(context, ...args) {
|
|
171
|
+
let pipeline = [
|
|
172
|
+
...this.hooks.PRE.values(),
|
|
173
|
+
...this.hooks.MAIN.values(),
|
|
174
|
+
...this.hooks.POST.values()
|
|
175
|
+
], error;
|
|
176
|
+
for (let hook of pipeline) {
|
|
177
|
+
if (context.canceled)
|
|
511
178
|
break;
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
`> Expected: ${expected}`,
|
|
517
|
-
`> Received: ${String(received)}`
|
|
518
|
-
].join("\n");
|
|
179
|
+
try {
|
|
180
|
+
await hook(context, ...args);
|
|
181
|
+
} catch (e) {
|
|
182
|
+
error = e;
|
|
519
183
|
break;
|
|
520
184
|
}
|
|
521
|
-
|
|
522
|
-
|
|
185
|
+
}
|
|
186
|
+
if (!error)
|
|
187
|
+
return;
|
|
188
|
+
if (!this.hooks.ERROR.size)
|
|
189
|
+
throw error;
|
|
190
|
+
for (let [key, callback] of this.hooks.ERROR.entries()) {
|
|
191
|
+
if (context.canceled)
|
|
523
192
|
break;
|
|
193
|
+
try {
|
|
194
|
+
await callback(context, error, ...args);
|
|
195
|
+
} catch (innerError) {
|
|
196
|
+
console.error(`[Lifecycle] Error handler for '${key}' failed:`, innerError);
|
|
524
197
|
}
|
|
525
198
|
}
|
|
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
|
-
}
|
|
533
|
-
get name() {
|
|
534
|
-
return `CommandSyntaxError[${this.type}]`;
|
|
535
199
|
}
|
|
536
200
|
};
|
|
537
201
|
|
|
538
|
-
// src/command/
|
|
539
|
-
var
|
|
202
|
+
// src/command/param/Param.ts
|
|
203
|
+
var BaseParam = class {
|
|
204
|
+
options;
|
|
540
205
|
constructor(options) {
|
|
541
|
-
this.options = options;
|
|
542
|
-
}
|
|
543
|
-
parsedValues = [];
|
|
544
|
-
/**
|
|
545
|
-
* Get the first value as the command trigger.
|
|
546
|
-
*/
|
|
547
|
-
get trigger() {
|
|
548
|
-
return this.options.values[0];
|
|
206
|
+
this.options = { ...options, required: options.required ?? true };
|
|
549
207
|
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
get specifiedAmount() {
|
|
554
|
-
return this.options.values.length - this.options.startAt;
|
|
208
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
209
|
+
setOption(key, value) {
|
|
210
|
+
return value === null ? delete this.options[key] : this.options[key] = value, this;
|
|
555
211
|
}
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
*/
|
|
559
|
-
get values() {
|
|
560
|
-
return [...this.options.values];
|
|
212
|
+
name(value) {
|
|
213
|
+
return this.setOption("name", value);
|
|
561
214
|
}
|
|
562
|
-
|
|
563
|
-
return this.
|
|
215
|
+
description(value) {
|
|
216
|
+
return this.setOption("description", value);
|
|
564
217
|
}
|
|
565
|
-
|
|
566
|
-
|
|
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
|
-
});
|
|
218
|
+
required(value) {
|
|
219
|
+
return this.setOption("required", value);
|
|
587
220
|
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
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
|
-
}
|
|
630
|
-
}
|
|
631
|
-
async dynamicParse() {
|
|
632
|
-
const { args, values } = this.options;
|
|
633
|
-
let argIndex = 0;
|
|
634
|
-
let valueIndex = this.options.startAt + 1;
|
|
635
|
-
while (valueIndex < values.length && argIndex < args.length) {
|
|
636
|
-
const value = values[valueIndex];
|
|
637
|
-
const arg = args[argIndex];
|
|
638
|
-
if (arg.tuple) {
|
|
639
|
-
this.parsedValues.push(...await this.resolveTuple(arg, valueIndex, argIndex));
|
|
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
|
-
}
|
|
666
|
-
}
|
|
667
|
-
async resolveTuple(arg, startIndex, argIndex) {
|
|
668
|
-
const { args } = this.options;
|
|
669
|
-
if (argIndex !== args.length - 1) {
|
|
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
|
-
}
|
|
706
|
-
}
|
|
707
|
-
async matchUserValue(arg, value) {
|
|
708
|
-
const userId = extractId(value);
|
|
709
|
-
if (!userId) {
|
|
710
|
-
return null;
|
|
711
|
-
}
|
|
712
|
-
const user2 = await this.client.users.fetch(userId).catch(() => null);
|
|
713
|
-
if (!user2) {
|
|
714
|
-
return null;
|
|
715
|
-
}
|
|
716
|
-
return user2;
|
|
221
|
+
/**
|
|
222
|
+
* Helper to normalize string inputs into an options object.
|
|
223
|
+
*/
|
|
224
|
+
static getOptions(options) {
|
|
225
|
+
return typeof options == "string" ? { name: options } : options;
|
|
717
226
|
}
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
return null;
|
|
722
|
-
}
|
|
723
|
-
if (arg.minValue !== void 0 && intVal < arg.minValue) {
|
|
724
|
-
return null;
|
|
725
|
-
}
|
|
726
|
-
if (arg.maxValue !== void 0 && intVal > arg.maxValue) {
|
|
727
|
-
return null;
|
|
728
|
-
}
|
|
729
|
-
return intVal;
|
|
227
|
+
}, StringParam = class extends BaseParam {
|
|
228
|
+
constructor(options) {
|
|
229
|
+
super(BaseParam.getOptions(options));
|
|
730
230
|
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
if (isNaN(numVal)) {
|
|
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;
|
|
231
|
+
required(value) {
|
|
232
|
+
return super.required(value);
|
|
743
233
|
}
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
}
|
|
751
|
-
return value;
|
|
234
|
+
/**
|
|
235
|
+
* Sets the minimum allowed length for this string.
|
|
236
|
+
* Pass `null` to remove this constraint.
|
|
237
|
+
*/
|
|
238
|
+
min(length) {
|
|
239
|
+
return this.setOption("minLength", length);
|
|
752
240
|
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
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
|
-
}
|
|
241
|
+
/**
|
|
242
|
+
* Sets the maximum allowed length for this string.
|
|
243
|
+
* Pass `null` to remove this constraint.
|
|
244
|
+
*/
|
|
245
|
+
max(length) {
|
|
246
|
+
return this.setOption("maxLength", length);
|
|
768
247
|
}
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
import { AsyncLocalStorage } from "async_hooks";
|
|
773
|
-
var StateBox = class _StateBox {
|
|
774
|
-
static STATES_KEY = Symbol("states");
|
|
775
|
-
static storage = new AsyncLocalStorage();
|
|
776
|
-
static getState() {
|
|
777
|
-
const state = this.storage.getStore();
|
|
778
|
-
if (!state) {
|
|
779
|
-
throw new Error("No active context, did you forget to wrap it with StateBox.wrap()?");
|
|
780
|
-
}
|
|
781
|
-
return state;
|
|
248
|
+
}, NumberParam = class extends BaseParam {
|
|
249
|
+
constructor(options) {
|
|
250
|
+
super(BaseParam.getOptions(options));
|
|
782
251
|
}
|
|
783
|
-
|
|
784
|
-
return
|
|
252
|
+
required(value) {
|
|
253
|
+
return super.required(value);
|
|
785
254
|
}
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
return
|
|
255
|
+
/**
|
|
256
|
+
* Sets the minimum allowed value for this number.
|
|
257
|
+
* Pass `null` to remove this constraint.
|
|
258
|
+
*/
|
|
259
|
+
min(value) {
|
|
260
|
+
return this.setOption("minValue", value);
|
|
792
261
|
}
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
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
|
-
};
|
|
262
|
+
/**
|
|
263
|
+
* Sets the maximum allowed value for this number.
|
|
264
|
+
* Pass `null` to remove this constraint.
|
|
265
|
+
*/
|
|
266
|
+
max(value) {
|
|
267
|
+
return this.setOption("maxValue", value);
|
|
811
268
|
}
|
|
812
269
|
};
|
|
813
270
|
|
|
814
|
-
// src/
|
|
815
|
-
var
|
|
271
|
+
// src/command/Command.ts
|
|
272
|
+
var CommandOptionsSchema = z.object({
|
|
273
|
+
name: z.string(),
|
|
274
|
+
description: z.string().min(1).max(100).optional(),
|
|
275
|
+
params: z.array(z.instanceof(BaseParam)).default([])
|
|
276
|
+
}).transform((data) => ({
|
|
277
|
+
...data,
|
|
278
|
+
description: data.description ?? `Command ${data.name}`
|
|
279
|
+
})), Command = class extends LifecycleManager {
|
|
816
280
|
constructor(options) {
|
|
817
|
-
|
|
818
|
-
this.options =
|
|
281
|
+
let _options = CommandOptionsSchema.parse(typeof options == "string" ? { name: options } : options);
|
|
282
|
+
super(`command:${_options.name}`), this.options = _options;
|
|
819
283
|
}
|
|
820
284
|
};
|
|
285
|
+
function defineCommand(options) {
|
|
286
|
+
return new Command(options);
|
|
287
|
+
}
|
|
821
288
|
|
|
822
|
-
// src/
|
|
823
|
-
var
|
|
824
|
-
(
|
|
825
|
-
|
|
826
|
-
function use(entry) {
|
|
827
|
-
return (target) => {
|
|
828
|
-
Reflect.defineMetadata(ListenerAPI2.ENTRY_KEY, entry, target);
|
|
829
|
-
};
|
|
289
|
+
// src/base/BaseClientManager.ts
|
|
290
|
+
var BaseClientManager = class {
|
|
291
|
+
constructor(client) {
|
|
292
|
+
this.client = client;
|
|
830
293
|
}
|
|
831
|
-
|
|
832
|
-
function getEntry(target) {
|
|
833
|
-
return Reflect.getMetadata(ListenerAPI2.ENTRY_KEY, target);
|
|
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);
|
|
840
|
-
}
|
|
841
|
-
var Listener = Object.assign(ListenerFactory, ListenerAPI);
|
|
294
|
+
};
|
|
842
295
|
|
|
843
|
-
// src/
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
if (!this.client) {
|
|
864
|
-
throw new Error("Client is not ready.");
|
|
296
|
+
// src/command/CommandManager.ts
|
|
297
|
+
var CommandManager = class extends BaseClientManager {
|
|
298
|
+
commands = new Collection();
|
|
299
|
+
async loadModules() {
|
|
300
|
+
let entryDir = posix.resolve(getConfig().entryDir), pattern = posix.join(entryDir, "commands", "**/*.{ts,js}"), loads = (await glob(pattern, {
|
|
301
|
+
cwd: process.cwd()
|
|
302
|
+
})).map(async (file) => {
|
|
303
|
+
try {
|
|
304
|
+
let { default: command } = await import(pathToFileURL(file).toString());
|
|
305
|
+
if (!command) {
|
|
306
|
+
console.warn(`[Loader] File has no default export: ${file}`);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
if (!(command instanceof Command)) {
|
|
310
|
+
console.warn(`[Loader] Default export is not a Command: ${file}`);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
return this.add(command), command;
|
|
314
|
+
} catch (error) {
|
|
315
|
+
console.error(`An error occurred while trying to add command for '${file}':`, error);
|
|
865
316
|
}
|
|
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
|
-
});
|
|
317
|
+
}), loaded = (await Promise.all(loads)).filter((x) => x !== void 0);
|
|
318
|
+
return console.log(`Loaded ${loaded.length} command(s).`), loaded;
|
|
876
319
|
}
|
|
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;
|
|
320
|
+
add(command) {
|
|
321
|
+
if (!(command instanceof Command))
|
|
322
|
+
throw new Error("Invalid command provided");
|
|
323
|
+
let { name } = command.options;
|
|
324
|
+
if (this.commands.has(name)) {
|
|
325
|
+
console.warn(`[Loader] Duplicate command registered: '${name}'`);
|
|
326
|
+
return;
|
|
896
327
|
}
|
|
897
|
-
|
|
898
|
-
emitter?.removeListener(name, executor);
|
|
899
|
-
this.executors.delete(instance);
|
|
900
|
-
return true;
|
|
328
|
+
this.commands.set(name, command);
|
|
901
329
|
}
|
|
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;
|
|
330
|
+
remove(target) {
|
|
331
|
+
let name = typeof target == "string" ? target : target.options.name, existing = this.commands.get(name);
|
|
332
|
+
if (existing)
|
|
333
|
+
return this.commands.delete(name), existing;
|
|
914
334
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
* @param newClient base client to set for the registry.
|
|
918
|
-
*/
|
|
919
|
-
static setClient(newClient) {
|
|
920
|
-
this.client = newClient;
|
|
335
|
+
get(name) {
|
|
336
|
+
return this.commands.get(name);
|
|
921
337
|
}
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
338
|
+
};
|
|
339
|
+
var ListenerOptionsSchema = z3.object({
|
|
340
|
+
name: z3.enum(Events),
|
|
341
|
+
once: z3.boolean().default(false)
|
|
342
|
+
}), Listener = class extends LifecycleManager {
|
|
343
|
+
options;
|
|
344
|
+
constructor(options) {
|
|
345
|
+
let _options = ListenerOptionsSchema.parse(typeof options == "string" ? { name: options } : options);
|
|
346
|
+
super(`listener:${_options.name}`), this.options = options;
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
function defineListener(options) {
|
|
350
|
+
return new Listener(options);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// src/listener/ListenerManager.ts
|
|
354
|
+
var ListenerManager = class extends BaseClientManager {
|
|
355
|
+
listeners = [];
|
|
356
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
357
|
+
executors = /* @__PURE__ */ new WeakMap();
|
|
358
|
+
async loadModules() {
|
|
359
|
+
let entryDir = posix.resolve(getConfig().entryDir), pattern = posix.join(entryDir, "listeners", "**/*.{ts,js}"), loads = (await glob(pattern, {
|
|
360
|
+
cwd: process.cwd()
|
|
361
|
+
})).map(async (file) => {
|
|
936
362
|
try {
|
|
937
|
-
|
|
938
|
-
|
|
363
|
+
let { default: listener } = await import(pathToFileURL(file).toString());
|
|
364
|
+
if (!listener) {
|
|
365
|
+
console.warn(`[Loader] File has no default export: ${file}`);
|
|
366
|
+
return;
|
|
939
367
|
}
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
368
|
+
if (!(listener instanceof Listener)) {
|
|
369
|
+
console.warn(`[Loader] Default export is not a Listener: ${file}`);
|
|
370
|
+
return;
|
|
943
371
|
}
|
|
372
|
+
return this.add(listener), listener;
|
|
944
373
|
} catch (error) {
|
|
945
|
-
|
|
946
|
-
await errorHook.method.call(
|
|
947
|
-
instance,
|
|
948
|
-
error,
|
|
949
|
-
...args
|
|
950
|
-
);
|
|
951
|
-
} else {
|
|
952
|
-
throw error;
|
|
953
|
-
}
|
|
374
|
+
console.error(`An error occurred while trying to add listener for '${file}':`, error);
|
|
954
375
|
}
|
|
955
|
-
};
|
|
376
|
+
}), loaded = (await Promise.all(loads)).filter((x) => x !== void 0);
|
|
377
|
+
return console.log(`Loaded ${loaded.length} listener(s).`), loaded;
|
|
956
378
|
}
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
result.push(await loader);
|
|
977
|
-
}
|
|
978
|
-
return result;
|
|
379
|
+
add(listener) {
|
|
380
|
+
if (!(listener instanceof Listener))
|
|
381
|
+
throw new Error("Invalid listener provided");
|
|
382
|
+
let execute = (...args) => {
|
|
383
|
+
listener.execute(new Context(), ...args);
|
|
384
|
+
};
|
|
385
|
+
this.listeners.push(listener), this.executors.set(listener, execute);
|
|
386
|
+
let { once, name } = listener.options;
|
|
387
|
+
this.client[once ? "once" : "on"](name, execute);
|
|
388
|
+
}
|
|
389
|
+
remove(target) {
|
|
390
|
+
let isMatched = (listener) => typeof target == "string" ? listener.options.name === target : listener === target, removed = [];
|
|
391
|
+
return this.listeners = this.listeners.filter((listener) => {
|
|
392
|
+
if (!isMatched(listener))
|
|
393
|
+
return true;
|
|
394
|
+
removed.push(listener);
|
|
395
|
+
let execute = this.executors.get(listener);
|
|
396
|
+
return execute && (this.client.removeListener(listener.options.name, execute), this.executors.delete(listener)), false;
|
|
397
|
+
}), removed;
|
|
979
398
|
}
|
|
980
399
|
};
|
|
981
400
|
|
|
982
401
|
// src/BakitClient.ts
|
|
983
|
-
var
|
|
402
|
+
var BakitClient3 = class extends Client {
|
|
403
|
+
managers;
|
|
984
404
|
constructor(options) {
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
super(options);
|
|
989
|
-
ListenerRegistry["setClient"](this);
|
|
990
|
-
this.once(
|
|
991
|
-
Events.ClientReady,
|
|
992
|
-
(client) => void this.registerApplicationCommands(client)
|
|
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
|
|
405
|
+
super(options), this.managers = {
|
|
406
|
+
commands: new CommandManager(this),
|
|
407
|
+
listeners: new ListenerManager(this)
|
|
1010
408
|
};
|
|
1011
|
-
};
|
|
1012
|
-
async registerApplicationCommands(client) {
|
|
1013
|
-
const commands = CommandRegistry.constructors.map((c) => CommandRegistry.buildSlashCommand(c));
|
|
1014
|
-
await client.application.commands.set(commands);
|
|
1015
409
|
}
|
|
1016
|
-
async
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
}
|
|
1020
|
-
const context = new MessageContext(message);
|
|
1021
|
-
const resolver = ArgumentResolver.create(message);
|
|
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));
|
|
410
|
+
async start(token) {
|
|
411
|
+
let { commands, listeners } = this.managers;
|
|
412
|
+
return await Promise.all([commands.loadModules(), listeners.loadModules()]), await this.login(token);
|
|
1031
413
|
}
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
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));
|
|
414
|
+
/**
|
|
415
|
+
* Check if the client is connected to gateway successfully and finished initialization.
|
|
416
|
+
*/
|
|
417
|
+
isReady() {
|
|
418
|
+
return super.isReady();
|
|
1043
419
|
}
|
|
1044
|
-
|
|
1045
|
-
|
|
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
|
-
}
|
|
420
|
+
on(event, listener) {
|
|
421
|
+
return super.on(event, listener);
|
|
1056
422
|
}
|
|
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);
|
|
423
|
+
once(event, listener) {
|
|
424
|
+
return super.once(event, listener);
|
|
1070
425
|
}
|
|
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
|
-
}
|
|
426
|
+
off(event, listener) {
|
|
427
|
+
return super.off(event, listener);
|
|
1085
428
|
}
|
|
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;
|
|
429
|
+
removeAllListeners(event) {
|
|
430
|
+
return super.removeAllListeners(event);
|
|
1112
431
|
}
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
if (!mainHook) {
|
|
1116
|
-
return;
|
|
1117
|
-
}
|
|
1118
|
-
const newArgs = Arg.getMethodArguments(mainHook.method).map(
|
|
1119
|
-
(arg) => ArgumentResolver.resolveChatInput(context.source, arg)
|
|
1120
|
-
);
|
|
1121
|
-
const argValues = [...inheritedArgs, ...newArgs];
|
|
1122
|
-
await this.runHooks(context, instance, hooks, argValues);
|
|
1123
|
-
return argValues;
|
|
432
|
+
removeListener(event, listener) {
|
|
433
|
+
return super.removeListener(event, listener);
|
|
1124
434
|
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
const preHook = hooks["PRE" /* Pre */];
|
|
1128
|
-
const postHook = hooks["POST" /* Post */];
|
|
1129
|
-
const errorHook = hooks["ERROR" /* Error */];
|
|
1130
|
-
if (!mainHook) {
|
|
1131
|
-
return;
|
|
1132
|
-
}
|
|
1133
|
-
const execute = async (hook, error) => {
|
|
1134
|
-
if (!hook) {
|
|
1135
|
-
return;
|
|
1136
|
-
}
|
|
1137
|
-
if (hook.state === "ERROR" /* Error */) {
|
|
1138
|
-
await hook.method.call(instance, error, context, ...args);
|
|
1139
|
-
} else {
|
|
1140
|
-
await hook.method.call(instance, context, ...args);
|
|
1141
|
-
}
|
|
1142
|
-
};
|
|
1143
|
-
try {
|
|
1144
|
-
await execute(preHook);
|
|
1145
|
-
await execute(mainHook);
|
|
1146
|
-
await execute(postHook);
|
|
1147
|
-
} catch (error) {
|
|
1148
|
-
if (errorHook) {
|
|
1149
|
-
await execute(errorHook, error);
|
|
1150
|
-
} else {
|
|
1151
|
-
throw error;
|
|
1152
|
-
}
|
|
1153
|
-
}
|
|
435
|
+
emit(event, ...args) {
|
|
436
|
+
return super.emit(event, ...args);
|
|
1154
437
|
}
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
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
|
-
};
|
|
438
|
+
/**
|
|
439
|
+
* Override BakitClient output when using logger for security concern.
|
|
440
|
+
* @returns `BakitClient {}`
|
|
441
|
+
*/
|
|
442
|
+
[inspect.custom]() {
|
|
443
|
+
return `${this.constructor.name} {}`;
|
|
1182
444
|
}
|
|
1183
445
|
};
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
ListenerRegistry,
|
|
1204
|
-
MessageContext,
|
|
1205
|
-
RootCommandEntry,
|
|
1206
|
-
StateBox,
|
|
1207
|
-
SubcommandEntry,
|
|
1208
|
-
extractId
|
|
446
|
+
var ParamUserType = /* @__PURE__ */ ((ParamUserType2) => (ParamUserType2.Bot = "bot", ParamUserType2.Normal = "normal", ParamUserType2.Any = "any", ParamUserType2))(ParamUserType || {}), BaseParamSchema = z.object({
|
|
447
|
+
name: z.string(),
|
|
448
|
+
description: z.string().optional(),
|
|
449
|
+
required: z.boolean().default(true)
|
|
450
|
+
}), StringParamSchema = BaseParamSchema.extend({
|
|
451
|
+
maxLength: z.number().min(1).optional(),
|
|
452
|
+
minLength: z.number().min(1).optional()
|
|
453
|
+
}), NumberParamSchema = BaseParamSchema.extend({
|
|
454
|
+
maxValue: z.number().optional(),
|
|
455
|
+
minValue: z.number().optional()
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
// src/command/param/Params.ts
|
|
459
|
+
function createFactory(ctor) {
|
|
460
|
+
return (...args) => new ctor(...args);
|
|
461
|
+
}
|
|
462
|
+
var Params = {
|
|
463
|
+
string: createFactory(StringParam),
|
|
464
|
+
number: createFactory(NumberParam)
|
|
1209
465
|
};
|
|
466
|
+
|
|
467
|
+
export { BakitClient3 as BakitClient, BaseCommandContext, BaseParam, BaseParamSchema, ChatInputContext, Command, CommandManager, CommandOptionsSchema, Listener, ListenerManager, ListenerOptionsSchema, MessageContext, NumberParam, NumberParamSchema, ParamUserType, Params, ProjectConfigSchema, StringParam, StringParamSchema, defineCommand, defineConfig, defineListener, getConfig, loadConfig };
|