@guardbot/framework 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js ADDED
@@ -0,0 +1,699 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ AttachmentOption: () => import_discord7.SlashCommandAttachmentOption,
34
+ Autocompleter: () => Autocompleter,
35
+ BooleanOption: () => import_discord7.SlashCommandBooleanOption,
36
+ ChannelOption: () => import_discord7.SlashCommandChannelOption,
37
+ ContextCommand: () => ContextCommand,
38
+ FrameworkClient: () => FrameworkClient,
39
+ IntegerOption: () => import_discord7.SlashCommandIntegerOption,
40
+ Listener: () => Listener,
41
+ MentionableOption: () => import_discord7.SlashCommandMentionableOption,
42
+ MessageCommand: () => MessageCommand,
43
+ NumberOption: () => import_discord7.SlashCommandNumberOption,
44
+ RoleOption: () => import_discord7.SlashCommandRoleOption,
45
+ SlashCommand: () => SlashCommand,
46
+ SlashCommandOptionsBuilder: () => import_discord7.SlashCommandOptionsOnlyBuilder,
47
+ StringOption: () => import_discord7.SlashCommandStringOption,
48
+ SubcommandBuilder: () => import_discord7.SlashCommandSubcommandBuilder,
49
+ SubcommandGroupBuilder: () => import_discord7.SlashCommandSubcommandGroupBuilder
50
+ });
51
+ module.exports = __toCommonJS(index_exports);
52
+
53
+ // src/utils/errors.ts
54
+ var import_util = require("util");
55
+ var messages = {
56
+ NoOptions: () => `No options object was provided.`,
57
+ InvalidOption: (name) => `No "${name}" option was provided.`,
58
+ InvalidType: (name, expected, actual) => `Expected "${name}" to be of type "${expected}", but got "${actual}".`,
59
+ InvalidValue: (name, expected) => `Expected "${name}" to be any one of the listed values: ${expected.map((v) => `"${v}"`).join(" | ")}`,
60
+ InvalidValues: (name, expected) => `Expected "${name}" to contain only the listed values: ${expected.map((v) => `"${v}"`).join(" | ")}`,
61
+ UnknownComponent: (type, id) => `Encountered an error as there is no "${type}" loaded with the id "${id}".`,
62
+ ComponentLoadError: (type, error) => `Encountered an error while loading the "${type}":
63
+ ${(0, import_util.inspect)(error)}`,
64
+ ComponentAlreadyLoaded: (type, id) => `Encountered an error as a "${type}" with the id "${id}" is already loaded.`,
65
+ AppCommandRegister: (error, guildId) => `Encountered an error while registering commands ${guildId ? `to guild "${guildId}"` : ""}:
66
+ ${(0, import_util.inspect)(error)}`
67
+ };
68
+ var FrameworkError = class extends Error {
69
+ constructor(id, ...values) {
70
+ const message = messages[id](...values);
71
+ super(message);
72
+ this.name = `Error [ ${id} ]`;
73
+ }
74
+ };
75
+ var FrameworkTypeError = class extends TypeError {
76
+ constructor(id, ...values) {
77
+ const message = messages[id](...values);
78
+ super(message);
79
+ this.name = `TypeError [ ${id} ]`;
80
+ }
81
+ };
82
+
83
+ // src/autocomplete/Autocompleter.ts
84
+ function Autocompleter(options) {
85
+ if (!options) throw new FrameworkError("NoOptions");
86
+ if (typeof options !== "object") throw new FrameworkTypeError("InvalidType", "options", "object", typeof options);
87
+ if (!options.name || !options.name?.length) throw new FrameworkError("InvalidOption", "name");
88
+ if (typeof options.name !== "string") throw new FrameworkTypeError("InvalidType", "name", "string", typeof options.name);
89
+ if (!options.execute) throw new FrameworkError("InvalidOption", "execute");
90
+ if (typeof options.execute !== "function") throw new FrameworkTypeError("InvalidType", "execute", "function", typeof options.execute);
91
+ if (options.disabled !== void 0 && typeof options.disabled !== "boolean") throw new FrameworkTypeError("InvalidType", "disabled", "boolean", typeof options.disabled);
92
+ return {
93
+ id: options.name,
94
+ name: options.name,
95
+ disabled: options.disabled ?? false,
96
+ execute: options.execute
97
+ };
98
+ }
99
+
100
+ // src/commands/ContextCommand.ts
101
+ var import_discord2 = require("discord.js");
102
+
103
+ // src/utils/utils.ts
104
+ var import_discord = require("discord.js");
105
+ var import_path = __toESM(require("path"));
106
+ var import_fs = __toESM(require("fs"));
107
+ async function listFiles(dir) {
108
+ if (!import_fs.default.existsSync(dir)) return [];
109
+ const files = [];
110
+ const items = import_fs.default.readdirSync(dir, { withFileTypes: true });
111
+ for (const item of items) {
112
+ const fullPath = import_path.default.join(dir, item.name);
113
+ if (item.isDirectory()) files.push(...await listFiles(fullPath));
114
+ else if (item.name.endsWith(".js") || item.name.endsWith(".ts")) files.push(fullPath);
115
+ }
116
+ return files;
117
+ }
118
+ function isPermissionResolvable(option) {
119
+ try {
120
+ import_discord.PermissionsBitField.resolve(option);
121
+ return true;
122
+ } catch {
123
+ return false;
124
+ }
125
+ }
126
+ function unixTimestamp(date, type = "f") {
127
+ return `<t:${Math.floor(new Date(date).valueOf() / 1e3)}:${type}>`;
128
+ }
129
+ function resolveCommandType(type) {
130
+ return type === "Slash" ? import_discord.ApplicationCommandType.ChatInput : type === "ContextUser" ? import_discord.ApplicationCommandType.User : import_discord.ApplicationCommandType.Message;
131
+ }
132
+ function resolveCommandContexts(contexts) {
133
+ return contexts?.length ? contexts.map((c) => typeof c === "string" ? import_discord.InteractionContextType[c] : c) : [import_discord.InteractionContextType.Guild];
134
+ }
135
+ function resolveIntegrationTypes(types) {
136
+ return types?.length ? types.map((c) => typeof c === "string" ? import_discord.ApplicationIntegrationType[c] : c) : [import_discord.ApplicationIntegrationType.GuildInstall];
137
+ }
138
+
139
+ // src/commands/Command.ts
140
+ var CommandTypes = ["Slash", "Message", "ContextMessage", "ContextUser"];
141
+ function Command(options) {
142
+ if (!options) throw new FrameworkError("NoOptions");
143
+ if (typeof options !== "object") throw new FrameworkTypeError("InvalidType", "options", "object", typeof options);
144
+ if (!options.name || !options.name?.length) throw new FrameworkError("InvalidOption", "name");
145
+ if (typeof options.name !== "string") throw new FrameworkTypeError("InvalidType", "name", "string", typeof options.name);
146
+ if (!options.description || !options.description?.length) throw new FrameworkError("InvalidOption", "description");
147
+ if (typeof options.description !== "string") throw new FrameworkTypeError("InvalidType", "description", "string", typeof options.name);
148
+ if (!options.commandType) throw new FrameworkError("InvalidOption", "commandType");
149
+ if (!CommandTypes.includes(options.commandType)) throw new FrameworkError("InvalidValue", "commandType", CommandTypes);
150
+ if (options.memberPermissions !== void 0 && !isPermissionResolvable(options.memberPermissions)) throw new FrameworkTypeError("InvalidType", "memberPermissions", "PermissionResolvable", typeof options.memberPermissions);
151
+ if (options.clientPermissions !== void 0 && !isPermissionResolvable(options.clientPermissions)) throw new FrameworkTypeError("InvalidType", "clientPermissions", "PermissionResolvable", typeof options.clientPermissions);
152
+ if (options.cooldown && typeof options.cooldown !== "number") throw new FrameworkTypeError("InvalidType", "cooldown", "number", typeof options.cooldown);
153
+ if (options.disabled !== void 0 && typeof options.disabled !== "boolean") throw new FrameworkTypeError("InvalidType", "disabled", "boolean", typeof options.disabled);
154
+ return {
155
+ ...options,
156
+ id: `${options.commandType}:${options.name}`,
157
+ name: options.name,
158
+ description: options.description,
159
+ commandType: options.commandType,
160
+ memberPermissions: options.memberPermissions ?? void 0,
161
+ clientPermissions: options.clientPermissions ?? void 0,
162
+ cooldown: options.cooldown ?? void 0,
163
+ disabled: options.disabled ?? false
164
+ };
165
+ }
166
+
167
+ // src/commands/ContextCommand.ts
168
+ var CommandScope = ["default", "guild", "global"];
169
+ var CommandTypes2 = ["ContextUser", "ContextMessage"];
170
+ var CommandContexts = ["Guild", "BotDM", "PrivateChannel", 0, 1, 2];
171
+ var IntegrationTypes = ["GuildInstall", "UserInstall", 0, 1];
172
+ function ContextCommand(options) {
173
+ if (!options.commandType) throw new FrameworkError("InvalidOption", "commandType");
174
+ if (typeof options.commandScope !== "string" || !CommandTypes2.includes(options.commandType)) throw new FrameworkError("InvalidValue", "commandType", CommandTypes2);
175
+ if (!options.commandScope) throw new FrameworkError("InvalidOption", "commandScope");
176
+ if (typeof options.commandScope !== "string" || !CommandScope.includes(options.commandScope)) throw new FrameworkError("InvalidValue", "commandScope", CommandScope);
177
+ if (options.commandContexts && !Array.isArray(options.commandContexts)) throw new FrameworkTypeError("InvalidType", "commandContexts", "Array", typeof options.commandContexts);
178
+ if (options.commandContexts && options.commandContexts.some((c) => !CommandContexts.includes(c))) throw new FrameworkError("InvalidValues", "commandContexts", CommandContexts);
179
+ if (options.integrationTypes && !Array.isArray(options.integrationTypes)) throw new FrameworkTypeError("InvalidType", "integrationTypes", "Array", typeof options.integrationTypes);
180
+ if (options.integrationTypes && options.integrationTypes.some((c) => !IntegrationTypes.includes(c))) throw new FrameworkError("InvalidValues", "integrationTypes", IntegrationTypes);
181
+ if (!options.execute) throw new FrameworkError("InvalidOption", "execute");
182
+ if (typeof options.execute !== "function") throw new FrameworkTypeError("InvalidType", "execute", "function", typeof options.execute);
183
+ if (!options.commandContexts) options.commandContexts = [import_discord2.InteractionContextType.Guild];
184
+ if (!options.integrationTypes) options.integrationTypes = [import_discord2.ApplicationIntegrationType.GuildInstall];
185
+ return Command({
186
+ ...options,
187
+ commandType: options.commandType
188
+ });
189
+ }
190
+
191
+ // src/commands/MessageCommand.ts
192
+ var Contexts = ["BotDM", "Guild"];
193
+ function MessageCommand(options) {
194
+ if (options.aliases && !Array.isArray(options.aliases)) throw new FrameworkTypeError("InvalidType", "aliases", "array", typeof options.aliases);
195
+ if (options.usage && typeof options.usage !== "string") throw new FrameworkTypeError("InvalidType", "usage", "string", typeof options.usage);
196
+ if (options.contexts && !Array.isArray(options.contexts)) throw new FrameworkTypeError("InvalidType", "contexts", "array", typeof options.contexts);
197
+ if (options.contexts && options.contexts.some((c) => !Contexts.includes(c))) throw new FrameworkError("InvalidValues", "contexts", Contexts);
198
+ if (!options.execute) throw new FrameworkError("InvalidOption", "execute");
199
+ if (typeof options.execute !== "function") throw new FrameworkTypeError("InvalidType", "execute", "function", typeof options.execute);
200
+ if (options.devOnly !== void 0 && typeof options.devOnly !== "boolean") throw new FrameworkTypeError("InvalidType", "devOnly", "boolean", typeof options.devOnly);
201
+ if (!options.contexts) options.contexts = ["Guild"];
202
+ if (options.devOnly === void 0) options.devOnly = false;
203
+ return Command({
204
+ ...options,
205
+ commandType: "Message"
206
+ });
207
+ }
208
+
209
+ // src/commands/SlashCommand.ts
210
+ var import_discord3 = require("discord.js");
211
+ var CommandScope2 = ["default", "guild", "global"];
212
+ var CommandContexts2 = ["Guild", "BotDM", "PrivateChannel", 0, 1, 2];
213
+ var IntegrationTypes2 = ["GuildInstall", "UserInstall", 0, 1];
214
+ function SlashCommand(options) {
215
+ if (!options.commandScope) throw new FrameworkError("InvalidOption", "commandScope");
216
+ if (typeof options.commandScope !== "string" || !CommandScope2.includes(options.commandScope)) throw new FrameworkError("InvalidValue", "commandScope", CommandScope2);
217
+ if (options.commandContexts && !Array.isArray(options.commandContexts)) throw new FrameworkTypeError("InvalidType", "commandContexts", "Array", typeof options.commandContexts);
218
+ if (options.commandContexts && options.commandContexts.some((c) => !CommandContexts2.includes(c))) throw new FrameworkError("InvalidValues", "commandContexts", CommandContexts2);
219
+ if (options.integrationTypes && !Array.isArray(options.integrationTypes)) throw new FrameworkTypeError("InvalidType", "integrationTypes", "Array", typeof options.integrationTypes);
220
+ if (options.integrationTypes && options.integrationTypes.some((c) => !IntegrationTypes2.includes(c))) throw new FrameworkError("InvalidType", "integrationTypes", IntegrationTypes2);
221
+ if (!options.execute) throw new FrameworkError("InvalidOption", "execute");
222
+ if (typeof options.execute !== "function") throw new FrameworkTypeError("InvalidType", "execute", "function", typeof options.execute);
223
+ if (!options.commandContexts) options.commandContexts = [import_discord3.InteractionContextType.Guild];
224
+ if (!options.integrationTypes) options.integrationTypes = [import_discord3.ApplicationIntegrationType.GuildInstall];
225
+ return Command({
226
+ ...options,
227
+ commandType: "Slash"
228
+ });
229
+ }
230
+
231
+ // src/listeners/Listener.ts
232
+ function Listener(options) {
233
+ if (!options) throw new FrameworkError("NoOptions");
234
+ if (typeof options !== "object") throw new FrameworkTypeError("InvalidType", "options", "object", typeof options);
235
+ if (!options.name || !options.name?.length) throw new FrameworkError("InvalidOption", "name");
236
+ if (typeof options.name !== "string") throw new FrameworkTypeError("InvalidType", "name", "string", typeof options.name);
237
+ if (!options.execute) throw new FrameworkError("InvalidOption", "execute");
238
+ if (typeof options.execute !== "function") throw new FrameworkTypeError("InvalidType", "execute", "function", typeof options.execute);
239
+ if (options.once !== void 0 && typeof options.once !== "boolean") throw new FrameworkTypeError("InvalidType", "once", "boolean", typeof options.once);
240
+ if (options.disabled !== void 0 && typeof options.disabled !== "boolean") throw new FrameworkTypeError("InvalidType", "disabled", "boolean", typeof options.disabled);
241
+ return {
242
+ id: `Client:${options.name}`,
243
+ name: options.name,
244
+ once: options.once ?? false,
245
+ disabled: options.disabled ?? false,
246
+ execute: options.execute
247
+ };
248
+ }
249
+
250
+ // src/FrameworkClient.ts
251
+ var import_discord5 = require("discord.js");
252
+
253
+ // src/autocomplete/AutocompleteModule.ts
254
+ var import_node_url = require("url");
255
+ var import_events = __toESM(require("events"));
256
+ var import_path2 = __toESM(require("path"));
257
+ var AutocompleteModule = class extends import_events.default {
258
+ client;
259
+ constructor(client) {
260
+ super();
261
+ this.client = client;
262
+ this.client.on("interactionCreate", (interaction) => this._handleInteraction(interaction));
263
+ }
264
+ async load(filepath, reload = false) {
265
+ const completerModule = await import((0, import_node_url.pathToFileURL)(filepath).href);
266
+ const completer = completerModule.autocomplete ?? completerModule.default ?? completerModule;
267
+ if (typeof completer !== "object" || !completer.name || completer.disabled) return false;
268
+ if (!reload && this.client.autocomplete.has(completer.id)) throw new FrameworkError("ComponentAlreadyLoaded", "autocomplete", completer.id);
269
+ completer.filepath = filepath;
270
+ this.client.autocomplete.set(completer.id, completer);
271
+ return true;
272
+ }
273
+ async loadAll() {
274
+ const listenerDirs = import_path2.default.resolve(this.client.rootDir, "autocomplete");
275
+ const files = await listFiles(listenerDirs);
276
+ for (const file of files) {
277
+ try {
278
+ await this.load(import_path2.default.resolve(file));
279
+ } catch (error) {
280
+ this.client.emit("error", new FrameworkError("ComponentLoadError", "autocomplete", error));
281
+ }
282
+ }
283
+ }
284
+ reload(id) {
285
+ const completer = this.client.autocomplete.get(id);
286
+ if (!completer) throw new FrameworkError("UnknownComponent", "autocomplete", id);
287
+ this.unload(id, true);
288
+ this.load(completer.filepath, true);
289
+ }
290
+ unload(id, reload = false) {
291
+ if (!this.client.autocomplete.has(id)) throw new FrameworkError("UnknownComponent", "autocomplete", id);
292
+ const completer = this.client.autocomplete.get(id);
293
+ delete require.cache[completer.filepath];
294
+ if (!reload) this.client.autocomplete.delete(id);
295
+ }
296
+ async _handleInteraction(interaction) {
297
+ if (!interaction.isAutocomplete()) return;
298
+ const option = interaction.options.getFocused(true);
299
+ const command = this.client.commands.get(`Slash:${interaction.commandName}`);
300
+ const completer = this.client.autocomplete.get(option.name);
301
+ if (!option || !command || command.commandType !== "Slash") {
302
+ this.emit("unknown", interaction);
303
+ return;
304
+ }
305
+ if (completer && !completer.disabled) {
306
+ try {
307
+ this.emit("execute", { interaction, command, completer });
308
+ await completer.execute(this.client, interaction, command, option.value);
309
+ this.emit("success", { interaction, command, completer });
310
+ } catch (error) {
311
+ this.emit("success", { interaction, command, completer, error });
312
+ }
313
+ } else if (typeof command.autocomplete === "function" && !command.disabled) {
314
+ try {
315
+ this.emit("execute", { interaction, command, completer });
316
+ await command.autocomplete(this.client, interaction);
317
+ this.emit("success", { interaction, command, completer });
318
+ } catch (error) {
319
+ this.emit("success", { interaction, command, completer, error });
320
+ }
321
+ } else {
322
+ this.emit("unknown", interaction);
323
+ }
324
+ }
325
+ };
326
+
327
+ // src/listeners/ListenersModule.ts
328
+ var import_node_url2 = require("url");
329
+ var import_path3 = __toESM(require("path"));
330
+ var ListenerModule = class {
331
+ client;
332
+ constructor(client) {
333
+ this.client = client;
334
+ }
335
+ async load(filepath, reload = false) {
336
+ const listenerModule = await import((0, import_node_url2.pathToFileURL)(filepath).href);
337
+ const listener = listenerModule.listener ?? listenerModule.default ?? listenerModule;
338
+ if (typeof listener !== "object" || !listener.name || listener.disabled) return false;
339
+ if (!reload && this.client.events.has(listener.id)) throw new FrameworkError("ComponentAlreadyLoaded", "listener", listener.id);
340
+ listener.filepath = filepath;
341
+ listener._execute = (...args) => listener.execute(...args);
342
+ this.client[listener.once ? "once" : "on"](listener.name, listener._execute);
343
+ this.client.events.set(listener.id, listener);
344
+ return true;
345
+ }
346
+ async loadAll() {
347
+ const listenerDirs = import_path3.default.resolve(this.client.rootDir, "listeners");
348
+ const files = await listFiles(listenerDirs);
349
+ for (const file of files) {
350
+ try {
351
+ await this.load(import_path3.default.resolve(file));
352
+ } catch (error) {
353
+ this.client.emit("error", new FrameworkError("ComponentLoadError", "listener", error));
354
+ }
355
+ }
356
+ }
357
+ reload(id) {
358
+ if (!this.client.events.has(id)) throw new FrameworkError("UnknownComponent", "listener", id);
359
+ const listener = this.client.events.get(id);
360
+ this.unload(id, true);
361
+ this.load(listener.filepath, true);
362
+ }
363
+ unload(id, reload = false) {
364
+ if (!this.client.events.has(id)) throw new FrameworkError("UnknownComponent", "listener", id);
365
+ const listener = this.client.events.get(id);
366
+ if (listener._execute) this.client.off(listener.name, listener._execute);
367
+ delete require.cache[listener.filepath];
368
+ if (!reload) this.client.events.delete(id);
369
+ }
370
+ };
371
+
372
+ // src/commands/CommandsModule.ts
373
+ var import_discord4 = require("discord.js");
374
+ var import_node_url3 = require("url");
375
+ var import_events2 = __toESM(require("events"));
376
+ var import_path4 = __toESM(require("path"));
377
+ var CommandsModule = class extends import_events2.default {
378
+ client;
379
+ handler = {};
380
+ constructor(client) {
381
+ super();
382
+ this.client = client;
383
+ this.client.on("messageCreate", (message) => this._handleMessage(message));
384
+ this.client.on("interactionCreate", (interaction) => this._handleInteraction(interaction));
385
+ }
386
+ setHandler(key, callback) {
387
+ return this.handler[key] = callback;
388
+ }
389
+ setMessageInterceptor(callback) {
390
+ return this.handler.MessageCommandInterceptor = callback;
391
+ }
392
+ setInteractionInterceptor(callback) {
393
+ return this.handler.InteractionCommandInterceptor = callback;
394
+ }
395
+ async load(filepath, reload = false) {
396
+ const commandModule = await import((0, import_node_url3.pathToFileURL)(filepath).href);
397
+ const command = commandModule?.command ?? commandModule?.default?.default ?? commandModule?.default ?? commandModule;
398
+ if (typeof command !== "object" || !command.name || command.disabled) return false;
399
+ if (!reload && this.client.commands.has(command.id)) throw new FrameworkError("ComponentAlreadyLoaded", "command", command.id);
400
+ command.filepath = filepath;
401
+ this.client.commands.set(command.id, command);
402
+ if (command.commandType === "Message" && Array.isArray(command.aliases)) command.aliases.forEach((alias) => {
403
+ if (typeof alias === "string" && !this.client.aliases.get(alias)) this.client.aliases.set(alias, command.id);
404
+ });
405
+ return true;
406
+ }
407
+ async loadAll() {
408
+ const commandsDir = import_path4.default.resolve(this.client.rootDir, "commands");
409
+ const files = await listFiles(commandsDir);
410
+ for (const file of files) {
411
+ try {
412
+ await this.load(import_path4.default.resolve(file));
413
+ } catch (error) {
414
+ this.client.emit("error", new FrameworkError("ComponentLoadError", "commands", error));
415
+ }
416
+ }
417
+ }
418
+ reload(id) {
419
+ if (!this.client.commands.has(id)) throw new FrameworkError("UnknownComponent", "commands", id);
420
+ const command = this.client.commands.get(id);
421
+ this.unload(id, true);
422
+ this.load(command.filepath, true);
423
+ }
424
+ unload(id, reload = false) {
425
+ if (!this.client.commands.has(id)) throw new FrameworkError("UnknownComponent", "commands", id);
426
+ const command = this.client.commands.get(id);
427
+ delete require.cache[command.filepath];
428
+ if (!reload) this.client.commands.delete(id);
429
+ }
430
+ async registerOnStart(guildIds, commands) {
431
+ for (const guildId of guildIds) {
432
+ try {
433
+ await this.publishGuild(guildId, commands);
434
+ } catch (error) {
435
+ this.client.emit("error", new FrameworkError("AppCommandRegister", error, guildId));
436
+ }
437
+ }
438
+ }
439
+ async publishGlobal(commands) {
440
+ if (!this.client.application) return false;
441
+ const commandsToSet = (commands ?? this.client.commands).filter((c) => c.commandType !== "Message" && c.commandScope !== "guild" && !c.disabled).map((c) => this._getCommandData(c));
442
+ return this.client.application.commands.set(commandsToSet);
443
+ }
444
+ async publishGuild(guildId, commands) {
445
+ const commandsToSet = (commands ?? this.client.commands).filter((c) => c.commandType !== "Message" && c.commandScope !== "global" && !c.disabled).map((c) => this._getCommandData(c));
446
+ const guild = await this.client.guilds.fetch({ guild: guildId, force: false });
447
+ if (guild) guild.commands.set(commandsToSet);
448
+ }
449
+ async _handleMessage(message) {
450
+ if (!message.content?.length || message.author.bot) return;
451
+ if (this.handler.MessageCommandInterceptor) {
452
+ const shouldContinue = await this.handler.MessageCommandInterceptor(message);
453
+ if (!shouldContinue) return;
454
+ }
455
+ const prefixRegex = new RegExp(`^(<@!?${message.client.user.id}>${this.client.prefix ? `|${this.client.prefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}` : ""})\\s*`);
456
+ if (!prefixRegex.test(message.content.toLowerCase())) return;
457
+ const matchedPrefix = message.content.toLowerCase().match(prefixRegex)?.[1];
458
+ if (!matchedPrefix) return;
459
+ const args = (message.content || "").slice(matchedPrefix.length).trim().split(/ +/);
460
+ const commandName = args.shift()?.toLowerCase();
461
+ if (!commandName) return;
462
+ const commandId = `Message:${commandName}`;
463
+ const command = this.client.commands.get(commandId) || this.client.commands.get(this.client.aliases.get(commandId) || "");
464
+ if (!command || command.commandType !== "Message" || command.disabled || command.devOnly && !this.client.developers.includes(message.author.id)) return;
465
+ if (!message.inGuild() && !command.contexts.includes("BotDM") || message.inGuild() && !command.contexts.includes("Guild")) return;
466
+ if (message.inGuild() && command.memberPermissions) {
467
+ const executor = await message.guild.members.fetch({ user: message.author.id, force: false });
468
+ const memberPerms = executor.permissionsIn(message.channel) ?? executor.permissions;
469
+ if (!memberPerms.has(command.memberPermissions)) {
470
+ const missingPermsArray = memberPerms.missing(command.memberPermissions);
471
+ if (typeof this.handler.onMemberPermissions === "function") return this.handler.onMemberPermissions(message, command, missingPermsArray);
472
+ else return await message.reply({ content: "\u274C You don't have the required permission(s) to use this command." }).then((m) => {
473
+ setTimeout(() => m.delete().catch((e) => null), 1e4);
474
+ }).catch(() => null);
475
+ }
476
+ }
477
+ if (message.inGuild() && command.clientPermissions) {
478
+ const clientMember = await message.guild.members.fetchMe({ force: false });
479
+ const clientPerms = clientMember.permissionsIn(message.channel) ?? clientMember.permissions;
480
+ if (!clientMember.permissions.has(command.clientPermissions)) {
481
+ const missingPermsArray = clientPerms.missing(command.clientPermissions);
482
+ if (typeof this.handler.onClientPermissions === "function") return this.handler.onClientPermissions(message, command, missingPermsArray);
483
+ else return await message.reply({ content: `\u274C ${clientMember.displayName} requires ${missingPermsArray.map((p) => `\` ${p.replace(/([A-Z])/g, (_, l, i) => i === 0 ? l : ` ${l}`)} \``).join(" ")} permission(s) to run this command.` }).then((m) => {
484
+ setTimeout(() => m.delete().catch((e) => null), 1e4);
485
+ }).catch(() => null);
486
+ }
487
+ }
488
+ if (command.cooldown && command.cooldown > 1e3) {
489
+ if (!this.client.cooldowns.has(commandId)) this.client.cooldowns.set(commandId, new import_discord4.Collection());
490
+ const commandCooldowns = this.client.cooldowns.get(commandId);
491
+ if (commandCooldowns) {
492
+ if (commandCooldowns.has(message.author.id)) {
493
+ const expirationDate = new Date((commandCooldowns.get(message.author.id) || 0) + command.cooldown);
494
+ if (expirationDate.valueOf() - Date.now() > 1e3) {
495
+ if (typeof this.handler.onCooldown === "function") return this.handler.onCooldown(message, command, expirationDate);
496
+ else return await message.reply({ content: `\u274C Slow down and try the Command Again **${unixTimestamp(new Date(expirationDate), "R")}**.` }).then((m) => {
497
+ setTimeout(() => m.delete().catch((e) => null), expirationDate.valueOf() - Date.now());
498
+ });
499
+ }
500
+ }
501
+ commandCooldowns.set(message.author.id, (/* @__PURE__ */ new Date()).valueOf());
502
+ setTimeout(() => commandCooldowns.delete(message.author.id), command.cooldown);
503
+ }
504
+ }
505
+ try {
506
+ this.emit("execute", { context: message, command });
507
+ await command.execute(this.client, message, args);
508
+ this.emit("success", { context: message, command });
509
+ } catch (error) {
510
+ this.emit("error", { context: message, command, error });
511
+ }
512
+ }
513
+ async _handleInteraction(interaction) {
514
+ if (!interaction.isChatInputCommand() && !interaction.isContextMenuCommand()) return;
515
+ if (this.handler.InteractionCommandInterceptor) {
516
+ const shouldContinue = await this.handler.InteractionCommandInterceptor(interaction);
517
+ if (!shouldContinue) return;
518
+ }
519
+ const commandId = `${this._getCommandId(interaction)}:${interaction.commandName}`;
520
+ const command = this.client.commands.get(commandId);
521
+ if (!command || command.disabled || command.commandType === "Message") {
522
+ this.emit("unknown", interaction);
523
+ return;
524
+ }
525
+ if (interaction.guild && interaction.channel && !interaction.channel.isDMBased() && command.clientPermissions) {
526
+ const clientMember = await interaction.guild.members.fetchMe({ force: false });
527
+ const clientPerms = interaction.channel.isSendable() ? clientMember.permissionsIn(interaction.channel) : clientMember.permissions;
528
+ if (!clientPerms.has(command.clientPermissions)) {
529
+ const missingPermsArray = clientPerms.missing(command.clientPermissions);
530
+ if (typeof this.handler.onClientPermissions === "function") return this.handler.onClientPermissions(interaction, command, missingPermsArray);
531
+ else return await interaction.reply({ content: `\u274C ${clientMember.displayName} requires ${missingPermsArray.map((p) => `\` ${p.replace(/([A-Z])/g, (_, l, i) => i === 0 ? l : ` ${l}`)} \``).join(" ")} permission(s) to run this command.`, flags: import_discord4.MessageFlags.Ephemeral });
532
+ }
533
+ }
534
+ if (command.cooldown && command.cooldown > 1e3) {
535
+ if (!this.client.cooldowns.has(commandId)) this.client.cooldowns.set(commandId, new import_discord4.Collection());
536
+ const commandCooldowns = this.client.cooldowns.get(commandId);
537
+ if (commandCooldowns) {
538
+ if (commandCooldowns.has(interaction.user.id)) {
539
+ const expirationDate = new Date((commandCooldowns.get(interaction.user.id) || 0) + command.cooldown);
540
+ if (expirationDate.valueOf() - Date.now() > 1e3) {
541
+ if (typeof this.handler.onCooldown === "function") return this.handler.onCooldown(interaction, command, expirationDate);
542
+ else return await interaction.reply({ content: `\u274C Slow down and try the Command Again **${unixTimestamp(new Date(expirationDate), "R")}**.`, flags: import_discord4.MessageFlags.Ephemeral });
543
+ }
544
+ }
545
+ commandCooldowns.set(interaction.user.id, (/* @__PURE__ */ new Date()).valueOf());
546
+ setTimeout(() => commandCooldowns.delete(interaction.user.id), command.cooldown);
547
+ }
548
+ }
549
+ try {
550
+ this.emit("execute", { context: interaction, command });
551
+ await command.execute(this.client, interaction);
552
+ this.emit("success", { context: interaction, command });
553
+ } catch (error) {
554
+ this.emit("error", { context: interaction, command, error });
555
+ }
556
+ }
557
+ _getCommandId(interaction) {
558
+ if (interaction.isChatInputCommand()) return "Slash";
559
+ else if (interaction.isUserContextMenuCommand()) return "ContextUser";
560
+ else if (interaction.isMessageContextMenuCommand()) return "ContextMessage";
561
+ return "unknown";
562
+ }
563
+ _getCommandData(command) {
564
+ return {
565
+ name: command.name,
566
+ description: command.description,
567
+ type: resolveCommandType(command.commandType),
568
+ defaultMemberPermissions: command.memberPermissions ?? null,
569
+ contexts: resolveCommandContexts(command.commandContexts),
570
+ integrationTypes: resolveIntegrationTypes(command.integrationTypes),
571
+ nameLocalizations: command.nameLocalizations,
572
+ descriptionLocalizations: command.descriptionLocalizations,
573
+ ...command.commandType === "Slash" ? { options: command.options ?? [] } : {}
574
+ };
575
+ }
576
+ };
577
+
578
+ // src/FrameworkClient.ts
579
+ var import_fs2 = __toESM(require("fs"));
580
+ var FrameworkClient = class extends import_discord5.Client {
581
+ rootDir;
582
+ prefix;
583
+ developers;
584
+ constructor(frameworkOptions) {
585
+ super(frameworkOptions.clientOptions);
586
+ this.prefix = frameworkOptions.prefix ?? "!";
587
+ this.rootDir = frameworkOptions.rootDir ?? (import_fs2.default.existsSync("./src") ? "./src" : "./");
588
+ this.developers = frameworkOptions.developers || [];
589
+ this.autocomplete = new import_discord5.Collection();
590
+ this.events = new import_discord5.Collection();
591
+ this.aliases = new import_discord5.Collection();
592
+ this.commands = new import_discord5.Collection();
593
+ this.cooldowns = new import_discord5.Collection();
594
+ this.autocompleteModule = new AutocompleteModule(this);
595
+ this.listenerModule = new ListenerModule(this);
596
+ this.commandsModule = new CommandsModule(this);
597
+ this.on("interactionCreate", (interaction) => {
598
+ if (interaction.isAnySelectMenu()) return this.emit("selectMenuInteraction", interaction);
599
+ else if (interaction.isModalSubmit()) return this.emit("modalSubmitInteraction", interaction);
600
+ else if (interaction.isButton()) return this.emit("buttonInteraction", interaction);
601
+ });
602
+ this.once("clientReady", async () => {
603
+ if (frameworkOptions.registerOnStart && frameworkOptions.guildsToRegister?.length) {
604
+ await this.commandsModule.registerOnStart(frameworkOptions.guildsToRegister);
605
+ }
606
+ });
607
+ }
608
+ async start(token) {
609
+ await this.autocompleteModule.loadAll();
610
+ await this.commandsModule.loadAll();
611
+ await this.listenerModule.loadAll();
612
+ await this.login(token);
613
+ }
614
+ };
615
+
616
+ // src/extensions/Message.ts
617
+ var import_discord6 = require("discord.js");
618
+ function prefix() {
619
+ return this.client.prefix;
620
+ }
621
+ function isDeveloper() {
622
+ return this.client.developers.includes(this.author.id);
623
+ }
624
+ function awaitMemberResponse(options = {}) {
625
+ return new Promise((resolve, reject) => {
626
+ if (!this.channel) {
627
+ return reject(new Error("Channel not available for this message."));
628
+ }
629
+ const collector = new import_discord6.MessageCollector(this.channel, {
630
+ time: 6e4,
631
+ filter: (m) => m.author.id === this.author.id && (m.content || "").length > 0,
632
+ ...options,
633
+ max: 1
634
+ });
635
+ collector.on("end", (messages2, reason) => {
636
+ const message = messages2.first();
637
+ if (message) {
638
+ if (options.deleteMessage) message.delete().catch(() => null);
639
+ resolve(message);
640
+ } else {
641
+ reject(new Error(reason));
642
+ }
643
+ });
644
+ });
645
+ }
646
+ function createModalSubmitCollector(options = {}) {
647
+ return new import_discord6.InteractionCollector(this.client, {
648
+ ...options,
649
+ interactionType: import_discord6.InteractionType.ModalSubmit,
650
+ message: this
651
+ });
652
+ }
653
+ function awaitModalSubmitComponent(options = {}) {
654
+ return new Promise((resolve, reject) => {
655
+ const collector = new import_discord6.InteractionCollector(this.client, {
656
+ time: 6e4,
657
+ filter: (i) => i.user.id === this.author.id,
658
+ ...options,
659
+ interactionType: import_discord6.InteractionType.ModalSubmit,
660
+ message: this,
661
+ max: 1
662
+ });
663
+ collector.on("end", (interactions, reason) => {
664
+ const interaction = interactions.first();
665
+ if (interaction) resolve(interaction);
666
+ else reject(new Error(reason));
667
+ });
668
+ });
669
+ }
670
+ Object.defineProperties(import_discord6.Message.prototype, {
671
+ prefix: { get: prefix, configurable: true },
672
+ isDeveloper: { value: isDeveloper, writable: true, configurable: true },
673
+ awaitMemberResponse: { value: awaitMemberResponse, writable: true, configurable: true },
674
+ createModalSubmitCollector: { value: createModalSubmitCollector, writable: true, configurable: true },
675
+ awaitModalSubmitComponent: { value: awaitModalSubmitComponent, writable: true, configurable: true }
676
+ });
677
+
678
+ // src/Builders.ts
679
+ var import_discord7 = require("discord.js");
680
+ // Annotate the CommonJS export names for ESM import in node:
681
+ 0 && (module.exports = {
682
+ AttachmentOption,
683
+ Autocompleter,
684
+ BooleanOption,
685
+ ChannelOption,
686
+ ContextCommand,
687
+ FrameworkClient,
688
+ IntegerOption,
689
+ Listener,
690
+ MentionableOption,
691
+ MessageCommand,
692
+ NumberOption,
693
+ RoleOption,
694
+ SlashCommand,
695
+ SlashCommandOptionsBuilder,
696
+ StringOption,
697
+ SubcommandBuilder,
698
+ SubcommandGroupBuilder
699
+ });