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/dist/index.js CHANGED
@@ -1,402 +1,213 @@
1
- // src/index.ts
2
- import "reflect-metadata";
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/BakitClient.ts
5
- import {
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);
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/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
- }
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
- case "user" /* User */:
221
- case "member" /* Member */: {
222
- break;
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 parts.join(", ");
125
+ return current.length > 0 && args.push(current), args;
226
126
  }
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}`;
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/command/CommandRegistry.ts
247
- var CommandRegistry = class _CommandRegistry {
248
- static constructors = new Collection2();
249
- static instances = new Collection2();
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
- * Add a command to the registry.
252
- * @param constructor The command class you want to add.
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
- static add(constructor) {
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
- * Load and add all commands which matched provided glob pattern to the registry.
265
- * @param pattern glob pattern to load.
266
- * @param parallel load all matched results in parallel, enabled by default.
267
- * @returns All loaded command constructors.
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
- static async load(pattern, parallel = true) {
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
- * Build a command into application command data.
288
- * @param constructor The command class you want to build.
289
- * @returns a REST JSON version of the application command data.
160
+ * The path to the main project source directory.
161
+ *
162
+ * @defaultvalue `src`
290
163
  */
291
- static buildSlashCommand(constructor) {
292
- const root = Command.getRoot(constructor);
293
- if (!root) {
294
- throw new Error(`No root found for "${constructor.name}"`);
295
- }
296
- const { options } = root;
297
- const builder = new SlashCommandBuilder().setName(options.name).setDescription(options.description).setNSFW(Boolean(options.nsfw));
298
- const args = this.getMainHookArguments(root);
299
- if (root.children.size) {
300
- this.buildSlashCommandSubcommands(builder, root, args);
301
- } else {
302
- this.buildSlashCommandOptions(builder, args);
303
- }
304
- return builder.toJSON();
305
- }
306
- static getMainHookArguments(entry) {
307
- const { hooks } = entry;
308
- const mainHook = hooks["MAIN" /* Main */];
309
- return mainHook ? Arg.getMethodArguments(mainHook.method) : [];
310
- }
311
- static buildSlashCommandSubcommands(parent, entry, inheritedArgs) {
312
- const { children } = entry;
313
- for (const child of children.values()) {
314
- if (child instanceof CommandGroupEntry && parent instanceof SlashCommandBuilder) {
315
- const { options } = child;
316
- const group = new SlashCommandSubcommandGroupBuilder().setName(options.name).setDescription(options.description);
317
- this.buildSlashCommandSubcommands(group, child, [
318
- ...inheritedArgs,
319
- ...this.getMainHookArguments(child)
320
- ]);
321
- parent.addSubcommandGroup(group);
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
- }
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
- 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
- }
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/Context.ts
394
- import {
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 Boolean(this.guildId);
232
+ return !!this.guildId;
419
233
  }
420
234
  inCachedGuild() {
421
- if (this.isChatInput()) {
235
+ if (this.isChatInput())
422
236
  return this.source.inCachedGuild();
423
- } else if (this.isMessage()) {
237
+ if (this.isMessage())
424
238
  return this.source.inGuild();
425
- } else {
426
- throw new Error("Invalid source");
427
- }
239
+ throw new Error("Invalid source");
428
240
  }
429
- get author() {
430
- if (this.isChatInput()) {
241
+ get user() {
242
+ if (this.isChatInput())
431
243
  return this.source.user;
432
- } else if (this.isMessage()) {
244
+ if (this.isMessage())
433
245
  return this.source.author;
434
- } else {
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
- if (typeof options === "string") {
448
- options = { content: options };
449
- }
450
- const sendOptions = {
256
+ typeof options == "string" && (options = { content: options });
257
+ let sendOptions = {
451
258
  ...options,
452
259
  withResponse: true
453
260
  };
454
- if (this.source.deferred || this.source.replied) {
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
- const { channel } = this;
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
- // src/utils/user.ts
472
- function extractId(value) {
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
- const numericMatch = value.match(/^(\d{17,19})$/);
478
- if (numericMatch) {
479
- return numericMatch[1];
480
- }
481
- return null;
482
- }
483
-
484
- // src/errors/CommandSyntaxError.ts
485
- var CommandSyntaxErrorType = /* @__PURE__ */ ((CommandSyntaxErrorType2) => {
486
- CommandSyntaxErrorType2["MissingRequireArgument"] = "MISSING_REQUIRE_ARGUMENT";
487
- CommandSyntaxErrorType2["InvalidArgument"] = "INVALID_ARGUMENT";
488
- CommandSyntaxErrorType2["InvalidVariadicArgumentValue"] = "INVALID_VARIADIC_ARGUMENT_VALUE";
489
- return CommandSyntaxErrorType2;
490
- })(CommandSyntaxErrorType || {});
491
- var CommandSyntaxError = class extends Error {
492
- arg;
493
- type;
494
- expected;
495
- received;
496
- constructor(options) {
497
- let message;
498
- const { arg, type, received } = options;
499
- const expected = Arg.describeArgumentExpectation(arg);
500
- switch (type) {
501
- case "MISSING_REQUIRE_ARGUMENT" /* MissingRequireArgument */: {
502
- message = [`Missing required argument "${arg.name}"`, `> Expected: ${expected}`].join("\n");
503
- break;
504
- }
505
- case "INVALID_ARGUMENT" /* InvalidArgument */: {
506
- message = [
507
- `Invalid value received for argument "${arg.name}"`,
508
- `> Expected: ${expected}`,
509
- `> Received: ${String(received)}`
510
- ].join("\n");
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
- case "INVALID_VARIADIC_ARGUMENT_VALUE" /* InvalidVariadicArgumentValue */: {
514
- message = [
515
- `Invalid value received for variadic argument "${arg.name}"`,
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
- default: {
522
- message = "Unknown error";
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
- get name() {
534
- return `CommandSyntaxError[${this.type}]`;
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/command/argument/ArgumentResolver.ts
539
- var ArgumentResolver = class _ArgumentResolver {
540
- constructor(options) {
541
- this.options = options;
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
- * Get the first value as the command trigger.
413
+ * Helper to normalize string inputs into an options object.
546
414
  */
547
- get trigger() {
548
- return this.options.values[0];
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
- * Get amount of specified argument values.
438
+ * Sets the minimum allowed length for this string.
439
+ * Pass `null` to remove this constraint.
552
440
  */
553
- get specifiedAmount() {
554
- return this.options.values.length - this.options.startAt;
441
+ min(length) {
442
+ return this.setOption("minLength", length);
555
443
  }
556
444
  /**
557
- * Get parsed raw values from content.
445
+ * Sets the maximum allowed length for this string.
446
+ * Pass `null` to remove this constraint.
558
447
  */
559
- get values() {
560
- return [...this.options.values];
448
+ max(length) {
449
+ return this.setOption("maxLength", length);
561
450
  }
562
- get client() {
563
- return this.options.message.client;
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
- async resolve(args) {
589
- const child = new _ArgumentResolver({
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
- 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
- }
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
- 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
- }
468
+ resolveChatInput(context) {
469
+ let { name, required } = this.options;
470
+ return context.source.options.getString(name, required);
706
471
  }
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;
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
- matchIntegerValue(arg, value) {
719
- const intVal = parseInt(value, 10);
720
- if (isNaN(intVal)) {
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;
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
- matchNumberValue(arg, value) {
732
- const numVal = parseFloat(value);
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;
486
+ }, UserParam = class extends BaseParam {
487
+ constructor(options) {
488
+ super(BaseParam.getOptions(options), UserParamSchema);
743
489
  }
744
- matchStringValue(arg, value) {
745
- if (arg.minLength !== void 0 && value.length < arg.minLength) {
746
- return null;
747
- }
748
- if (arg.maxLength !== void 0 && value.length > arg.maxLength) {
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 value;
497
+ let { users } = context.client;
498
+ return await users.fetch(id).catch(() => null);
752
499
  }
753
- static resolveChatInput(interaction, arg) {
754
- switch (arg.type) {
755
- case "string" /* String */:
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
- // src/libs/StateBox.ts
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;
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
- static run(fn, store = {}) {
784
- return this.storage.run(store, fn);
534
+ async handleSyntaxError(context, error, _args) {
535
+ error instanceof BakitError && await context.send(error.message);
785
536
  }
786
- static wrap(fn) {
787
- const currentStore = this.storage.getStore();
788
- if (!currentStore) {
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
- // src/listener/ListenerEntry.ts
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
- // src/listener/Listener.ts
823
- var ListenerAPI;
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
- ListenerAPI2.use = use;
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);
566
+ };
567
+ function defineCommand(options) {
568
+ return new Command(options);
840
569
  }
841
- var Listener = Object.assign(ListenerFactory, ListenerAPI);
842
570
 
843
- // src/listener/ListenerRegistry.ts
844
- import glob2 from "tiny-glob";
845
- import { pathToFileURL as pathToFileURL2 } from "url";
846
- var ListenerRegistry = class {
847
- static client;
848
- static constructors = /* @__PURE__ */ new Set();
849
- static instances = /* @__PURE__ */ new WeakMap();
850
- static executors = /* @__PURE__ */ new WeakMap();
851
- /**
852
- * Add and register a listener to the registry.
853
- * If `options.emitter` is not provided, the registry will use the base `client` by default.
854
- * @param constructor The listener class you want to add.
855
- */
856
- static add(constructor) {
857
- const entry = Listener.getEntry(constructor);
858
- if (!entry) {
859
- throw new Error(`No entry found for "${constructor.name}"`);
860
- }
861
- const { options } = entry;
862
- if (!options.emitter) {
863
- if (!this.client) {
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
- options.emitter = this.client;
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
- * Remove and unregister a listener from the registry.
879
- * @param constructor The listener class you want to remove.
880
- * @returns `boolean`, returns `true` if the listener is removed successfully.
881
- */
882
- static remove(constructor) {
883
- const entry = Listener.getEntry(constructor);
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
- const { name, emitter } = entry.options;
898
- emitter?.removeListener(name, executor);
899
- this.executors.delete(instance);
900
- return true;
604
+ this.commands.set(name, command);
901
605
  }
902
- /**
903
- * Remove and unregister all listeners from the registry.
904
- * @returns Amount of removed listeners.
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
- * Set base client for the registry to fallback as default emitter. This should be used only by BakitClient and stay untouched.
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
- static createExecutor(constructor, instance) {
923
- const entry = Listener.getEntry(constructor);
924
- if (!entry) {
925
- throw new Error("Missing listener entry");
926
- }
927
- const { hooks } = entry;
928
- return async function(...args) {
929
- const mainHook = hooks["MAIN" /* Main */];
930
- const preHook = hooks["PRE" /* Pre */];
931
- const postHook = hooks["POST" /* Post */];
932
- const errorHook = hooks["ERROR" /* Error */];
933
- if (!mainHook) {
934
- return;
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
- if (preHook) {
938
- await preHook.method.call(instance, ...args);
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
- await mainHook.method.call(instance, ...args);
941
- if (postHook) {
942
- await postHook.method.call(instance, ...args);
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
- if (errorHook) {
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
- * Load and add all listeners which matched provided glob pattern to the registry.
959
- * @param pattern glob pattern to load.
960
- * @param parallel load all matched results in parallel, enabled by default.
961
- * @returns All loaded listener constructors.
962
- */
963
- static async load(pattern, parallel = true) {
964
- const files = await glob2(pattern);
965
- const loaders = files.map(async (file) => {
966
- const fileURL = pathToFileURL2(file).toString();
967
- const { default: constructor } = await import(fileURL);
968
- this.add(constructor);
969
- return constructor;
970
- });
971
- if (parallel) {
972
- return Promise.all(loaders);
973
- }
974
- const result = [];
975
- for (const loader of loaders) {
976
- result.push(await loader);
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 BakitClient = class _BakitClient extends Client {
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
- 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
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
- async handleMessage(message) {
1017
- if (message.author.bot) {
1018
- return;
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));
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
- async handleInteraction(interaction) {
1033
- if (!interaction.isChatInputCommand()) {
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
- async handleMessageHooks(context, instance, resolver) {
1058
- if (!resolver) {
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
- async handleChildMessageHooks(context, parent, instance, resolver, skip = 1) {
1072
- if (!resolver) {
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
- async runMessageHooks(context, instance, hooks, resolver) {
1087
- const mainHook = hooks["MAIN" /* Main */];
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
- async runChatInputHooks(context, instance, hooks, inheritedArgs) {
1114
- const mainHook = hooks["MAIN" /* Main */];
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;
1124
- }
1125
- async runHooks(context, instance, hooks, args) {
1126
- const mainHook = hooks["MAIN" /* Main */];
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
- };
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 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
- }
819
+ let content = await readFile(fullPath, "utf-8");
820
+ return JSON.parse(content);
821
+ } catch {
822
+ return null;
1153
823
  }
1154
824
  }
1155
- getChatInputTargetHooks(interaction, instance) {
1156
- const subcommandName = interaction.options.getSubcommand(false);
1157
- const groupName = interaction.options.getSubcommandGroup(false);
1158
- const root = Command.getRoot(instance.constructor);
1159
- if (!root) {
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
- export {
1185
- Arg,
1186
- ArgumentType,
1187
- BakitClient,
1188
- BaseCommandEntry,
1189
- BaseCommandGroupEntry,
1190
- BaseContext,
1191
- ChatInputContext,
1192
- Command,
1193
- CommandAPI,
1194
- CommandFactory,
1195
- CommandGroupEntry,
1196
- CommandRegistry,
1197
- CommandSyntaxError,
1198
- CommandSyntaxErrorType,
1199
- Listener,
1200
- ListenerAPI,
1201
- ListenerEntry,
1202
- ListenerFactory,
1203
- ListenerRegistry,
1204
- MessageContext,
1205
- RootCommandEntry,
1206
- StateBox,
1207
- SubcommandEntry,
1208
- extractId
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 };