vimcord 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,10 +1,10 @@
1
1
  import * as discord_js from 'discord.js';
2
- import { SlashCommandBuilder as SlashCommandBuilder$1, SlashCommandOptionsOnlyBuilder, SlashCommandSubcommandBuilder, SlashCommandSubcommandsOnlyBuilder, SlashCommandSubcommandGroupBuilder, PermissionResolvable, ActivityType, ContextMenuCommandBuilder, ChatInputCommandInteraction, REST, ClientEvents, CommandInteraction, RepliableInteraction, TextBasedChannel, Message, GuildMember, User, EmbedBuilder, DMChannel, TextChannel, NewsChannel, ThreadChannel, ColorResolvable, ButtonComponentData, APIThumbnailComponent, ActionRowBuilder, MessageActionRowComponentBuilder, ContainerBuilder, BaseMessageOptions, StickerResolvable, PollData, InteractionReplyOptions, MessageMentionOptions, ReplyOptions, ForwardOptions, Client, APIEmbedField, APIEmbed, ClientOptions, Guild, ContextMenuCommandInteraction, MessageComponentType, UserResolvable as UserResolvable$1, InteractionCollector, MappedInteractionTypes, APITextInputComponent, APIStringSelectComponent, APIChannelSelectComponent, APIUserSelectComponent, APIRoleSelectComponent, APIMentionableSelectComponent, APIFileUploadComponent, ModalSubmitInteraction, APIModalInteractionResponseCallbackData, ModalBuilder, Interaction, AwaitModalSubmitOptions, AttachmentBuilder, SelectMenuComponentOptionData, StringSelectMenuOptionBuilder, StringSelectMenuInteraction, ButtonInteraction, MessageReaction, StringSelectMenuBuilder, ButtonBuilder, ReactionCollector, APIButtonComponent, ChannelType, PartialGroupDMChannel, PartialDMChannel, GuildBasedChannel, AnyThreadChannel, VoiceBasedChannel, CategoryChannel, Channel, Role, GuildTextBasedChannel } from 'discord.js';
2
+ import { SlashCommandBuilder as SlashCommandBuilder$1, SlashCommandOptionsOnlyBuilder, SlashCommandSubcommandBuilder, SlashCommandSubcommandsOnlyBuilder, SlashCommandSubcommandGroupBuilder, PermissionResolvable, ActivityType, ContextMenuCommandBuilder, ChatInputCommandInteraction, REST, ClientEvents, CommandInteraction, RepliableInteraction, TextBasedChannel, Message, GuildMember, User, EmbedBuilder, DMChannel, TextChannel, NewsChannel, ThreadChannel, ColorResolvable, ButtonComponentData, APIThumbnailComponent, ActionRowBuilder, MessageActionRowComponentBuilder, ContainerBuilder, BaseMessageOptions, StickerResolvable, PollData, InteractionReplyOptions, MessageMentionOptions, ReplyOptions, ForwardOptions, Client, APIEmbedField, APIEmbed, ClientOptions, Guild, ContextMenuCommandInteraction, MessageComponentType, UserResolvable as UserResolvable$1, MappedInteractionTypes, InteractionCollector, APITextInputComponent, APIStringSelectComponent, APIChannelSelectComponent, APIUserSelectComponent, APIRoleSelectComponent, APIMentionableSelectComponent, APIFileUploadComponent, ModalSubmitInteraction, APIModalInteractionResponseCallbackData, ModalBuilder, Interaction, AwaitModalSubmitOptions, AttachmentBuilder, SelectMenuComponentOptionData, StringSelectMenuOptionBuilder, StringSelectMenuInteraction, ButtonInteraction, MessageReaction, StringSelectMenuBuilder, ButtonBuilder, ReactionCollector, APIButtonComponent, ChannelType, PartialGroupDMChannel, PartialDMChannel, GuildBasedChannel, AnyThreadChannel, VoiceBasedChannel, CategoryChannel, Channel, Role, GuildTextBasedChannel } from 'discord.js';
3
3
  import { DotenvConfigOptions } from 'dotenv';
4
4
  import mongoose, { ClientSessionOptions, QueryOptions, HydratedDocument, Require_id, SchemaDefinition, Schema, Model, RootFilterQuery, mongo, MongooseBaseQueryOptions, CreateOptions, ProjectionType, UpdateQuery, MongooseUpdateQueryOptions, PipelineStage, AggregateOptions } from 'mongoose';
5
5
  import { PartialDeep } from 'type-fest';
