vimcord 1.0.49 → 1.0.51

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.cjs CHANGED
@@ -82,6 +82,7 @@ __export(index_exports, {
82
82
  createMongoPlugin: () => createMongoPlugin,
83
83
  createMongoSchema: () => createMongoSchema,
84
84
  createPrefixCommandConfig: () => createPrefixCommandConfig,
85
+ createRandomId: () => createRandomId,
85
86
  createSlashCommandConfig: () => createSlashCommandConfig,
86
87
  createStaffConfig: () => createStaffConfig,
87
88
  createToolsConfig: () => createToolsConfig,
@@ -316,6 +317,7 @@ var BaseCommandBuilder = class {
316
317
  async run(client, ...args) {
317
318
  const config = this.resolveConfig(client);
318
319
  const ctx = this.extractContext(args);
320
+ let cancel = false;
319
321
  try {
320
322
  if (!config.enabled) {
321
323
  return await config.onUsedWhenDisabled?.(...args);
@@ -330,11 +332,16 @@ var BaseCommandBuilder = class {
330
332
  if (!await this.checkConditions(config, ...args)) {
331
333
  return await config.onConditionsNotMet?.(...args);
332
334
  }
333
- await config.beforeExecute?.(...args);
335
+ await config.beforeExecute?.({ cancel: () => cancel = true }, ...args);
336
+ if (cancel) return;
334
337
  if (config.logExecution !== false) {
335
- const cmdName = this.options.name || this.builder?.name || "Unknown";
338
+ const optionsWithName = this.options;
339
+ const builderWithName = this;
340
+ const cmdName = optionsWithName.name ?? builderWithName.builder?.name ?? "Unknown";
336
341
  const location = ctx.guild ? `${ctx.guild.name} (${ctx.guild.id})` : "Direct Messages";
337
- client.logger.commandExecuted(cmdName, ctx.user.username, location);
342
+ if (client.logger) {
343
+ client.logger.commandExecuted(cmdName, ctx.user.username, location);
344
+ }
338
345
  }
339
346
  const result = await config.execute?.(...args);
340
347
  await config.afterExecute?.(result, ...args);
@@ -562,9 +569,7 @@ var Logger = class {
562
569
  extend(extras) {
563
570
  for (const [key, fn] of Object.entries(extras)) {
564
571
  if (typeof fn === "function") {
565
- this[key] = function(...args) {
566
- return fn.call(this, ...args);
567
- };
572
+ this[key] = (...args) => fn.call(this, ...args);
568
573
  }
569
574
  }
570
575
  return this;
@@ -934,12 +939,14 @@ var contextCommandHandler = new EventBuilder({
934
939
  if (!command) {
935
940
  const content = `**${interaction.commandName}** is not a registered context command.`;
936
941
  if (interaction.replied || interaction.deferred) {
937
- return interaction.followUp({ content, flags: "Ephemeral" });
942
+ await interaction.followUp({ content, flags: "Ephemeral" });
943
+ } else {
944
+ await interaction.reply({ content, flags: "Ephemeral" });
938
945
  }
939
- return interaction.reply({ content, flags: "Ephemeral" });
946
+ return;
940
947
  }
941
948
  try {
942
- return await command.run(client, client, interaction);
949
+ await command.run(client, client, interaction);
943
950
  } catch (err) {
944
951
  await client.error.handleCommandError(err, interaction.guild, interaction);
945
952
  }
@@ -998,12 +1005,14 @@ var slashCommandHandler = new EventBuilder({
998
1005
  if (!command) {
999
1006
  const content = `**/\`${interaction.commandName}\`** is not a registered command.`;
1000
1007
  if (interaction.replied || interaction.deferred) {
1001
- return interaction.followUp({ content, flags: "Ephemeral" });
1008
+ await interaction.followUp({ content, flags: "Ephemeral" });
1009
+ } else {
1010
+ await interaction.reply({ content, flags: "Ephemeral" });
1002
1011
  }
1003
- return interaction.reply({ content, flags: "Ephemeral" });
1012
+ return;
1004
1013
  }
1005
1014
  try {
1006
- return await command.run(client, client, interaction);
1015
+ await command.run(client, client, interaction);
1007
1016
  } catch (err) {
1008
1017
  await client.error.handleCommandError(err, interaction.guild, interaction);
1009
1018
  }
@@ -1787,7 +1796,7 @@ var VimcordErrorHandler = class {
1787
1796
  var import_chalk2 = __toESM(require("chalk"));
1788
1797
 
1789
1798
  // package.json
1790
- var version = "1.0.48";
1799
+ var version = "1.0.51";
1791
1800
 
1792
1801
  // src/client/vimcord.logger.ts
1793
1802
  var clientLoggerFactory = (client) => new Logger({ prefixEmoji: "\u26A1", prefix: `vimcord (i${client.clientId})` }).extend({
@@ -1863,9 +1872,11 @@ function getDevMode() {
1863
1872
  }
1864
1873
 
1865
1874
  // src/configs/app.config.ts
1875
+ var packageJson = getPackageJson();
1876
+ var version2 = typeof packageJson.version === "string" ? packageJson.version : "1.0.0";
1866
1877
  var defaultConfig = {
1867
1878
  name: "Discord Bot",
1868
- version: getPackageJson()?.version ?? "1.0.0",
1879
+ version: version2,
1869
1880
  devMode: getDevMode(),
1870
1881
  verbose: false,
1871
1882
  enableCLI: false,
@@ -2189,11 +2200,16 @@ var CommandManager = class {
2189
2200
  slash;
2190
2201
  prefix;
2191
2202
  context;
2203
+ logger;
2192
2204
  constructor(client) {
2193
2205
  this.client = client;
2194
2206
  this.slash = new SlashCommandManager(client);
2195
2207
  this.prefix = new PrefixCommandManager(client);
2196
2208
  this.context = new ContextCommandManager(client);
2209
+ this.logger = new Logger({
2210
+ prefixEmoji: "\u26A1",
2211
+ prefix: `vimcord (i${client.clientId}) [CommandManager]`
2212
+ });
2197
2213
  }
2198
2214
  getAllAppCommands(options = {}) {
2199
2215
  return [...this.slash.getAll(options), ...this.context.getAll(options)];
@@ -2201,23 +2217,21 @@ var CommandManager = class {
2201
2217
  async registerGlobal(options = {}) {
2202
2218
  const client = await Vimcord.getReadyInstance(this.client.clientId);
2203
2219
  if (!client.rest) {
2204
- console.error(`[CommandManager] \u2716 Failed to register app commands globally: REST is not initialized`);
2220
+ this.logger.error("Failed to register app commands globally: REST is not initialized");
2205
2221
  return;
2206
2222
  }
2207
2223
  const commands = this.getAllAppCommands(options).map((cmd) => cmd.builder.toJSON());
2208
2224
  if (!commands.length) {
2209
- console.log("[CommandManager] No commands to register globally");
2225
+ this.logger.info("No commands to register globally");
2210
2226
  return;
2211
2227
  }
2212
- console.log(
2213
- `[CommandManager] Registering (${commands.length}) ${commands.length === 1 ? "command" : "commands"} globally...`
2214
- );
2228
+ this.logger.info(`Registering (${commands.length}) ${commands.length === 1 ? "command" : "commands"} globally...`);
2215
2229
  try {
2216
2230
  await client.rest.put(import_discord8.Routes.applicationCommands(client.user.id), { body: commands });
2217
- console.log(`[CommandManager] \u2714 Registered app ${commands.length === 1 ? "command" : "commands"} globally`);
2231
+ this.logger.success(`Registered app ${commands.length === 1 ? "command" : "commands"} globally`);
2218
2232
  } catch (err) {
2219
- console.error(
2220
- `[CommandManager] \u2716 Failed to register app ${commands.length === 1 ? "command" : "commands"} globally`,
2233
+ this.logger.error(
2234
+ `Failed to register app ${commands.length === 1 ? "command" : "commands"} globally`,
2221
2235
  err
2222
2236
  );
2223
2237
  }
@@ -2225,60 +2239,66 @@ var CommandManager = class {
2225
2239
  async unregisterGlobal() {
2226
2240
  const client = await Vimcord.getReadyInstance(this.client.clientId);
2227
2241
  if (!client.rest) {
2228
- console.error(`[CommandManager] \u2716 Failed to remove app commands globally: REST is not initialized`);
2242
+ this.logger.error("Failed to remove app commands globally: REST is not initialized");
2229
2243
  return;
2230
2244
  }
2231
2245
  try {
2232
2246
  await client.rest.put(import_discord8.Routes.applicationCommands(client.user.id), { body: [] });
2233
- console.log(`[CommandManager] \u2714 Removed app commands globally`);
2247
+ this.logger.success("Removed app commands globally");
2234
2248
  } catch (err) {
2235
- console.error(`[CommandManager] \u2716 Failed to remove app commands globally`, err);
2249
+ this.logger.error("Failed to remove app commands globally", err);
2236
2250
  }
2237
2251
  }
2238
2252
  async registerGuild(options = {}) {
2239
2253
  const client = await Vimcord.getReadyInstance(this.client.clientId);
2240
2254
  if (!client.rest) {
2241
- console.error(`[CommandManager] \u2716 Failed to register app commands by guild: REST is not initialized`);
2255
+ this.logger.error("Failed to register app commands by guild: REST is not initialized");
2242
2256
  return;
2243
2257
  }
2244
2258
  const commands = this.getAllAppCommands(options).map((cmd) => cmd.builder.toJSON());
2245
2259
  if (!commands.length) {
2246
- console.log("[CommandManager] No commands to register by guild");
2260
+ this.logger.info("No commands to register by guild");
2247
2261
  return;
2248
2262
  }
2249
2263
  const guildIds = options.guilds || client.guilds.cache.map((g) => g.id);
2250
- console.log(
2251
- `[CommandManager] Registering (${commands.length}) ${commands.length === 1 ? "command" : "commands"} for ${guildIds.length} guilds...`
2264
+ this.logger.info(
2265
+ `Registering (${commands.length}) ${commands.length === 1 ? "command" : "commands"} for ${guildIds.length} guilds...`
2252
2266
  );
2253
2267
  await Promise.all(
2254
- guildIds.map(
2255
- (guildId) => client.rest.put(import_discord8.Routes.applicationGuildCommands(client.user.id, guildId), { body: commands }).then(() => {
2268
+ guildIds.map(async (guildId) => {
2269
+ try {
2270
+ await client.rest.put(import_discord8.Routes.applicationGuildCommands(client.user.id, guildId), { body: commands });
2256
2271
  const gName = client.guilds.cache.get(guildId)?.name || "n/a";
2257
- console.log(
2258
- `[CommandManager] \u2714 Set app ${commands.length === 1 ? "command" : "commands"} in guild: ${guildId} (${gName})`
2272
+ this.logger.success(
2273
+ `Set app ${commands.length === 1 ? "command" : "commands"} in guild: ${guildId} (${gName})`
2259
2274
  );
2260
- }).catch((err) => {
2275
+ } catch (err) {
2261
2276
  const gName = client.guilds.cache.get(guildId)?.name || "n/a";
2262
- console.log(
2263
- `[CommandManager] \u2716 Failed to set app ${commands.length === 1 ? "command" : "commands"} in guild: ${guildId} (${gName})`,
2277
+ this.logger.error(
2278
+ `Failed to set app ${commands.length === 1 ? "command" : "commands"} in guild: ${guildId} (${gName})`,
2264
2279
  err
2265
2280
  );
2266
- })
2267
- )
2281
+ }
2282
+ })
2268
2283
  );
2269
2284
  }
2270
2285
  async unregisterGuild(options = {}) {
2271
2286
  const client = await Vimcord.getReadyInstance(this.client.clientId);
2272
2287
  if (!client.rest) {
2273
- console.error(`[CommandManager] \u2716 Failed to register app commands by guild: REST is not initialized`);
2288
+ this.logger.error("Failed to unregister app commands by guild: REST is not initialized");
2274
2289
  return;
2275
2290
  }
2276
2291
  const guildIds = options.guilds || client.guilds.cache.map((g) => g.id);
2277
- console.log(`[CommandManager] Unregistering commands from ${guildIds.length} guilds...`);
2292
+ this.logger.info(`Unregistering commands from ${guildIds.length} guilds...`);
2278
2293
  await Promise.all(
2279
- guildIds.map(
2280
- (guildId) => client.rest.put(import_discord8.Routes.applicationGuildCommands(client.user.id, guildId), { body: [] }).then(() => console.log(`[CommandManager] \u2714 Removed app commands in guild: ${guildId}`)).catch((err) => console.log(`[CommandManager] \u2716 Failed to remove app commands in guild: ${guildId}`, err))
2281
- )
2294
+ guildIds.map(async (guildId) => {
2295
+ try {
2296
+ await client.rest.put(import_discord8.Routes.applicationGuildCommands(client.user.id, guildId), { body: [] });
2297
+ this.logger.success(`Removed app commands in guild: ${guildId}`);
2298
+ } catch (err) {
2299
+ this.logger.error(`Failed to remove app commands in guild: ${guildId}`, err);
2300
+ }
2301
+ })
2282
2302
  );
2283
2303
  }
2284
2304
  };
@@ -2786,8 +2806,8 @@ var Vimcord = class _Vimcord extends import_discord11.Client {
2786
2806
  return this.config.app.version;
2787
2807
  }
2788
2808
  // prettier-ignore
2789
- set $version(version2) {
2790
- this.config.app.version = version2;
2809
+ set $version(version3) {
2810
+ this.config.app.version = version3;
2791
2811
  }
2792
2812
  /** Current dev mode state */
2793
2813
  // prettier-ignore
@@ -3559,49 +3579,77 @@ var BetterContainer = class {
3559
3579
 
3560
3580
  // src/tools/BetterModal.ts
3561
3581
  var import_discord13 = require("discord.js");
3562
- var import_qznt7 = require("qznt");
3563
- var BetterModal = class {
3564
- id;
3565
- options;
3566
- modal;
3582
+ var DEFAULT_CONFIG = {
3583
+ timeout: 6e4
3584
+ };
3585
+ function createRandomId() {
3586
+ return `v-${Math.random().toString(36).split(".")[1]}`;
3587
+ }
3588
+ var BetterModal = class _BetterModal {
3589
+ customId;
3567
3590
  components = /* @__PURE__ */ new Map();
3568
- config;
3569
- constructor(options = {}) {
3570
- this.id = options.id || this.createModalId();
3571
- this.options = options;
3572
- this.modal = new import_discord13.ModalBuilder().setCustomId(this.id);
3573
- this.config = options.config || globalToolsConfig;
3574
- if (options.title) {
3575
- this.setTitle(options.title);
3576
- }
3577
- if (options.components?.length) {
3578
- this.addComponents(...options.components);
3579
- }
3591
+ labelComponents = [];
3592
+ modal;
3593
+ constructor(options) {
3594
+ this.customId = options?.customId ?? createRandomId();
3595
+ this.modal = new import_discord13.ModalBuilder().setCustomId(this.customId);
3596
+ if (options?.title) this.setTitle(options.title);
3597
+ if (options?.components?.length) this.addComponents(...options.components);
3580
3598
  }
3581
- createModalId() {
3582
- return `modal:${import_qznt7.$.rnd.str(10, "alpha", { casing: "mixed" })}-${Date.now()}`;
3599
+ validateComponentLength() {
3600
+ if ((this.components.size ?? 0) >= 25) {
3601
+ throw new Error("[BetterModal] Modal can only have 25 components");
3602
+ }
3583
3603
  }
3584
3604
  createComponentId() {
3585
- return `modal-component:${this.id}-${import_qznt7.$.rnd.str(4, "alpha", { casing: "mixed" })}-${Date.now().toString().slice(-4)}`;
3605
+ return `${this.customId}:${createRandomId()}`;
3586
3606
  }
3587
- validateComponentLength() {
3588
- if (this.components.size >= 5) throw new Error("Modal can only have 5 components");
3589
- }
3590
- toJSON() {
3591
- return this.modal.toJSON();
3607
+ createLabelComponent(data) {
3608
+ const component = new import_discord13.LabelBuilder().setLabel(data.label);
3609
+ if (data.description) component.setDescription(data.description);
3610
+ return component;
3592
3611
  }
3593
3612
  build() {
3594
- this.modal.setLabelComponents(Array.from(this.components.values()));
3613
+ if (!this.modal.data.title) throw new Error("[BetterModal] Modal must have a title");
3614
+ this.modal.setLabelComponents(this.labelComponents);
3595
3615
  return this.modal;
3596
3616
  }
3617
+ clone() {
3618
+ return new _BetterModal({
3619
+ customId: this.customId,
3620
+ title: this.modal.data.title,
3621
+ components: Array.from(this.components.values())
3622
+ });
3623
+ }
3624
+ toJSON() {
3625
+ return this.build().toJSON();
3626
+ }
3627
+ /**
3628
+ * Sets the title of the modal.
3629
+ * @param title The title of the modal.
3630
+ */
3597
3631
  setTitle(title) {
3598
3632
  this.modal.setTitle(title);
3599
3633
  return this;
3600
3634
  }
3635
+ /** Sets components for the modal. */
3636
+ setComponents(...components) {
3637
+ this.components.clear();
3638
+ this.labelComponents = [];
3639
+ this.addComponents(...components);
3640
+ return this;
3641
+ }
3642
+ /** Adds components to the modal. */
3601
3643
  addComponents(...components) {
3602
3644
  for (const component of components) {
3603
3645
  if ("textInput" in component) {
3604
3646
  this.addTextInput(component.textInput);
3647
+ } else if ("checkbox" in component) {
3648
+ this.addCheckbox(component.checkbox);
3649
+ } else if ("checkboxGroup" in component) {
3650
+ this.addCheckboxGroup(component.checkboxGroup);
3651
+ } else if ("radioGroup" in component) {
3652
+ this.addRadioGroup(component.radioGroup);
3605
3653
  } else if ("stringSelect" in component) {
3606
3654
  this.addStringSelect(component.stringSelect);
3607
3655
  } else if ("channelSelect" in component) {
@@ -3618,112 +3666,144 @@ var BetterModal = class {
3618
3666
  }
3619
3667
  return this;
3620
3668
  }
3621
- setComponents(...components) {
3622
- this.modal.spliceLabelComponents(0, this.modal.components.length);
3623
- this.addComponents(...components);
3624
- return this;
3625
- }
3626
3669
  addTextInput(data) {
3627
3670
  this.validateComponentLength();
3628
- let { label, description, custom_id, ...rest } = data;
3629
- custom_id ||= this.createComponentId();
3630
- const textInputComponent = new import_discord13.TextInputBuilder(rest).setCustomId(custom_id);
3631
- if (!rest.style) textInputComponent.setStyle(import_discord13.TextInputStyle.Short);
3632
- const labelComponent = new import_discord13.LabelBuilder().setLabel(label).setTextInputComponent(textInputComponent);
3633
- if (description) labelComponent.setDescription(description);
3634
- this.components.set(custom_id, labelComponent);
3671
+ const customId = data.customId ?? this.createComponentId();
3672
+ const textInput = new import_discord13.TextInputBuilder({ ...data, customId });
3673
+ const label = this.createLabelComponent(data);
3674
+ label.setTextInputComponent(textInput);
3675
+ this.components.set(customId, { textInput: data });
3676
+ this.labelComponents.push(label);
3635
3677
  return this;
3636
3678
  }
3637
3679
  addStringSelect(data) {
3638
3680
  this.validateComponentLength();
3639
- let { label, description, custom_id, ...rest } = data;
3640
- custom_id ||= this.createComponentId();
3641
- const stringSelectComponent = new import_discord13.StringSelectMenuBuilder(rest).setCustomId(custom_id);
3642
- const labelComponent = new import_discord13.LabelBuilder().setLabel(label).setStringSelectMenuComponent(stringSelectComponent);
3643
- if (description) labelComponent.setDescription(description);
3644
- this.components.set(custom_id, labelComponent);
3681
+ const customId = data.customId ?? this.createComponentId();
3682
+ const select = new import_discord13.StringSelectMenuBuilder({ ...data, customId });
3683
+ const label = this.createLabelComponent(data);
3684
+ label.setStringSelectMenuComponent(select);
3685
+ this.components.set(customId, { stringSelect: data });
3686
+ this.labelComponents.push(label);
3687
+ return this;
3688
+ }
3689
+ addCheckbox(data) {
3690
+ this.validateComponentLength();
3691
+ const customId = data.custom_id ?? this.createComponentId();
3692
+ const checkbox = new import_discord13.CheckboxBuilder({ ...data, custom_id: customId });
3693
+ const label = this.createLabelComponent(data);
3694
+ label.setCheckboxComponent(checkbox);
3695
+ this.components.set(customId, { checkbox: data });
3696
+ this.labelComponents.push(label);
3697
+ return this;
3698
+ }
3699
+ addCheckboxGroup(data) {
3700
+ this.validateComponentLength();
3701
+ const customId = data.custom_id ?? this.createComponentId();
3702
+ const checkboxGroup = new import_discord13.CheckboxGroupBuilder({ ...data, custom_id: customId });
3703
+ const label = this.createLabelComponent(data);
3704
+ label.setCheckboxGroupComponent(checkboxGroup);
3705
+ this.components.set(customId, { checkboxGroup: data });
3706
+ this.labelComponents.push(label);
3707
+ return this;
3708
+ }
3709
+ addRadioGroup(data) {
3710
+ this.validateComponentLength();
3711
+ const customId = data.custom_id ?? this.createComponentId();
3712
+ const radioGroup = new import_discord13.RadioGroupBuilder({ ...data, custom_id: customId });
3713
+ const label = this.createLabelComponent(data);
3714
+ label.setRadioGroupComponent(radioGroup);
3715
+ this.components.set(customId, { radioGroup: data });
3716
+ this.labelComponents.push(label);
3645
3717
  return this;
3646
3718
  }
3647
3719
  addChannelSelect(data) {
3648
3720
  this.validateComponentLength();
3649
- let { label, description, custom_id, ...rest } = data;
3650
- custom_id ||= this.createComponentId();
3651
- const channelSelectComponent = new import_discord13.ChannelSelectMenuBuilder(rest).setCustomId(custom_id);
3652
- const labelComponent = new import_discord13.LabelBuilder().setLabel(label).setChannelSelectMenuComponent(channelSelectComponent);
3653
- if (description) labelComponent.setDescription(description);
3654
- this.components.set(custom_id, labelComponent);
3721
+ const customId = data.customId ?? this.createComponentId();
3722
+ const channelSelect = new import_discord13.ChannelSelectMenuBuilder({ ...data, customId });
3723
+ const label = this.createLabelComponent(data);
3724
+ label.setChannelSelectMenuComponent(channelSelect);
3725
+ this.components.set(customId, { channelSelect: data });
3726
+ this.labelComponents.push(label);
3655
3727
  return this;
3656
3728
  }
3657
3729
  addUserSelect(data) {
3658
3730
  this.validateComponentLength();
3659
- let { label, description, custom_id, ...rest } = data;
3660
- custom_id ||= this.createComponentId();
3661
- const userSelectComponent = new import_discord13.UserSelectMenuBuilder(rest).setCustomId(custom_id);
3662
- const labelComponent = new import_discord13.LabelBuilder().setLabel(label).setUserSelectMenuComponent(userSelectComponent);
3663
- if (description) labelComponent.setDescription(description);
3664
- this.components.set(custom_id, labelComponent);
3731
+ const customId = data.customId ?? this.createComponentId();
3732
+ const userSelect = new import_discord13.UserSelectMenuBuilder({ ...data, customId });
3733
+ const label = this.createLabelComponent(data);
3734
+ label.setUserSelectMenuComponent(userSelect);
3735
+ this.components.set(customId, { userSelect: data });
3736
+ this.labelComponents.push(label);
3665
3737
  return this;
3666
3738
  }
3667
3739
  addRoleSelect(data) {
3668
3740
  this.validateComponentLength();
3669
- let { label, description, custom_id, ...rest } = data;
3670
- custom_id ||= this.createComponentId();
3671
- const roleSelectComponent = new import_discord13.RoleSelectMenuBuilder(rest).setCustomId(custom_id);
3672
- const labelComponent = new import_discord13.LabelBuilder().setLabel(label).setRoleSelectMenuComponent(roleSelectComponent);
3673
- if (description) labelComponent.setDescription(description);
3674
- this.components.set(custom_id, labelComponent);
3741
+ const customId = data.customId ?? this.createComponentId();
3742
+ const roleSelect = new import_discord13.RoleSelectMenuBuilder({ ...data, customId });
3743
+ const label = this.createLabelComponent(data);
3744
+ label.setRoleSelectMenuComponent(roleSelect);
3745
+ this.components.set(customId, { roleSelect: data });
3746
+ this.labelComponents.push(label);
3675
3747
  return this;
3676
3748
  }
3677
3749
  addMentionableSelect(data) {
3678
3750
  this.validateComponentLength();
3679
- let { label, description, custom_id, ...rest } = data;
3680
- custom_id ||= this.createComponentId();
3681
- const mentionableSelectComponent = new import_discord13.MentionableSelectMenuBuilder(rest).setCustomId(custom_id);
3682
- const labelComponent = new import_discord13.LabelBuilder().setLabel(label).setMentionableSelectMenuComponent(mentionableSelectComponent);
3683
- if (description) labelComponent.setDescription(description);
3684
- this.components.set(custom_id, labelComponent);
3751
+ const customId = data.customId ?? this.createComponentId();
3752
+ const mentionableSelect = new import_discord13.MentionableSelectMenuBuilder({ ...data, customId });
3753
+ const label = this.createLabelComponent(data);
3754
+ label.setMentionableSelectMenuComponent(mentionableSelect);
3755
+ this.components.set(customId, { mentionableSelect: data });
3756
+ this.labelComponents.push(label);
3685
3757
  return this;
3686
3758
  }
3687
3759
  addFileUpload(data) {
3688
3760
  this.validateComponentLength();
3689
- let { label, description, custom_id, ...rest } = data;
3690
- custom_id ||= this.createComponentId();
3691
- const fileUploadComponent = new import_discord13.FileUploadBuilder(rest).setCustomId(custom_id);
3692
- const labelComponent = new import_discord13.LabelBuilder().setLabel(label).setFileUploadComponent(fileUploadComponent);
3693
- if (description) labelComponent.setDescription(description);
3694
- this.components.set(custom_id, labelComponent);
3761
+ const customId = data.custom_id ?? this.createComponentId();
3762
+ const fileUpload = new import_discord13.FileUploadBuilder({ ...data, custom_id: customId });
3763
+ const label = this.createLabelComponent(data);
3764
+ label.setFileUploadComponent(fileUpload);
3765
+ this.components.set(customId, { fileUpload: data });
3766
+ this.labelComponents.push(label);
3695
3767
  return this;
3696
3768
  }
3697
3769
  /**
3698
- * Shows the modal via interaction.
3699
- * @param interaction The interaction used to show the modal
3770
+ * Shows the modal to the user via interaction.
3771
+ * @param interaction The command interaction to show the modal with.
3772
+ * @param options Modal options.
3700
3773
  */
3701
- async show(interaction) {
3702
- if (!("showModal" in interaction)) throw new Error("Interaction does not support showing modals");
3703
- if (!this.modal.data.title) throw new Error("Modal must have a title");
3704
- this.build();
3705
- await interaction.showModal(this.modal).catch((err) => {
3706
- console.error("Modal failed to send", err);
3707
- });
3774
+ async show(interaction, options) {
3775
+ if (!interaction) throw new Error("[BetterModal] Interaction is null or undefined");
3776
+ const modal = this.build();
3777
+ await interaction.showModal(modal, options);
3778
+ }
3779
+ /**
3780
+ * Shows the modal and waits for it to be submitted.
3781
+ * @param interaction The interaction to show the modal with.
3782
+ * @param options Modal submission options.
3783
+ */
3784
+ async showAndAwait(interaction, options) {
3785
+ await this.show(interaction);
3786
+ return this.awaitSubmit(interaction, options);
3708
3787
  }
3709
3788
  /**
3710
- * Waits for the modal to be submitted and returns the component data.
3711
- * @param interaction The interaction used to show the modal
3712
- * @param options Options */
3789
+ * Waits for this modal to be submitted, returning a helper utility object.
3790
+ * @param interaction The interaction to show the modal with.
3791
+ * @param options Modal submission options.
3792
+ */
3713
3793
  async awaitSubmit(interaction, options) {
3714
- if (!("showModal" in interaction)) throw new Error("Interaction does not support showing modals");
3794
+ if (!interaction) throw new Error("[BetterModal] Interaction is null or undefined");
3795
+ const timeout = options?.timeout ?? DEFAULT_CONFIG.timeout;
3715
3796
  try {
3716
3797
  const modalSubmit = await interaction.awaitModalSubmit({
3717
- filter: (i) => i.customId === this.id,
3718
- time: options?.timeout ?? this.config.timeouts.modalSubmit,
3719
- ...options
3798
+ filter: (i) => i.customId === this.customId,
3799
+ time: timeout
3720
3800
  });
3721
- if (options?.autoDefer) {
3801
+ if (options?.deferUpdate) {
3722
3802
  await modalSubmit.deferUpdate();
3723
3803
  }
3724
3804
  const fields = /* @__PURE__ */ new Map();
3725
3805
  const values = [];
3726
- for (const [customId] of this.components) {
3806
+ for (const customId of this.components.keys()) {
3727
3807
  let value = null;
3728
3808
  try {
3729
3809
  value = modalSubmit.fields.getTextInputValue(customId);
@@ -3740,31 +3820,17 @@ var BetterModal = class {
3740
3820
  values.push(value);
3741
3821
  }
3742
3822
  return {
3743
- getField(customId, required) {
3744
- const value = fields.get(customId);
3745
- if (required && value === void 0) {
3746
- throw new Error(`ModalSubmitResult: Field ${customId} is required but was not found`);
3747
- }
3748
- return value;
3749
- },
3750
3823
  values,
3751
3824
  interaction: modalSubmit,
3825
+ getField: (customId) => fields.get(customId),
3752
3826
  reply: (options2) => dynaSend(modalSubmit, options2),
3753
- deferUpdate: async (options2) => await modalSubmit.deferUpdate(options2),
3754
- followUp: async (options2) => await modalSubmit.followUp(options2)
3827
+ followUp: async (options2) => dynaSend(modalSubmit, options2),
3828
+ deferUpdate: () => modalSubmit.deferUpdate()
3755
3829
  };
3756
- } catch (error) {
3830
+ } catch {
3757
3831
  return null;
3758
3832
  }
3759
3833
  }
3760
- /**
3761
- * Shows the modal and waits for the modal to be submitted, returning the component data.
3762
- * @param interaction The interaction used to show the modal
3763
- * @param options Options */
3764
- async showAndAwait(interaction, options) {
3765
- await this.show(interaction);
3766
- return this.awaitSubmit(interaction, options);
3767
- }
3768
3834
  };
3769
3835
 
3770
3836
  // src/tools/Paginator.ts
@@ -3989,7 +4055,7 @@ var Paginator = class {
3989
4055
  if (disabledNavRow.components.length > 0) {
3990
4056
  newComponents.push(disabledNavRow);
3991
4057
  }
3992
- await this.data.message.edit({ components: newComponents }).catch(Boolean);
4058
+ await this.data.message.edit({ components: newComponents });
3993
4059
  if (this.options.useReactions) {
3994
4060
  await this.nav_removeFromMessage();
3995
4061
  }
@@ -4000,7 +4066,7 @@ var Paginator = class {
4000
4066
  }
4001
4067
  break;
4002
4068
  case 2 /* DeleteMessage */:
4003
- await this.data.message.delete().catch(Boolean);
4069
+ await this.data.message.delete();
4004
4070
  break;
4005
4071
  case 3 /* DoNothing */:
4006
4072
  break;
@@ -4010,16 +4076,16 @@ var Paginator = class {
4010
4076
  async nav_removeFromMessage() {
4011
4077
  if (!this.data.message?.editable) return;
4012
4078
  if (this.options.useReactions) {
4013
- await this.data.message.reactions.removeAll().catch(Boolean);
4079
+ await this.data.message.reactions.removeAll();
4014
4080
  } else {
4015
4081
  const newComponents = this.data.message.components.filter((c) => c.type !== import_discord14.ComponentType.Container);
4016
- await this.data.message.edit({ components: newComponents }).catch(Boolean);
4082
+ await this.data.message.edit({ components: newComponents });
4017
4083
  }
4018
4084
  }
4019
4085
  async nav_addReactions() {
4020
4086
  if (!this.data.message || !this.options.useReactions || !this.data.navigation.reactions.length) return;
4021
4087
  for (const r of this.data.navigation.reactions) {
4022
- await this.data.message.react(r.id).catch(Boolean);
4088
+ await this.data.message.react(r.id);
4023
4089
  }
4024
4090
  }
4025
4091
  async collect_components() {
@@ -4054,7 +4120,7 @@ var Paginator = class {
4054
4120
  }
4055
4121
  switch (i.customId) {
4056
4122
  case "ssm_chapterSelect":
4057
- await i.deferUpdate().catch(Boolean);
4123
+ await i.deferUpdate();
4058
4124
  const chapterIndex = this.chapters.findIndex(
4059
4125
  (c) => c.id === i.values[0]
4060
4126
  );
@@ -4062,25 +4128,25 @@ var Paginator = class {
4062
4128
  await this.refresh();
4063
4129
  break;
4064
4130
  case "btn_first":
4065
- await i.deferUpdate().catch(Boolean);
4131
+ await i.deferUpdate();
4066
4132
  this.callEventStack("first", this.data.page.current, this.data.page.index);
4067
4133
  await this.setPage(this.data.page.index.chapter, 0);
4068
4134
  await this.refresh();
4069
4135
  break;
4070
4136
  case "btn_back":
4071
- await i.deferUpdate().catch(Boolean);
4137
+ await i.deferUpdate();
4072
4138
  this.callEventStack("back", this.data.page.current, this.data.page.index);
4073
4139
  await this.setPage(this.data.page.index.chapter, this.data.page.index.nested - 1);
4074
4140
  await this.refresh();
4075
4141
  break;
4076
4142
  case "btn_next":
4077
- await i.deferUpdate().catch(Boolean);
4143
+ await i.deferUpdate();
4078
4144
  this.callEventStack("next", this.data.page.current, this.data.page.index);
4079
4145
  await this.setPage(this.data.page.index.chapter, this.data.page.index.nested + 1);
4080
4146
  await this.refresh();
4081
4147
  break;
4082
4148
  case "btn_last":
4083
- await i.deferUpdate().catch(Boolean);
4149
+ await i.deferUpdate();
4084
4150
  this.callEventStack("last", this.data.page.current, this.data.page.index);
4085
4151
  await this.setPage(
4086
4152
  this.data.page.index.chapter,
@@ -4478,6 +4544,7 @@ async function prompt(handler, options, sendOptions) {
4478
4544
  createMongoPlugin,
4479
4545
  createMongoSchema,
4480
4546
  createPrefixCommandConfig,
4547
+ createRandomId,
4481
4548
  createSlashCommandConfig,
4482
4549
  createStaffConfig,
4483
4550
  createToolsConfig,