6
- import { ScheduledTask } from 'node-cron';
7
6
  import EventEmitter from 'node:events';
7
+ import { Loop } from 'qznt';
8
8
  import { Interface } from 'node:readline';
9
9
 
10
10
  type AnySlashCommandBuilder = SlashCommandBuilder$1 | SlashCommandOptionsOnlyBuilder | SlashCommandSubcommandBuilder | SlashCommandSubcommandsOnlyBuilder | SlashCommandSubcommandGroupBuilder;
@@ -249,9 +249,9 @@ type VimcordStatusManagerEvents = {
249
249
  changed: [ClientActivity];
250
250
  cleared: [];
251
251
  rotation: [ClientActivity];
252
- rotationPaused: [ScheduledTask];
253
- rotationStarted: [ScheduledTask];
254
- rotationDestroyed: [];
252
+ paused: [Loop];
253
+ started: [Loop];
254
+ destroyed: [];
255
255
  };
256
256
  declare class VimcordStatusManager {
257
257
  client: Vimcord;
@@ -1173,12 +1173,13 @@ interface BetterCollectorOptions<T extends MessageComponentType> {
1173
1173
  onTimeout?: CollectorTimeoutType;
1174
1174
  config?: VimcordToolsConfig;
1175
1175
  }
1176
- interface ListenerOptions {
1176
+ interface ListenerOptions<ComponentType extends MessageComponentType = MessageComponentType, InGuild extends boolean = boolean> {
1177
1177
  participants?: UserResolvable$1[];
1178
1178
  defer?: boolean | {
1179
1179
  update?: boolean;
1180
1180
  ephemeral?: boolean;
1181
1181
  };
1182
+ finally?: (arg: MappedInteractionTypes<InGuild>[ComponentType]) => any;
1182
1183
  }
1183
1184
  declare enum CollectorTimeoutType {
1184
1185
  DisableComponents = 0,
@@ -1200,9 +1201,9 @@ declare class BetterCollector<ComponentType extends MessageComponentType, InGuil
1200
1201
  private handleListenerError;
1201
1202
  constructor(message: Message | undefined | null, options?: BetterCollectorOptions<ComponentType>);
1202
1203
  /** Triggers on any interaction */
1203
- on(fn: (interaction: MappedInteractionTypes<InGuild>[ComponentType]) => any, options?: ListenerOptions): this;
1204
+ on(fn: (interaction: MappedInteractionTypes<InGuild>[ComponentType]) => any, options?: ListenerOptions<ComponentType, InGuild>): this;
1204
1205
  /** Triggers when the interaction's customId matches */
1205
- on(customId: string, fn: (interaction: MappedInteractionTypes<InGuild>[ComponentType]) => any, options?: ListenerOptions): this;
1206
+ on(customId: string, fn: (interaction: MappedInteractionTypes<InGuild>[ComponentType]) => any, options?: ListenerOptions<ComponentType, InGuild>): this;
1206
1207
  onEnd(fn: (collected: MappedInteractionTypes<InGuild>[ComponentType][], reason: string) => any, options?: ListenerOptions): this;
1207
1208
  /** Manually stop the collector and trigger cleanup */
1208
1209
  stop(reason?: string): void;
@@ -1430,6 +1431,7 @@ interface PromptOptions {
1430
1431
  content?: string;
1431
1432
  embed?: EmbedResolvable;
1432
1433
  container?: ContainerBuilder | BetterContainer;
1434
+ textOnly?: boolean;
1433
1435
  buttons?: {
1434
1436
  confirm?: ButtonBuilder | ((builder: ButtonBuilder) => ButtonBuilder) | Partial<APIButtonComponent>;
1435
1437
  reject?: ButtonBuilder | ((builder: ButtonBuilder) => ButtonBuilder) | Partial<APIButtonComponent>;
@@ -1451,6 +1453,7 @@ declare class Prompt {
1451
1453
  readonly content?: string;
1452
1454
  readonly embed: EmbedResolvable;
1453
1455
  readonly container?: ContainerBuilder | BetterContainer;
1456
+ readonly textOnly?: boolean;
1454
1457
  readonly buttons: {
1455
1458
  confirm: ButtonBuilder;
1456
1459
  reject: ButtonBuilder;
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import * as discord_js from 'discord.js';
2
- import { SlashCommandBuilder as SlashCommandBuilder$1, SlashCommandOptionsOnlyBuilder, SlashCommandSubcommandBuilder, SlashCommandSubcommandsOnlyBuilder, SlashCommandSubcommandGroupBuilder, PermissionResolvable, ActivityType, ContextMenuCommandBuilder, ChatInputCommandInteraction, REST, ClientEvents, CommandInteraction, RepliableInteraction, TextBasedChannel, Message, GuildMember, User, EmbedBuilder, DMChannel, TextChannel, NewsChannel, ThreadChannel, ColorResolvable, ButtonComponentData, APIThumbnailComponent, ActionRowBuilder, MessageActionRowComponentBuilder, ContainerBuilder, BaseMessageOptions, StickerResolvable, PollData, InteractionReplyOptions, MessageMentionOptions, ReplyOptions, ForwardOptions, Client, APIEmbedField, APIEmbed, ClientOptions, Guild, ContextMenuCommandInteraction, MessageComponentType, UserResolvable as UserResolvable$1, InteractionCollector, MappedInteractionTypes, APITextInputComponent, APIStringSelectComponent, APIChannelSelectComponent, APIUserSelectComponent, APIRoleSelectComponent, APIMentionableSelectComponent, APIFileUploadComponent, ModalSubmitInteraction, APIModalInteractionResponseCallbackData, ModalBuilder, Interaction, AwaitModalSubmitOptions, AttachmentBuilder, SelectMenuComponentOptionData, StringSelectMenuOptionBuilder, StringSelectMenuInteraction, ButtonInteraction, MessageReaction, StringSelectMenuBuilder, ButtonBuilder, ReactionCollector, APIButtonComponent, ChannelType, PartialGroupDMChannel, PartialDMChannel, GuildBasedChannel, AnyThreadChannel, VoiceBasedChannel, CategoryChannel, Channel, Role, GuildTextBasedChannel } from 'discord.js';
2
+ import { SlashCommandBuilder as SlashCommandBuilder$1, SlashCommandOptionsOnlyBuilder, SlashCommandSubcommandBuilder, SlashCommandSubcommandsOnlyBuilder, SlashCommandSubcommandGroupBuilder, PermissionResolvable, ActivityType, ContextMenuCommandBuilder, ChatInputCommandInteraction, REST, ClientEvents, CommandInteraction, RepliableInteraction, TextBasedChannel, Message, GuildMember, User, EmbedBuilder, DMChannel, TextChannel, NewsChannel, ThreadChannel, ColorResolvable, ButtonComponentData, APIThumbnailComponent, ActionRowBuilder, MessageActionRowComponentBuilder, ContainerBuilder, BaseMessageOptions, StickerResolvable, PollData, InteractionReplyOptions, MessageMentionOptions, ReplyOptions, ForwardOptions, Client, APIEmbedField, APIEmbed, ClientOptions, Guild, ContextMenuCommandInteraction, MessageComponentType, UserResolvable as UserResolvable$1, MappedInteractionTypes, InteractionCollector, APITextInputComponent, APIStringSelectComponent, APIChannelSelectComponent, APIUserSelectComponent, APIRoleSelectComponent, APIMentionableSelectComponent, APIFileUploadComponent, ModalSubmitInteraction, APIModalInteractionResponseCallbackData, ModalBuilder, Interaction, AwaitModalSubmitOptions, AttachmentBuilder, SelectMenuComponentOptionData, StringSelectMenuOptionBuilder, StringSelectMenuInteraction, ButtonInteraction, MessageReaction, StringSelectMenuBuilder, ButtonBuilder, ReactionCollector, APIButtonComponent, ChannelType, PartialGroupDMChannel, PartialDMChannel, GuildBasedChannel, AnyThreadChannel, VoiceBasedChannel, CategoryChannel, Channel, Role, GuildTextBasedChannel } from 'discord.js';
3
3
  import { DotenvConfigOptions } from 'dotenv';
4
4
  import mongoose, { ClientSessionOptions, QueryOptions, HydratedDocument, Require_id, SchemaDefinition, Schema, Model, RootFilterQuery, mongo, MongooseBaseQueryOptions, CreateOptions, ProjectionType, UpdateQuery, MongooseUpdateQueryOptions, PipelineStage, AggregateOptions } from 'mongoose';
5
5
  import { PartialDeep } from 'type-fest';
6
- import { ScheduledTask } from 'node-cron';
7
6
  import EventEmitter from 'node:events';
7
+ import { Loop } from 'qznt';
8
8
  import { Interface } from 'node:readline';
9
9
 
10
10
  type AnySlashCommandBuilder = SlashCommandBuilder$1 | SlashCommandOptionsOnlyBuilder | SlashCommandSubcommandBuilder | SlashCommandSubcommandsOnlyBuilder | SlashCommandSubcommandGroupBuilder;
@@ -249,9 +249,9 @@ type VimcordStatusManagerEvents = {
249
249
  changed: [ClientActivity];
250
250
  cleared: [];
251
251
  rotation: [ClientActivity];
252
- rotationPaused: [ScheduledTask];
253
- rotationStarted: [ScheduledTask];
254
- rotationDestroyed: [];
252
+ paused: [Loop];
253
+ started: [Loop];
254
+ destroyed: [];
255
255
  };
256
256
  declare class VimcordStatusManager {
257
257
  client: Vimcord;
@@ -1173,12 +1173,13 @@ interface BetterCollectorOptions<T extends MessageComponentType> {
1173
1173
  onTimeout?: CollectorTimeoutType;
1174
1174
  config?: VimcordToolsConfig;
1175
1175
  }
1176
- interface ListenerOptions {
1176
+ interface ListenerOptions<ComponentType extends MessageComponentType = MessageComponentType, InGuild extends boolean = boolean> {
1177
1177
  participants?: UserResolvable$1[];
1178
1178
  defer?: boolean | {
1179
1179
  update?: boolean;
1180
1180
  ephemeral?: boolean;
1181
1181
  };
1182
+ finally?: (arg: MappedInteractionTypes<InGuild>[ComponentType]) => any;
1182
1183
  }
1183
1184
  declare enum CollectorTimeoutType {
1184
1185
  DisableComponents = 0,
@@ -1200,9 +1201,9 @@ declare class BetterCollector<ComponentType extends MessageComponentType, InGuil
1200
1201
  private handleListenerError;
1201
1202
  constructor(message: Message | undefined | null, options?: BetterCollectorOptions<ComponentType>);
1202
1203
  /** Triggers on any interaction */
1203
- on(fn: (interaction: MappedInteractionTypes<InGuild>[ComponentType]) => any, options?: ListenerOptions): this;
1204
+ on(fn: (interaction: MappedInteractionTypes<InGuild>[ComponentType]) => any, options?: ListenerOptions<ComponentType, InGuild>): this;
1204
1205
  /** Triggers when the interaction's customId matches */
1205
- on(customId: string, fn: (interaction: MappedInteractionTypes<InGuild>[ComponentType]) => any, options?: ListenerOptions): this;
1206
+ on(customId: string, fn: (interaction: MappedInteractionTypes<InGuild>[ComponentType]) => any, options?: ListenerOptions<ComponentType, InGuild>): this;
1206
1207
  onEnd(fn: (collected: MappedInteractionTypes<InGuild>[ComponentType][], reason: string) => any, options?: ListenerOptions): this;
1207
1208
  /** Manually stop the collector and trigger cleanup */
1208
1209
  stop(reason?: string): void;
@@ -1430,6 +1431,7 @@ interface PromptOptions {
1430
1431
  content?: string;
1431
1432
  embed?: EmbedResolvable;
1432
1433
  container?: ContainerBuilder | BetterContainer;
1434
+ textOnly?: boolean;
1433
1435
  buttons?: {
1434
1436
  confirm?: ButtonBuilder | ((builder: ButtonBuilder) => ButtonBuilder) | Partial<APIButtonComponent>;
1435
1437
  reject?: ButtonBuilder | ((builder: ButtonBuilder) => ButtonBuilder) | Partial<APIButtonComponent>;
@@ -1451,6 +1453,7 @@ declare class Prompt {
1451
1453
  readonly content?: string;
1452
1454
  readonly embed: EmbedResolvable;
1453
1455
  readonly container?: ContainerBuilder | BetterContainer;
1456
+ readonly textOnly?: boolean;
1454
1457
  readonly buttons: {
1455
1458
  confirm: ButtonBuilder;
1456
1459
  reject: ButtonBuilder;
package/dist/index.js CHANGED
@@ -421,8 +421,8 @@ var ContextCommandBuilder = class extends BaseCommandBuilder {
421
421
  };
422
422
 
423
423
  // src/utils/dir.ts
424
- import jsTools from "jstools";
425
424
  import path from "path";
425
+ import { $ } from "qznt";
426
426
  function getProcessDir() {
427
427
  const mainPath = process.argv[1];
428
428
  if (!mainPath) return "";
@@ -432,7 +432,7 @@ async function importModulesFromDir(dir, fnPrefix) {
432
432
  const cwd = getProcessDir();
433
433
  const MODULE_RELATIVE_PATH = path.join(cwd, dir);
434
434
  const MODULE_LOG_PATH = dir;
435
- const files = jsTools.readDir(MODULE_RELATIVE_PATH, { recursive: true }).filter(
435
+ const files = $.fs.readDir(MODULE_RELATIVE_PATH).filter(
436
436
  (fn) => fn.endsWith(`${fnPrefix ? `.${fnPrefix}` : ""}.js`) || fn.endsWith(`${fnPrefix ? `.${fnPrefix}` : ""}.ts`)
437
437
  );
438
438
  if (!files.length) {
@@ -1237,28 +1237,9 @@ function formatThousands(num, sep = ",") {
1237
1237
  return `${num}`.replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, sep);
1238
1238
  }
1239
1239
 
1240
- // src/utils/random.ts
1241
- function pickRandom(arr, options) {
1242
- const _rnd = () => {
1243
- return arr[Math.floor(Math.random() * arr.length)];
1244
- };
1245
- let att = 0;
1246
- let candidate = _rnd();
1247
- if (options?.notEqualTo !== void 0 && arr.length > 1) {
1248
- while (candidate === options.notEqualTo) {
1249
- if (att < (options?.maxRerollAttempts ?? 100)) {
1250
- throw new Error(`pickRandom reached max reroll attempts (${options?.maxRerollAttempts ?? 100})`);
1251
- }
1252
- candidate = _rnd();
1253
- att++;
1254
- }
1255
- }
1256
- return options?.clone ? structuredClone(candidate) : candidate;
1257
- }
1258
-
1259
1240
  // src/modules/status.manager.ts
1260
- import cron from "node-cron";
1261
1241
  import EventEmitter from "events";
1242
+ import { $ as $2 } from "qznt";
1262
1243
  var VimcordStatusManager = class {
1263
1244
  client;
1264
1245
  logger;
@@ -1279,24 +1260,9 @@ var VimcordStatusManager = class {
1279
1260
  this.logger.debug("Status cleared");
1280
1261
  }
1281
1262
  });
1282
- this.emitter.on("rotation", () => {
1283
- if (this.client.config.app.verbose) {
1284
- this.logger.debug("Status rotated");
1285
- }
1286
- });
1287
- this.emitter.on("rotationStarted", () => {
1288
- if (this.client.config.app.verbose) {
1289
- this.logger.debug("Status rotation resumed \u25B6\uFE0F");
1290
- }
1291
- });
1292
- this.emitter.on("rotationPaused", () => {
1293
- if (this.client.config.app.verbose) {
1294
- this.logger.debug("Status rotation paused \u23F8\uFE0F");
1295
- }
1296
- });
1297
1263
  }
1298
1264
  clearData() {
1299
- this.task?.destroy();
1265
+ this.task?.stop();
1300
1266
  this.task = null;
1301
1267
  this.lastActivity = null;
1302
1268
  this.lastActivityIndex = 0;
@@ -1329,11 +1295,8 @@ var VimcordStatusManager = class {
1329
1295
  }
1330
1296
  async statusRotationTask(clientStatus) {
1331
1297
  let activity;
1332
- if (clientStatus.randomize) {
1333
- activity = pickRandom(clientStatus.activity, {
1334
- notEqualTo: this.lastActivity,
1335
- clone: true
1336
- });
1298
+ if (clientStatus.randomize && Array.isArray(clientStatus.activity)) {
1299
+ activity = $2.rnd.choice(clientStatus.activity, { not: this.lastActivity });
1337
1300
  this.lastActivity = activity;
1338
1301
  } else {
1339
1302
  const activityIndex = (this.lastActivityIndex + 1) % clientStatus.activity.length;
@@ -1345,34 +1308,22 @@ var VimcordStatusManager = class {
1345
1308
  }
1346
1309
  async scheduleStatusRotation(clientStatus) {
1347
1310
  if (!clientStatus.interval) throw new Error("Cannot create client activity interval without interval time");
1348
- this.task?.destroy();
1311
+ this.task?.stop();
1349
1312
  this.task = null;
1350
- await this.statusRotationTask(clientStatus);
1351
- this.task = cron.createTask(
1352
- `*/${clientStatus.interval} * * * * *`,
1353
- async () => await this.statusRotationTask(clientStatus),
1354
- { noOverlap: true }
1355
- );
1313
+ this.task = new $2.Loop(() => this.statusRotationTask(clientStatus), $2.math.ms(clientStatus.interval), true);
1356
1314
  this.start();
1357
- this.emitter.emit("rotationStarted", this.task);
1358
1315
  }
1359
1316
  start() {
1360
1317
  if (this.task) {
1361
1318
  this.task.start();
1362
- this.emitter.emit("rotationStarted", this.task);
1363
- if (this.client.config.app.verbose) {
1364
- this.logger.debug("Status rotation started");
1365
- }
1319
+ this.emitter.emit("started", this.task);
1366
1320
  }
1367
1321
  return this;
1368
1322
  }
1369
1323
  pause() {
1370
1324
  if (this.task) {
1371
1325
  this.task.stop();
1372
- this.emitter.emit("rotationPaused", this.task);
1373
- if (this.client.config.app.verbose) {
1374
- this.logger.debug("Status rotation paused");
1375
- }
1326
+ this.emitter.emit("paused", this.task);
1376
1327
  }
1377
1328
  return this;
1378
1329
  }
@@ -1386,21 +1337,16 @@ var VimcordStatusManager = class {
1386
1337
  }
1387
1338
  if (!clientStatus.interval) {
1388
1339
  await this.setActivity(Array.isArray(clientStatus.activity) ? clientStatus.activity[0] : clientStatus.activity);
1389
- return this;
1390
- }
1391
- if (clientStatus.interval) {
1340
+ } else {
1392
1341
  await this.scheduleStatusRotation(clientStatus);
1393
1342
  }
1394
1343
  return this;
1395
1344
  }
1396
1345
  async destroy() {
1397
1346
  if (this.task) {
1398
- this.task.destroy();
1347
+ this.task.stop();
1399
1348
  this.task = null;
1400
- this.emitter.emit("rotationDestroyed");
1401
- if (this.client.config.app.verbose) {
1402
- this.logger.debug("Status rotation destroyed");
1403
- }
1349
+ this.emitter.emit("destroyed");
1404
1350
  await this.clear();
1405
1351
  }
1406
1352
  return this;
@@ -1410,9 +1356,6 @@ var VimcordStatusManager = class {
1410
1356
  this.clearData();
1411
1357
  client.user.setActivity({ name: "" });
1412
1358
  this.emitter.emit("cleared");
1413
- if (this.client.config.app.verbose) {
1414
- this.logger.debug("Status cleared");
1415
- }
1416
1359
  return this;
1417
1360
  }
1418
1361
  };
@@ -2962,7 +2905,7 @@ var BetterCollector = class _BetterCollector {
2962
2905
  if (shouldBeDeferred.update) {
2963
2906
  await interaction.deferUpdate().catch(Boolean);
2964
2907
  } else {
2965
- await interaction.deferReply({ ephemeral: shouldBeDeferred.ephemeral }).catch(Boolean);
2908
+ await interaction.deferReply({ flags: shouldBeDeferred.ephemeral ? "Ephemeral" : void 0 }).catch(Boolean);
2966
2909
  }
2967
2910
  } else {
2968
2911
  await interaction.deferReply().catch(Boolean);
@@ -2973,7 +2916,7 @@ var BetterCollector = class _BetterCollector {
2973
2916
  try {
2974
2917
  const isAllowed = await this.validateParticipant(interaction, listener.options?.participants);
2975
2918
  if (!isAllowed) return;
2976
- await listener.fn(interaction);
2919
+ await listener.fn(interaction).finally(() => listener.options?.finally?.(interaction));
2977
2920
  } catch (err) {
2978
2921
  this.handleListenerError(err);
2979
2922
  }
@@ -2983,7 +2926,7 @@ var BetterCollector = class _BetterCollector {
2983
2926
  allListeners.map((l) => {
2984
2927
  const isAllowed = this.validateParticipant(interaction, l.options?.participants);
2985
2928
  if (!isAllowed) return;
2986
- return l.fn(interaction).catch(this.handleListenerError);
2929
+ return l.fn(interaction).catch(this.handleListenerError).finally(() => l.options?.finally?.(interaction));
2987
2930
  })
2988
2931
  );
2989
2932
  }
@@ -3862,6 +3805,7 @@ var Prompt = class {
3862
3805
  content;
3863
3806
  embed;
3864
3807
  container;
3808
+ textOnly;
3865
3809
  buttons;
3866
3810
  customButtons;
3867
3811
  onResolve;
@@ -3875,6 +3819,7 @@ var Prompt = class {
3875
3819
  this.content = options.content;
3876
3820
  this.embed = options.embed ?? this.createDefaultForm();
3877
3821
  this.container = options?.container;
3822
+ this.textOnly = options.textOnly;
3878
3823
  this.buttons = this.createButtons(options.buttons);
3879
3824
  this.customButtons = this.createCustomButtons(options.customButtons);
3880
3825
  this.onResolve = options.onResolve ?? [3 /* DeleteOnConfirm */, 4 /* DeleteOnReject */];
@@ -3954,7 +3899,7 @@ var Prompt = class {
3954
3899
  }
3955
3900
  buildSendOptions(options) {
3956
3901
  const sendData = { ...options };
3957
- if (this.container) {
3902
+ if (!this.textOnly && this.container) {
3958
3903
  sendData.components = Array.isArray(sendData.components) ? [...sendData.components, this.container] : [this.container];
3959
3904
  const existingFlags = sendData.flags ? Array.isArray(sendData.flags) ? sendData.flags : [sendData.flags] : [];
3960
3905
  if (!existingFlags.includes("IsComponentsV2")) {
@@ -3963,7 +3908,9 @@ var Prompt = class {
3963
3908
  sendData.flags = existingFlags;
3964
3909
  }
3965
3910
  } else {
3966
- sendData.embeds = Array.isArray(sendData.embeds) ? [this.embed, ...sendData.embeds] : [this.embed];
3911
+ if (!this.textOnly) {
3912
+ sendData.embeds = Array.isArray(sendData.embeds) ? [this.embed, ...sendData.embeds] : [this.embed];
3913
+ }
3967
3914
  }
3968
3915
  if (this.content) {
3969
3916
  sendData.content = this.content;
@@ -4049,7 +3996,7 @@ async function prompt(handler, options, sendOptions) {
4049
3996
 
4050
3997
  // src/utils/VimcordCLI.ts
4051
3998
  import { createInterface } from "readline";
4052
- import jsTools2 from "jstools";
3999
+ import { $ as $3 } from "qznt";
4053
4000
  var VimcordCLI = class {
4054
4001
  rl;
4055
4002
  options;
@@ -4088,7 +4035,7 @@ var VimcordCLI = class {
4088
4035
  return { isCommand: true, commandName, content: args.join(" "), args };
4089
4036
  }
4090
4037
  getClientInstance(line) {
4091
- const clientIndex = jsTools2.getFlagSubstring(line, "--client", 1) || jsTools2.getFlagSubstring(line, "-c", 1);
4038
+ const clientIndex = $3.str.getFlag(line, "--client", 1) || $3.str.getFlag(line, "-c", 1);
4092
4039
  if (clientIndex) {
4093
4040
  const idx = Number(clientIndex);
4094
4041
  if (isNaN(idx)) {
@@ -4138,7 +4085,7 @@ CLI.addCommand("register", "Register app commands (slash & context) globally, or
4138
4085
  if (!["guild", "global"].includes(mode)) {
4139
4086
  return CLI.logger.error(`'${mode}' is not a valid option. Your options are [guild|global]`);
4140
4087
  }
4141
- let guildIds = (jsTools2.getFlagSubstring(content, "--guilds", 1) || jsTools2.getFlagSubstring(content, "-g", 1) || "").replaceAll(/["']/g, "").split(" ").filter(Boolean).map((s) => s.replaceAll(",", "").trim());
4088
+ let guildIds = ($3.str.getFlag(content, "--guilds", 1) || $3.str.getFlag(content, "-g", 1) || "").replaceAll(/["']/g, "").split(" ").filter(Boolean).map((s) => s.replaceAll(",", "").trim());
4142
4089
  if (!guildIds.length) guildIds = client.guilds.cache.map((g) => g.id);
4143
4090
  switch (mode) {
4144
4091
  case "guild":
@@ -4160,7 +4107,7 @@ CLI.addCommand("unregister", "Unregister app commands globally, or per guild", a
4160
4107
  if (!["guild", "global"].includes(mode)) {
4161
4108
  return CLI.logger.error(`'${mode}' is not a valid option. Your options are [guild|global]`);
4162
4109
  }
4163
- let guildIds = (jsTools2.getFlagSubstring(content, "--guilds", 1) || jsTools2.getFlagSubstring(content, "-g", 1) || "").replaceAll(/["']/g, "").split(" ").filter(Boolean).map((s) => s.replaceAll(",", "").trim());
4110
+ let guildIds = ($3.str.getFlag(content, "--guilds", 1) || $3.str.getFlag(content, "-g", 1) || "").replaceAll(/["']/g, "").split(" ").filter(Boolean).map((s) => s.replaceAll(",", "").trim());
4164
4111
  if (!guildIds.length) guildIds = client.guilds.cache.map((g) => g.id);
4165
4112
  switch (mode) {
4166
4113
  case "guild":
@@ -4179,9 +4126,9 @@ CLI.addCommand("stats", "View statistics about a client instance", (args, conten
4179
4126
  const client = CLI.getClientInstance(content);
4180
4127
  if (!client) return;
4181
4128
  CLI.logger.table(`(stats) ~ ${client.config.app.name}`, {
4182
- "Guilds:": jsTools2.formatThousands(client.guilds.cache.size),
4129
+ "Guilds:": $3.format.number(client.guilds.cache.size),
4183
4130
  "Ping:": `${client.ws.ping || 0}ms`,
4184
- "Uptime:": `${jsTools2.msToSec(client.uptime || 0)}s`,
4131
+ "Uptime:": `${$3.math.secs(client.uptime || 0)}s`,
4185
4132
  "Process Uptime:": `${Math.floor(process.uptime())}s`,
4186
4133
  "Memory Usage:": `${(process.memoryUsage().rss / 1024 / 1024).toFixed(2)} MB`
4187
4134
  });
@@ -4198,7 +4145,7 @@ CLI.addCommand("cmds", "List the loaded commands", async (args, content) => {
4198
4145
  for (const cmd of commands) {
4199
4146
  tableData[`/${cmd.builder.name}`] = `~ ${cmd.builder.description || "No description"}`;
4200
4147
  }
4201
- return CLI.logger.table(`(cmds) ~ slash (${jsTools2.formatThousands(commands.length)})`, tableData);
4148
+ return CLI.logger.table(`(cmds) ~ slash (${$3.format.number(commands.length)})`, tableData);
4202
4149
  }
4203
4150
  case "prefix": {
4204
4151
  const commands = Array.from(client.commands.prefix.commands.values());
@@ -4214,7 +4161,7 @@ CLI.addCommand("cmds", "List the loaded commands", async (args, content) => {
4214
4161
  const aliasIndicator = config.aliases?.length ? ` [${config.aliases.join(", ")}]` : "";
4215
4162
  tableData[`${defaultPrefix}${config.name}${aliasIndicator}`] = `~ ${config.description || "No description"}`;
4216
4163
  }
4217
- return CLI.logger.table(`(cmds) ~ prefix (${jsTools2.formatThousands(commands.length)})`, tableData);
4164
+ return CLI.logger.table(`(cmds) ~ prefix (${$3.format.number(commands.length)})`, tableData);
4218
4165
  }
4219
4166
  case "ctx": {
4220
4167
  const commands = Array.from(client.commands.context.commands.values());
@@ -4224,7 +4171,7 @@ CLI.addCommand("cmds", "List the loaded commands", async (args, content) => {
4224
4171
  const type = cmd.builder.type === 2 ? "User" : "Msg";
4225
4172
  tableData[`[${type}] ${cmd.builder.name}`] = "";
4226
4173
  }
4227
- return CLI.logger.table(`(cmds) ~ ctx (${jsTools2.formatThousands(commands.length)})`, tableData);
4174
+ return CLI.logger.table(`(cmds) ~ ctx (${$3.format.number(commands.length)})`, tableData);
4228
4175
  }
4229
4176
  default:
4230
4177
  return CLI.logger.error(`'${mode}' is not a valid option. Valid options: [slash|prefix|ctx]`);
@@ -4251,6 +4198,25 @@ function createClient(options, features = {}, config = {}) {
4251
4198
  function getClientInstances() {
4252
4199
  return clientInstances;
4253
4200
  }
4201
+
4202
+ // src/utils/random.ts
4203
+ function pickRandom(arr, options) {
4204
+ const _rnd = () => {
4205
+ return arr[Math.floor(Math.random() * arr.length)];
4206
+ };
4207
+ let att = 0;
4208
+ let candidate = _rnd();
4209
+ if (options?.notEqualTo !== void 0 && arr.length > 1) {
4210
+ while (candidate === options.notEqualTo) {
4211
+ if (att < (options?.maxRerollAttempts ?? 100)) {
4212
+ throw new Error(`pickRandom reached max reroll attempts (${options?.maxRerollAttempts ?? 100})`);
4213
+ }
4214
+ candidate = _rnd();
4215
+ att++;
4216
+ }
4217
+ }
4218
+ return options?.clone ? structuredClone(candidate) : candidate;
4219
+ }
4254
4220
  export {
4255
4221
  BaseCommandBuilder,
4256
4222
  BetterCollector,