vimcord 1.0.0 → 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/README.md +94 -0
- package/dist/index.cjs +878 -727
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +294 -186
- package/dist/index.d.ts +294 -186
- package/dist/index.js +874 -727
- package/dist/index.js.map +1 -1
- package/dist/metafile-cjs.json +1 -1
- package/dist/metafile-esm.json +1 -1
- package/package.json +54 -54
package/dist/index.cjs
CHANGED
|
@@ -31,14 +31,17 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
BaseCommandBuilder: () => BaseCommandBuilder,
|
|
34
|
+
BetterCollector: () => BetterCollector,
|
|
34
35
|
BetterContainer: () => BetterContainer,
|
|
35
36
|
BetterEmbed: () => BetterEmbed,
|
|
36
37
|
BetterModal: () => BetterModal,
|
|
37
38
|
CLI: () => CLI,
|
|
39
|
+
CollectorTimeoutType: () => CollectorTimeoutType,
|
|
38
40
|
CommandType: () => CommandType,
|
|
39
41
|
ContextCommandBuilder: () => ContextCommandBuilder,
|
|
40
42
|
DynaSend: () => DynaSend,
|
|
41
43
|
EventBuilder: () => EventBuilder,
|
|
44
|
+
LOGGER_COLORS: () => LOGGER_COLORS,
|
|
42
45
|
LogLevel: () => LogLevel,
|
|
43
46
|
Logger: () => Logger,
|
|
44
47
|
MissingPermissionReason: () => MissingPermissionReason,
|
|
@@ -67,6 +70,7 @@ __export(index_exports, {
|
|
|
67
70
|
clientInstances: () => clientInstances,
|
|
68
71
|
createClient: () => createClient,
|
|
69
72
|
createMongoSchema: () => createMongoSchema,
|
|
73
|
+
createMongoSession: () => createMongoSession,
|
|
70
74
|
createToolsConfig: () => createToolsConfig,
|
|
71
75
|
createVimcordAppConfig: () => createVimcordAppConfig,
|
|
72
76
|
createVimcordContextCommandConfig: () => createVimcordContextCommandConfig,
|
|
@@ -100,16 +104,17 @@ __export(index_exports, {
|
|
|
100
104
|
useClient: () => useClient,
|
|
101
105
|
useMongoDatabase: () => useMongoDatabase,
|
|
102
106
|
useReadyClient: () => useReadyClient,
|
|
107
|
+
useReadyMongoDatabase: () => useReadyMongoDatabase,
|
|
103
108
|
validateCommandPermissions: () => validateCommandPermissions
|
|
104
109
|
});
|
|
105
110
|
module.exports = __toCommonJS(index_exports);
|
|
106
111
|
|
|
107
112
|
// src/types/command.base.ts
|
|
108
|
-
var CommandType = /* @__PURE__ */ ((
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return
|
|
113
|
+
var CommandType = /* @__PURE__ */ ((CommandType2) => {
|
|
114
|
+
CommandType2[CommandType2["Slash"] = 0] = "Slash";
|
|
115
|
+
CommandType2[CommandType2["Prefix"] = 1] = "Prefix";
|
|
116
|
+
CommandType2[CommandType2["Context"] = 2] = "Context";
|
|
117
|
+
return CommandType2;
|
|
113
118
|
})(CommandType || {});
|
|
114
119
|
var MissingPermissionReason = /* @__PURE__ */ ((MissingPermissionReason2) => {
|
|
115
120
|
MissingPermissionReason2[MissingPermissionReason2["User"] = 0] = "User";
|
|
@@ -233,270 +238,239 @@ var import_lodash = __toESM(require("lodash"));
|
|
|
233
238
|
var BaseCommandBuilder = class {
|
|
234
239
|
uuid = (0, import_node_crypto.randomUUID)();
|
|
235
240
|
commandType;
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
channelRateLimitData = /* @__PURE__ */ new Map();
|
|
254
|
-
constructor(type, config) {
|
|
241
|
+
/** Local command configuration and hooks */
|
|
242
|
+
options;
|
|
243
|
+
/** Internal state for rate limiting across different scopes */
|
|
244
|
+
rlStores = {
|
|
245
|
+
[3 /* Global */]: { executions: 0, timestamp: 0 },
|
|
246
|
+
[0 /* User */]: /* @__PURE__ */ new Map(),
|
|
247
|
+
[1 /* Guild */]: /* @__PURE__ */ new Map(),
|
|
248
|
+
[2 /* Channel */]: /* @__PURE__ */ new Map()
|
|
249
|
+
};
|
|
250
|
+
/** * Mapping of CommandTypes to their respective config keys in the Vimcord client
|
|
251
|
+
*/
|
|
252
|
+
typeConfigMapping = {
|
|
253
|
+
[0 /* Slash */]: "slashCommands",
|
|
254
|
+
[1 /* Prefix */]: "prefixCommands",
|
|
255
|
+
[2 /* Context */]: "contextCommands"
|
|
256
|
+
};
|
|
257
|
+
constructor(type, options = {}) {
|
|
255
258
|
this.commandType = type;
|
|
256
|
-
this.
|
|
257
|
-
this.conditions = config?.conditions;
|
|
258
|
-
this.permissions = config?.permissions;
|
|
259
|
-
this.metadata = config?.metadata;
|
|
260
|
-
this.rateLimit = config?.rateLimit;
|
|
261
|
-
this.beforeExecute = config?.beforeExecute;
|
|
262
|
-
this.execute = config?.execute;
|
|
263
|
-
this.afterExecute = config?.afterExecute;
|
|
264
|
-
this.onRateLimit = config?.onRateLimit;
|
|
265
|
-
this.onMissingPermissions = config?.onMissingPermissions;
|
|
266
|
-
this.onConditionsNotMet = config?.onConditionsNotMet;
|
|
267
|
-
this.onUsedWhenDisabled = config?.onUsedWhenDisabled;
|
|
268
|
-
this.onError = config?.onError;
|
|
269
|
-
this.validateBaseConfig();
|
|
259
|
+
this.options = { enabled: true, ...options };
|
|
270
260
|
}
|
|
271
261
|
validateBaseConfig() {
|
|
272
|
-
if (this.rateLimit) {
|
|
273
|
-
|
|
274
|
-
|
|
262
|
+
if (this.options.rateLimit) {
|
|
263
|
+
const { max, interval } = this.options.rateLimit;
|
|
264
|
+
if (max <= 0 || interval <= 0) {
|
|
265
|
+
throw new Error(`[Vimcord:${this.constructor.name}] Rate limit values must be positive.`);
|
|
275
266
|
}
|
|
276
|
-
|
|
277
|
-
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Resolves the final configuration by merging layers:
|
|
271
|
+
* Client Defaults < Client Type-Specific < Local Command Options
|
|
272
|
+
*/
|
|
273
|
+
resolveConfig(client) {
|
|
274
|
+
const typeKey = this.typeConfigMapping[this.commandType];
|
|
275
|
+
const typeSpecificGlobals = client.config?.[typeKey] || {};
|
|
276
|
+
return import_lodash.default.merge({}, typeSpecificGlobals, this.options);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Executes the command lifecycle.
|
|
280
|
+
* Merges global client config with local command options at runtime.
|
|
281
|
+
*/
|
|
282
|
+
async run(client, ...args) {
|
|
283
|
+
const config = this.resolveConfig(client);
|
|
284
|
+
const ctx = this.extractContext(args);
|
|
285
|
+
try {
|
|
286
|
+
if (!config.enabled) {
|
|
287
|
+
return await config.onUsedWhenDisabled?.(...args);
|
|
288
|
+
}
|
|
289
|
+
if (this.isRateLimited(config, ctx)) {
|
|
290
|
+
return await config.onRateLimit?.(...args);
|
|
278
291
|
}
|
|
292
|
+
const perms = this.checkPermissions(client, ctx.member || ctx.user, args[1]);
|
|
293
|
+
if (!perms.validated) {
|
|
294
|
+
return await config.onMissingPermissions?.(perms, ...args);
|
|
295
|
+
}
|
|
296
|
+
if (!await this.checkConditions(config, ...args)) {
|
|
297
|
+
return await config.onConditionsNotMet?.(...args);
|
|
298
|
+
}
|
|
299
|
+
await config.beforeExecute?.(...args);
|
|
300
|
+
if (config.logExecution !== false) {
|
|
301
|
+
const cmdName = this.options.name || this.builder?.name || "Unknown";
|
|
302
|
+
const location = ctx.guild ? `${ctx.guild.name} (${ctx.guild.id})` : "Direct Messages";
|
|
303
|
+
client.logger.commandExecuted(cmdName, ctx.user.username, location);
|
|
304
|
+
}
|
|
305
|
+
const result = await config.execute?.(...args);
|
|
306
|
+
await config.afterExecute?.(result, ...args);
|
|
307
|
+
} catch (error) {
|
|
308
|
+
await this.handleError(error, config, ...args);
|
|
279
309
|
}
|
|
280
310
|
}
|
|
281
|
-
|
|
311
|
+
/**
|
|
312
|
+
* Internal logic to determine if a command execution should be throttled.
|
|
313
|
+
* @param config The merged configuration to use for limits.
|
|
314
|
+
* @param ctx Extracted Discord context (User, Guild, Channel).
|
|
315
|
+
*/
|
|
316
|
+
isRateLimited(config, ctx) {
|
|
317
|
+
if (!config.rateLimit) return false;
|
|
318
|
+
const { scope, interval, max } = config.rateLimit;
|
|
319
|
+
const now = Date.now();
|
|
320
|
+
const key = this.getScopeKey(scope, ctx);
|
|
321
|
+
if (scope !== 3 /* Global */ && !key) return false;
|
|
322
|
+
let data;
|
|
323
|
+
if (scope === 3 /* Global */) {
|
|
324
|
+
data = this.rlStores[3 /* Global */];
|
|
325
|
+
} else {
|
|
326
|
+
const store = this.rlStores[scope];
|
|
327
|
+
data = store.get(key) ?? { executions: 0, timestamp: now };
|
|
328
|
+
store.set(key, data);
|
|
329
|
+
}
|
|
330
|
+
if (now - data.timestamp > interval) {
|
|
331
|
+
data.executions = 0;
|
|
332
|
+
data.timestamp = now;
|
|
333
|
+
}
|
|
334
|
+
if (data.executions >= max) return true;
|
|
335
|
+
data.executions++;
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Validates if the user has required permissions.
|
|
340
|
+
*/
|
|
341
|
+
checkPermissions(client, user, target) {
|
|
342
|
+
if (!this.options.permissions) return { validated: true };
|
|
343
|
+
return validateCommandPermissions(this.options.permissions, client, user, target);
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Evaluates all custom conditions defined for the command.
|
|
347
|
+
*/
|
|
348
|
+
async checkConditions(config, ...args) {
|
|
349
|
+
if (!config.conditions?.length) return true;
|
|
350
|
+
const results = await Promise.all(config.conditions.map((c) => c(...args)));
|
|
351
|
+
return results.every(Boolean);
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Normalizes the trigger arguments into a standard context object.
|
|
355
|
+
*/
|
|
356
|
+
extractContext(args) {
|
|
357
|
+
const event = args[1];
|
|
282
358
|
return {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
rateLimit: this.rateLimit,
|
|
288
|
-
beforeExecute: this.beforeExecute,
|
|
289
|
-
execute: this.execute,
|
|
290
|
-
afterExecute: this.afterExecute,
|
|
291
|
-
onMissingPermissions: this.onMissingPermissions,
|
|
292
|
-
onConditionsNotMet: this.onConditionsNotMet,
|
|
293
|
-
onUsedWhenDisabled: this.onUsedWhenDisabled,
|
|
294
|
-
onRateLimit: this.onRateLimit,
|
|
295
|
-
onError: this.onError
|
|
359
|
+
user: event.user || event.author,
|
|
360
|
+
member: event.member,
|
|
361
|
+
guild: event.guild,
|
|
362
|
+
channel: event.channel
|
|
296
363
|
};
|
|
297
364
|
}
|
|
365
|
+
/**
|
|
366
|
+
* Resolves the storage key based on the RateLimit scope.
|
|
367
|
+
*/
|
|
368
|
+
getScopeKey(scope, ctx) {
|
|
369
|
+
switch (scope) {
|
|
370
|
+
case 0 /* User */:
|
|
371
|
+
return ctx.user.id;
|
|
372
|
+
case 1 /* Guild */:
|
|
373
|
+
return ctx.guild?.id ?? null;
|
|
374
|
+
case 2 /* Channel */:
|
|
375
|
+
return ctx.channel?.id ?? null;
|
|
376
|
+
default:
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Handles command errors by checking local handlers before falling back to global handlers.
|
|
382
|
+
*/
|
|
383
|
+
async handleError(err, config, ...args) {
|
|
384
|
+
if (config.onError) return config.onError(err, ...args);
|
|
385
|
+
throw err;
|
|
386
|
+
}
|
|
387
|
+
/** Toggle command availability */
|
|
298
388
|
setEnabled(enabled) {
|
|
299
|
-
this.enabled = enabled;
|
|
389
|
+
this.options.enabled = enabled;
|
|
390
|
+
return this;
|
|
391
|
+
}
|
|
392
|
+
/** Merge new permission requirements into the existing ones */
|
|
393
|
+
setPermissions(perms) {
|
|
394
|
+
this.options.permissions = import_lodash.default.merge(this.options.permissions || {}, perms);
|
|
300
395
|
return this;
|
|
301
396
|
}
|
|
397
|
+
/** Add custom logic checks that run before execution */
|
|
302
398
|
addConditions(...conditions) {
|
|
303
|
-
|
|
304
|
-
this.conditions.push(...conditions);
|
|
399
|
+
this.options.conditions = [...this.options.conditions || [], ...conditions];
|
|
305
400
|
return this;
|
|
306
401
|
}
|
|
307
|
-
|
|
308
|
-
|
|
402
|
+
/** Set the primary command execution logic */
|
|
403
|
+
setExecute(fn) {
|
|
404
|
+
this.options.execute = fn;
|
|
309
405
|
return this;
|
|
310
406
|
}
|
|
311
|
-
|
|
312
|
-
|
|
407
|
+
/** * Set the custom conditions that must be met for this command to execute
|
|
408
|
+
*/
|
|
409
|
+
setConditions(conditions) {
|
|
410
|
+
this.options.conditions = conditions;
|
|
313
411
|
return this;
|
|
314
412
|
}
|
|
413
|
+
/** * Set the command metadata configuration
|
|
414
|
+
*/
|
|
315
415
|
setMetadata(metadata) {
|
|
316
|
-
this.metadata = import_lodash.default.merge(this.metadata, metadata);
|
|
416
|
+
this.options.metadata = import_lodash.default.merge(this.options.metadata || {}, metadata);
|
|
317
417
|
return this;
|
|
318
418
|
}
|
|
419
|
+
/** * Set the rate limiting options for this command
|
|
420
|
+
*/
|
|
319
421
|
setRateLimit(options) {
|
|
320
|
-
this.rateLimit = options;
|
|
422
|
+
this.options.rateLimit = options;
|
|
423
|
+
this.validateBaseConfig();
|
|
321
424
|
return this;
|
|
322
425
|
}
|
|
323
|
-
|
|
324
|
-
|
|
426
|
+
/** * Set whether to log whenever this command is executed
|
|
427
|
+
* @default true
|
|
428
|
+
*/
|
|
429
|
+
setLogExecution(log) {
|
|
430
|
+
this.options.logExecution = log;
|
|
325
431
|
return this;
|
|
326
432
|
}
|
|
327
|
-
|
|
328
|
-
|
|
433
|
+
/** * Set the function to execute before the main command logic
|
|
434
|
+
*/
|
|
435
|
+
setBeforeExecute(callback) {
|
|
436
|
+
this.options.beforeExecute = callback;
|
|
329
437
|
return this;
|
|
330
438
|
}
|
|
439
|
+
/** * Set the function to execute after successful command execution
|
|
440
|
+
*/
|
|
331
441
|
setAfterExecute(callback) {
|
|
332
|
-
this.afterExecute = callback;
|
|
333
|
-
return this;
|
|
334
|
-
}
|
|
335
|
-
setOnRateLimit(callback) {
|
|
336
|
-
this.onRateLimit = callback;
|
|
442
|
+
this.options.afterExecute = callback;
|
|
337
443
|
return this;
|
|
338
444
|
}
|
|
445
|
+
/** * Set the function to execute when the required permissions are not met
|
|
446
|
+
*/
|
|
339
447
|
setOnMissingPermissions(callback) {
|
|
340
|
-
this.onMissingPermissions = callback;
|
|
448
|
+
this.options.onMissingPermissions = callback;
|
|
341
449
|
return this;
|
|
342
450
|
}
|
|
451
|
+
/** * Set the function to execute when the required conditions are not met
|
|
452
|
+
*/
|
|
343
453
|
setOnConditionsNotMet(callback) {
|
|
344
|
-
this.onConditionsNotMet = callback;
|
|
454
|
+
this.options.onConditionsNotMet = callback;
|
|
345
455
|
return this;
|
|
346
456
|
}
|
|
457
|
+
/** * Set the function to execute when this command is used when its disabled
|
|
458
|
+
*/
|
|
347
459
|
setOnUsedWhenDisabled(callback) {
|
|
348
|
-
this.onUsedWhenDisabled = callback;
|
|
460
|
+
this.options.onUsedWhenDisabled = callback;
|
|
349
461
|
return this;
|
|
350
462
|
}
|
|
351
|
-
|
|
352
|
-
|
|
463
|
+
/** * Set the function to execute when the rate limit is hit
|
|
464
|
+
*/
|
|
465
|
+
setOnRateLimit(callback) {
|
|
466
|
+
this.options.onRateLimit = callback;
|
|
353
467
|
return this;
|
|
354
468
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
if (!user) return null;
|
|
361
|
-
rateLimitData = this.userRateLimitData.get(user.id) ?? { executions: 0, timestamp: 0 };
|
|
362
|
-
break;
|
|
363
|
-
case 1 /* Guild */:
|
|
364
|
-
if (!guild) return null;
|
|
365
|
-
rateLimitData = this.guildRateLimitData.get(guild.id) ?? { executions: 0, timestamp: 0 };
|
|
366
|
-
break;
|
|
367
|
-
case 2 /* Channel */:
|
|
368
|
-
if (!channel) return null;
|
|
369
|
-
rateLimitData = this.channelRateLimitData.get(channel.id) ?? { executions: 0, timestamp: 0 };
|
|
370
|
-
break;
|
|
371
|
-
case 3 /* Global */:
|
|
372
|
-
rateLimitData = this.globalRateLimitData;
|
|
373
|
-
break;
|
|
374
|
-
default:
|
|
375
|
-
return null;
|
|
376
|
-
}
|
|
377
|
-
return { ...rateLimitData, isLimited: this.isRateLimited(user, guild, channel, false) };
|
|
378
|
-
}
|
|
379
|
-
isRateLimited(user, guild, channel, updateExecutions = true) {
|
|
380
|
-
if (!this.rateLimit) return false;
|
|
381
|
-
const now = Date.now();
|
|
382
|
-
let rateLimitData;
|
|
383
|
-
switch (this.rateLimit.scope) {
|
|
384
|
-
case 0 /* User */:
|
|
385
|
-
if (!user) return false;
|
|
386
|
-
rateLimitData = this.userRateLimitData.get(user.id) ?? { executions: 0, timestamp: 0 };
|
|
387
|
-
if (now - rateLimitData.timestamp >= this.rateLimit.interval) {
|
|
388
|
-
rateLimitData.executions = 0;
|
|
389
|
-
rateLimitData.timestamp = now;
|
|
390
|
-
}
|
|
391
|
-
if (updateExecutions) rateLimitData.executions++;
|
|
392
|
-
this.userRateLimitData.set(user.id, rateLimitData);
|
|
393
|
-
break;
|
|
394
|
-
case 1 /* Guild */:
|
|
395
|
-
if (!guild) return false;
|
|
396
|
-
rateLimitData = this.guildRateLimitData.get(guild.id) ?? { executions: 0, timestamp: 0 };
|
|
397
|
-
if (now - rateLimitData.timestamp >= this.rateLimit.interval) {
|
|
398
|
-
rateLimitData.executions = 0;
|
|
399
|
-
rateLimitData.timestamp = now;
|
|
400
|
-
}
|
|
401
|
-
if (updateExecutions) rateLimitData.executions++;
|
|
402
|
-
this.guildRateLimitData.set(guild.id, rateLimitData);
|
|
403
|
-
break;
|
|
404
|
-
case 2 /* Channel */:
|
|
405
|
-
if (!channel) return false;
|
|
406
|
-
rateLimitData = this.guildRateLimitData.get(channel.id) ?? { executions: 0, timestamp: 0 };
|
|
407
|
-
if (now - rateLimitData.timestamp >= this.rateLimit.interval) {
|
|
408
|
-
rateLimitData.executions = 0;
|
|
409
|
-
rateLimitData.timestamp = now;
|
|
410
|
-
}
|
|
411
|
-
if (updateExecutions) rateLimitData.executions++;
|
|
412
|
-
this.channelRateLimitData.set(channel.id, rateLimitData);
|
|
413
|
-
break;
|
|
414
|
-
case 3 /* Global */:
|
|
415
|
-
rateLimitData = this.globalRateLimitData;
|
|
416
|
-
if (now - rateLimitData.timestamp >= this.rateLimit.interval) {
|
|
417
|
-
rateLimitData.executions = 0;
|
|
418
|
-
rateLimitData.timestamp = now;
|
|
419
|
-
}
|
|
420
|
-
if (updateExecutions) rateLimitData.executions++;
|
|
421
|
-
this.globalRateLimitData = rateLimitData;
|
|
422
|
-
break;
|
|
423
|
-
}
|
|
424
|
-
return rateLimitData.executions >= this.rateLimit.max;
|
|
425
|
-
}
|
|
426
|
-
checkPermissions(client, user, command) {
|
|
427
|
-
if (!this.permissions) return { validated: true };
|
|
428
|
-
return validateCommandPermissions(this.permissions, client, user, command);
|
|
429
|
-
}
|
|
430
|
-
async checkConditions(...args) {
|
|
431
|
-
if (!this.conditions?.length) return true;
|
|
432
|
-
const results = await Promise.all(this.conditions.map((condition) => condition(...args)));
|
|
433
|
-
return results.every(Boolean);
|
|
434
|
-
}
|
|
435
|
-
async _runPreflight(clientConfig, command, ...args) {
|
|
436
|
-
try {
|
|
437
|
-
if (!this.enabled) {
|
|
438
|
-
await clientConfig.onUsedWhenDisabled?.(...args);
|
|
439
|
-
await this.onUsedWhenDisabled?.(...args);
|
|
440
|
-
return;
|
|
441
|
-
}
|
|
442
|
-
if (this.isRateLimited(args[1]?.member || args[1]?.author, args[1].guild, args[1].channel)) {
|
|
443
|
-
await clientConfig.onRateLimit?.(...args);
|
|
444
|
-
await this.rateLimit?.onRateLimit?.(...args);
|
|
445
|
-
return;
|
|
446
|
-
}
|
|
447
|
-
const permissionResults = this.checkPermissions(
|
|
448
|
-
args[0],
|
|
449
|
-
args[1]?.member || args[1]?.author || args[1]?.user,
|
|
450
|
-
command
|
|
451
|
-
);
|
|
452
|
-
if (!permissionResults.validated) {
|
|
453
|
-
await clientConfig.onMissingPermissions?.(permissionResults, ...args);
|
|
454
|
-
await this.onMissingPermissions?.(permissionResults, ...args);
|
|
455
|
-
return;
|
|
456
|
-
}
|
|
457
|
-
if (!await this.checkConditions(...args)) {
|
|
458
|
-
await clientConfig.onConditionsNotMet?.(...args);
|
|
459
|
-
await this.onConditionsNotMet?.(...args);
|
|
460
|
-
return;
|
|
461
|
-
}
|
|
462
|
-
} catch (err) {
|
|
463
|
-
if (this.onError) {
|
|
464
|
-
return this.onError(err, ...args);
|
|
465
|
-
} else if (clientConfig.onError) {
|
|
466
|
-
return clientConfig.onError(err, ...args);
|
|
467
|
-
} else {
|
|
468
|
-
throw err;
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
async _runCabinCheck(clientConfig, ...args) {
|
|
473
|
-
try {
|
|
474
|
-
await clientConfig.beforeExecute?.(...args);
|
|
475
|
-
await this.beforeExecute?.(...args);
|
|
476
|
-
} catch (err) {
|
|
477
|
-
if (this.onError) {
|
|
478
|
-
return this.onError(err, ...args);
|
|
479
|
-
} else if (clientConfig.onError) {
|
|
480
|
-
return clientConfig.onError(err, ...args);
|
|
481
|
-
} else {
|
|
482
|
-
throw err;
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
async _runFlyAndLand(clientConfig, ...args) {
|
|
487
|
-
try {
|
|
488
|
-
const result = await this.execute?.(...args);
|
|
489
|
-
await clientConfig?.afterExecute?.(result, ...args);
|
|
490
|
-
await this.afterExecute?.(result, ...args);
|
|
491
|
-
} catch (err) {
|
|
492
|
-
if (this.onError) {
|
|
493
|
-
return this.onError(err, ...args);
|
|
494
|
-
} else if (clientConfig.onError) {
|
|
495
|
-
return clientConfig.onError(err, ...args);
|
|
496
|
-
} else {
|
|
497
|
-
throw err;
|
|
498
|
-
}
|
|
499
|
-
}
|
|
469
|
+
/** * Set a custom error handler for this command
|
|
470
|
+
*/
|
|
471
|
+
setOnError(callback) {
|
|
472
|
+
this.options.onError = callback;
|
|
473
|
+
return this;
|
|
500
474
|
}
|
|
501
475
|
};
|
|
502
476
|
|
|
@@ -505,79 +479,54 @@ var import_discord2 = require("discord.js");
|
|
|
505
479
|
var import_lodash2 = __toESM(require("lodash"));
|
|
506
480
|
var ContextCommandBuilder = class extends BaseCommandBuilder {
|
|
507
481
|
builder;
|
|
508
|
-
deferReply;
|
|
509
|
-
deployment;
|
|
510
482
|
constructor(config) {
|
|
511
483
|
super(2 /* Context */, config);
|
|
512
484
|
this.setBuilder(config.builder);
|
|
513
|
-
|
|
514
|
-
this.
|
|
515
|
-
|
|
485
|
+
const originalExecute = this.options.execute;
|
|
486
|
+
this.options.execute = async (client, interaction) => {
|
|
487
|
+
return await this.handleExecution(client, interaction, originalExecute);
|
|
488
|
+
};
|
|
516
489
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
try {
|
|
522
|
-
this.builder.toJSON();
|
|
523
|
-
} catch (err) {
|
|
524
|
-
throw new Error("VContextCommandBuilder: Invalid command builder", { cause: err });
|
|
490
|
+
async handleExecution(client, interaction, originalExecute) {
|
|
491
|
+
const config = this.resolveConfig(client);
|
|
492
|
+
if (config.deferReply && !interaction.replied && !interaction.deferred) {
|
|
493
|
+
await interaction.deferReply(typeof config.deferReply === "object" ? config.deferReply : void 0);
|
|
525
494
|
}
|
|
495
|
+
return await originalExecute?.(client, interaction);
|
|
526
496
|
}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
return {
|
|
531
|
-
...super.toConfig(),
|
|
532
|
-
builder: this.builder,
|
|
533
|
-
deferReply: this.deferReply,
|
|
534
|
-
deployment: this.deployment
|
|
535
|
-
};
|
|
497
|
+
validateBuilder() {
|
|
498
|
+
if (!this.builder.name) throw new Error(`[Vimcord] ContextCommandBuilder: Command name is required.`);
|
|
499
|
+
this.builder.toJSON();
|
|
536
500
|
}
|
|
501
|
+
// --- Specialized Fluent API ---
|
|
537
502
|
setBuilder(builder) {
|
|
538
|
-
|
|
539
|
-
this.builder = builder(new import_discord2.ContextMenuCommandBuilder());
|
|
540
|
-
} else {
|
|
541
|
-
this.builder = builder;
|
|
542
|
-
}
|
|
503
|
+
this.builder = typeof builder === "function" ? builder(new import_discord2.ContextMenuCommandBuilder()) : builder;
|
|
543
504
|
this.validateBuilder();
|
|
544
505
|
return this;
|
|
545
506
|
}
|
|
546
507
|
setDeferReply(defer) {
|
|
547
|
-
this.deferReply = defer;
|
|
508
|
+
this.options.deferReply = defer;
|
|
548
509
|
return this;
|
|
549
510
|
}
|
|
550
511
|
setDeployment(deployment) {
|
|
551
|
-
this.deployment = import_lodash2.default.merge(this.deployment, deployment);
|
|
512
|
+
this.options.deployment = import_lodash2.default.merge(this.options.deployment || {}, deployment);
|
|
552
513
|
return this;
|
|
553
514
|
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
await this.
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
if (this.onError) {
|
|
564
|
-
return this.onError(err, client, interaction);
|
|
565
|
-
} else if (client.config.contextCommands.onError) {
|
|
566
|
-
return client.config.contextCommands.onError(err, client, interaction);
|
|
567
|
-
} else {
|
|
568
|
-
throw err;
|
|
569
|
-
}
|
|
570
|
-
} finally {
|
|
571
|
-
if (client.config.contextCommands.logExecution) {
|
|
572
|
-
client.logger.commandExecuted(this.builder.name, interaction.user.username, interaction.guild?.name);
|
|
573
|
-
}
|
|
574
|
-
}
|
|
515
|
+
setExecute(fn) {
|
|
516
|
+
const originalExecute = fn;
|
|
517
|
+
this.options.execute = async (client, interaction) => {
|
|
518
|
+
return await this.handleExecution(client, interaction, originalExecute);
|
|
519
|
+
};
|
|
520
|
+
return this;
|
|
521
|
+
}
|
|
522
|
+
toConfig() {
|
|
523
|
+
return { ...this.options, builder: this.builder };
|
|
575
524
|
}
|
|
576
525
|
};
|
|
577
526
|
|
|
578
527
|
// src/utils/dir.ts
|
|
579
|
-
var import_jstools = __toESM(require("jstools"));
|
|
580
528
|
var import_node_path = __toESM(require("path"));
|
|
529
|
+
var import_qznt = require("qznt");
|
|
581
530
|
function getProcessDir() {
|
|
582
531
|
const mainPath = process.argv[1];
|
|
583
532
|
if (!mainPath) return "";
|
|
@@ -587,7 +536,7 @@ async function importModulesFromDir(dir, fnPrefix) {
|
|
|
587
536
|
const cwd = getProcessDir();
|
|
588
537
|
const MODULE_RELATIVE_PATH = import_node_path.default.join(cwd, dir);
|
|
589
538
|
const MODULE_LOG_PATH = dir;
|
|
590
|
-
const files =
|
|
539
|
+
const files = import_qznt.$.fs.readDir(MODULE_RELATIVE_PATH).filter(
|
|
591
540
|
(fn) => fn.endsWith(`${fnPrefix ? `.${fnPrefix}` : ""}.js`) || fn.endsWith(`${fnPrefix ? `.${fnPrefix}` : ""}.ts`)
|
|
592
541
|
);
|
|
593
542
|
if (!files.length) {
|
|
@@ -818,39 +767,74 @@ var EventBuilder = class _EventBuilder {
|
|
|
818
767
|
|
|
819
768
|
// src/builders/prefixCommand.builder.ts
|
|
820
769
|
var PrefixCommandBuilder = class extends BaseCommandBuilder {
|
|
821
|
-
name;
|
|
822
|
-
aliases;
|
|
823
|
-
description;
|
|
824
770
|
constructor(config) {
|
|
825
771
|
super(1 /* Prefix */, config);
|
|
826
|
-
|
|
827
|
-
this.
|
|
828
|
-
|
|
772
|
+
const originalExecute = this.options.execute;
|
|
773
|
+
this.options.execute = async (client, message) => {
|
|
774
|
+
return await this.handleExecution(client, message, originalExecute);
|
|
775
|
+
};
|
|
776
|
+
this.validatePrefixConfig();
|
|
829
777
|
}
|
|
830
|
-
|
|
778
|
+
/**
|
|
779
|
+
* Specialized execution logic for Prefix Commands.
|
|
780
|
+
*/
|
|
781
|
+
async handleExecution(client, message, originalExecute) {
|
|
782
|
+
return await originalExecute?.(client, message);
|
|
783
|
+
}
|
|
784
|
+
validatePrefixConfig() {
|
|
785
|
+
if (!this.options.name) {
|
|
786
|
+
throw new Error(`[Vimcord] PrefixCommandBuilder: Command name is required.`);
|
|
787
|
+
}
|
|
831
788
|
}
|
|
789
|
+
// --- Fluent API (Prefix Specific Only) ---
|
|
790
|
+
/**
|
|
791
|
+
* Set the primary name of the command.
|
|
792
|
+
*/
|
|
793
|
+
setName(name) {
|
|
794
|
+
this.options.name = name;
|
|
795
|
+
return this;
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Set or replace the command aliases.
|
|
799
|
+
*/
|
|
800
|
+
setAliases(aliases) {
|
|
801
|
+
this.options.aliases = aliases;
|
|
802
|
+
return this;
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Add additional aliases without clearing existing ones.
|
|
806
|
+
*/
|
|
807
|
+
addAliases(...aliases) {
|
|
808
|
+
this.options.aliases = [...this.options.aliases || [], ...aliases];
|
|
809
|
+
return this;
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* Set the command description.
|
|
813
|
+
*/
|
|
814
|
+
setDescription(description) {
|
|
815
|
+
this.options.description = description;
|
|
816
|
+
return this;
|
|
817
|
+
}
|
|
818
|
+
// --- Overrides ---
|
|
819
|
+
/**
|
|
820
|
+
* Override setExecute to ensure handleExecution remains the entry point.
|
|
821
|
+
* This is the only base method we need to redefine.
|
|
822
|
+
*/
|
|
823
|
+
setExecute(fn) {
|
|
824
|
+
const originalExecute = fn;
|
|
825
|
+
this.options.execute = async (client, message) => {
|
|
826
|
+
return await this.handleExecution(client, message, originalExecute);
|
|
827
|
+
};
|
|
828
|
+
return this;
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Converts the current builder state back into a config object.
|
|
832
|
+
*/
|
|
832
833
|
toConfig() {
|
|
833
834
|
return {
|
|
834
|
-
...
|
|
835
|
-
name: this.name,
|
|
836
|
-
description: this.description
|
|
835
|
+
...this.options
|
|
837
836
|
};
|
|
838
837
|
}
|
|
839
|
-
async executeCommand(client, message) {
|
|
840
|
-
try {
|
|
841
|
-
await this._runPreflight(client.config.prefixCommands, this.name, client, message);
|
|
842
|
-
await this._runCabinCheck(client.config.prefixCommands, client, message);
|
|
843
|
-
return this._runFlyAndLand(client.config.prefixCommands, client, message);
|
|
844
|
-
} catch (err) {
|
|
845
|
-
this.onError?.(err, client, message);
|
|
846
|
-
client.config.prefixCommands.onError?.(err, client, message);
|
|
847
|
-
throw err;
|
|
848
|
-
} finally {
|
|
849
|
-
if (client.config.prefixCommands.logExecution) {
|
|
850
|
-
client.logger.commandExecuted(this.name, message.author.username, message.guild?.name);
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
838
|
};
|
|
855
839
|
|
|
856
840
|
// src/builders/slashCommand.builder.ts
|
|
@@ -858,110 +842,81 @@ var import_discord3 = require("discord.js");
|
|
|
858
842
|
var import_lodash4 = __toESM(require("lodash"));
|
|
859
843
|
var SlashCommandBuilder = class extends BaseCommandBuilder {
|
|
860
844
|
builder;
|
|
861
|
-
deferReply;
|
|
862
|
-
deployment;
|
|
863
845
|
routes = /* @__PURE__ */ new Map();
|
|
864
|
-
onUnknownRouteHandler;
|
|
865
846
|
constructor(config) {
|
|
866
847
|
super(0 /* Slash */, config);
|
|
867
848
|
this.setBuilder(config.builder);
|
|
868
|
-
this.
|
|
869
|
-
|
|
870
|
-
this.
|
|
871
|
-
|
|
849
|
+
if (config.routes) this.addRoutes(...config.routes);
|
|
850
|
+
const originalExecute = this.options.execute;
|
|
851
|
+
this.options.execute = async (client, interaction) => {
|
|
852
|
+
return await this.handleExecution(client, interaction, originalExecute);
|
|
853
|
+
};
|
|
872
854
|
}
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
855
|
+
async handleExecution(client, interaction, originalExecute) {
|
|
856
|
+
const config = this.resolveConfig(client);
|
|
857
|
+
if (config.deferReply && !interaction.replied && !interaction.deferred) {
|
|
858
|
+
await interaction.deferReply(typeof config.deferReply === "object" ? config.deferReply : void 0);
|
|
876
859
|
}
|
|
877
|
-
|
|
878
|
-
|
|
860
|
+
const subCommand = interaction.options.getSubcommand(false);
|
|
861
|
+
if (subCommand) {
|
|
862
|
+
const handler = this.routes.get(subCommand.toLowerCase());
|
|
863
|
+
if (handler) return await handler(client, interaction);
|
|
864
|
+
if (config.onUnknownRouteHandler) return await config.onUnknownRouteHandler(client, interaction);
|
|
879
865
|
}
|
|
880
|
-
|
|
881
|
-
this.builder.toJSON();
|
|
882
|
-
} catch (err) {
|
|
883
|
-
throw new Error("VSlashCommandBuilder: Invalid command builder", { cause: err });
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
validateConfig() {
|
|
866
|
+
return await originalExecute?.(client, interaction);
|
|
887
867
|
}
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
deferReply: this.deferReply,
|
|
893
|
-
deployment: this.deployment,
|
|
894
|
-
routes: this.routes.size ? Array.from(this.routes.entries()).map(([k, v]) => ({ name: k, handler: v })) : void 0,
|
|
895
|
-
onUnknownRouteHandler: this.onUnknownRouteHandler
|
|
896
|
-
};
|
|
868
|
+
validateBuilder() {
|
|
869
|
+
if (!this.builder.name) throw new Error(`[Vimcord] SlashCommandBuilder: Command name is required.`);
|
|
870
|
+
if (!this.builder.description) throw new Error(`[Vimcord] SlashCommandBuilder: Command description is required.`);
|
|
871
|
+
this.builder.toJSON();
|
|
897
872
|
}
|
|
873
|
+
// --- Specialized Fluent API ---
|
|
898
874
|
setBuilder(builder) {
|
|
899
|
-
|
|
900
|
-
this.builder = builder(new import_discord3.SlashCommandBuilder());
|
|
901
|
-
} else {
|
|
902
|
-
this.builder = builder;
|
|
903
|
-
}
|
|
875
|
+
this.builder = typeof builder === "function" ? builder(new import_discord3.SlashCommandBuilder()) : builder;
|
|
904
876
|
this.validateBuilder();
|
|
905
877
|
return this;
|
|
906
878
|
}
|
|
907
879
|
setDeferReply(defer) {
|
|
908
|
-
this.deferReply = defer;
|
|
880
|
+
this.options.deferReply = defer;
|
|
909
881
|
return this;
|
|
910
882
|
}
|
|
911
883
|
setDeployment(deployment) {
|
|
912
|
-
this.deployment = import_lodash4.default.merge(this.deployment, deployment);
|
|
884
|
+
this.options.deployment = import_lodash4.default.merge(this.options.deployment || {}, deployment);
|
|
913
885
|
return this;
|
|
914
886
|
}
|
|
915
887
|
setRoutes(...routes) {
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
this.routes.set(route.name.toLowerCase(), route.handler);
|
|
919
|
-
}
|
|
920
|
-
} else {
|
|
921
|
-
this.routes = /* @__PURE__ */ new Map();
|
|
922
|
-
}
|
|
888
|
+
this.routes.clear();
|
|
889
|
+
this.addRoutes(...routes);
|
|
923
890
|
return this;
|
|
924
891
|
}
|
|
925
892
|
addRoutes(...routes) {
|
|
893
|
+
if (!this.options.routes) this.options.routes = [];
|
|
926
894
|
for (const route of routes) {
|
|
927
|
-
|
|
895
|
+
const name = route.name.toLowerCase();
|
|
896
|
+
this.routes.set(name, route.handler);
|
|
897
|
+
const existingIndex = this.options.routes.findIndex((r) => r.name.toLowerCase() === name);
|
|
898
|
+
if (existingIndex > -1) this.options.routes[existingIndex] = route;
|
|
899
|
+
else this.options.routes.push(route);
|
|
928
900
|
}
|
|
929
901
|
return this;
|
|
930
902
|
}
|
|
931
903
|
setUnknownRouteHandler(handler) {
|
|
932
|
-
this.onUnknownRouteHandler = handler;
|
|
904
|
+
this.options.onUnknownRouteHandler = handler;
|
|
933
905
|
return this;
|
|
934
906
|
}
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
await this.
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
return result;
|
|
949
|
-
} else if (this.onUnknownRouteHandler) {
|
|
950
|
-
const result = await this.onUnknownRouteHandler?.(client, interaction);
|
|
951
|
-
await this.afterExecute?.(result, client, interaction);
|
|
952
|
-
return result;
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
return this._runFlyAndLand(client.config.slashCommands, client, interaction);
|
|
956
|
-
} catch (err) {
|
|
957
|
-
this.onError?.(err, client, interaction);
|
|
958
|
-
client.config.slashCommands.onError?.(err, client, interaction);
|
|
959
|
-
throw err;
|
|
960
|
-
} finally {
|
|
961
|
-
if (client.config.slashCommands.logExecution) {
|
|
962
|
-
client.logger.commandExecuted(this.builder.name, interaction.user.username, interaction.guild?.name);
|
|
963
|
-
}
|
|
964
|
-
}
|
|
907
|
+
setExecute(fn) {
|
|
908
|
+
const originalExecute = fn;
|
|
909
|
+
this.options.execute = async (client, interaction) => {
|
|
910
|
+
return await this.handleExecution(client, interaction, originalExecute);
|
|
911
|
+
};
|
|
912
|
+
return this;
|
|
913
|
+
}
|
|
914
|
+
toConfig() {
|
|
915
|
+
return {
|
|
916
|
+
...this.options,
|
|
917
|
+
builder: this.builder,
|
|
918
|
+
routes: Array.from(this.routes.entries()).map(([name, handler]) => ({ name, handler }))
|
|
919
|
+
};
|
|
965
920
|
}
|
|
966
921
|
};
|
|
967
922
|
|
|
@@ -976,12 +931,19 @@ var globalVimcordToolsConfig = {
|
|
|
976
931
|
embedColor: [],
|
|
977
932
|
embedColorDev: [],
|
|
978
933
|
timeouts: {
|
|
934
|
+
collectorTimeout: 6e4,
|
|
935
|
+
collectorIdle: 6e4,
|
|
979
936
|
pagination: 6e4,
|
|
980
937
|
prompt: 3e4,
|
|
981
938
|
modalSubmit: 6e4
|
|
982
939
|
},
|
|
940
|
+
collector: {
|
|
941
|
+
notAParticipantMessage: "You are not allowed to use this.",
|
|
942
|
+
userLockMessage: "Please wait until your current action is finished.",
|
|
943
|
+
notAParticipantWarningCooldown: 5e3
|
|
944
|
+
},
|
|
983
945
|
paginator: {
|
|
984
|
-
notAParticipantMessage: "You are not allowed to use this
|
|
946
|
+
notAParticipantMessage: "You are not allowed to use this.",
|
|
985
947
|
jumpableThreshold: 5,
|
|
986
948
|
longThreshold: 4,
|
|
987
949
|
buttons: {
|
|
@@ -994,7 +956,7 @@ var globalVimcordToolsConfig = {
|
|
|
994
956
|
},
|
|
995
957
|
prompt: {
|
|
996
958
|
defaultTitle: "Are you sure?",
|
|
997
|
-
defaultDescription: "Make sure you know what you're doing
|
|
959
|
+
defaultDescription: "Make sure you know what you're doing.",
|
|
998
960
|
confirmLabel: "Confirm",
|
|
999
961
|
rejectLabel: "Cancel"
|
|
1000
962
|
}
|
|
@@ -1084,7 +1046,7 @@ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
|
1084
1046
|
LogLevel2[LogLevel2["ERROR"] = 4] = "ERROR";
|
|
1085
1047
|
return LogLevel2;
|
|
1086
1048
|
})(LogLevel || {});
|
|
1087
|
-
var
|
|
1049
|
+
var LOGGER_COLORS = {
|
|
1088
1050
|
primary: "#5865F2",
|
|
1089
1051
|
success: "#57F287",
|
|
1090
1052
|
warn: "#FEE75C",
|
|
@@ -1105,7 +1067,7 @@ var Logger = class {
|
|
|
1105
1067
|
this.minLevel = minLevel;
|
|
1106
1068
|
this.showTimestamp = showTimestamp;
|
|
1107
1069
|
this.colorScheme = {
|
|
1108
|
-
...
|
|
1070
|
+
...LOGGER_COLORS,
|
|
1109
1071
|
...options?.colors
|
|
1110
1072
|
};
|
|
1111
1073
|
}
|
|
@@ -1166,7 +1128,7 @@ var Logger = class {
|
|
|
1166
1128
|
}
|
|
1167
1129
|
setColors(colors) {
|
|
1168
1130
|
this.colorScheme = {
|
|
1169
|
-
...
|
|
1131
|
+
...LOGGER_COLORS,
|
|
1170
1132
|
...colors
|
|
1171
1133
|
};
|
|
1172
1134
|
return this;
|
|
@@ -1379,28 +1341,9 @@ function formatThousands(num, sep = ",") {
|
|
|
1379
1341
|
return `${num}`.replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, sep);
|
|
1380
1342
|
}
|
|
1381
1343
|
|
|
1382
|
-
// src/utils/random.ts
|
|
1383
|
-
function pickRandom(arr, options) {
|
|
1384
|
-
const _rnd = () => {
|
|
1385
|
-
return arr[Math.floor(Math.random() * arr.length)];
|
|
1386
|
-
};
|
|
1387
|
-
let att = 0;
|
|
1388
|
-
let candidate = _rnd();
|
|
1389
|
-
if (options?.notEqualTo !== void 0 && arr.length > 1) {
|
|
1390
|
-
while (candidate === options.notEqualTo) {
|
|
1391
|
-
if (att < (options?.maxRerollAttempts ?? 100)) {
|
|
1392
|
-
throw new Error(`pickRandom reached max reroll attempts (${options?.maxRerollAttempts ?? 100})`);
|
|
1393
|
-
}
|
|
1394
|
-
candidate = _rnd();
|
|
1395
|
-
att++;
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
return options?.clone ? structuredClone(candidate) : candidate;
|
|
1399
|
-
}
|
|
1400
|
-
|
|
1401
1344
|
// src/modules/status.manager.ts
|
|
1402
|
-
var import_node_cron = __toESM(require("node-cron"));
|
|
1403
1345
|
var import_node_events = __toESM(require("events"));
|
|
1346
|
+
var import_qznt2 = require("qznt");
|
|
1404
1347
|
var VimcordStatusManager = class {
|
|
1405
1348
|
client;
|
|
1406
1349
|
logger;
|
|
@@ -1421,24 +1364,9 @@ var VimcordStatusManager = class {
|
|
|
1421
1364
|
this.logger.debug("Status cleared");
|
|
1422
1365
|
}
|
|
1423
1366
|
});
|
|
1424
|
-
this.emitter.on("rotation", () => {
|
|
1425
|
-
if (this.client.config.app.verbose) {
|
|
1426
|
-
this.logger.debug("Status rotated");
|
|
1427
|
-
}
|
|
1428
|
-
});
|
|
1429
|
-
this.emitter.on("rotationStarted", () => {
|
|
1430
|
-
if (this.client.config.app.verbose) {
|
|
1431
|
-
this.logger.debug("Status rotation resumed \u25B6\uFE0F");
|
|
1432
|
-
}
|
|
1433
|
-
});
|
|
1434
|
-
this.emitter.on("rotationPaused", () => {
|
|
1435
|
-
if (this.client.config.app.verbose) {
|
|
1436
|
-
this.logger.debug("Status rotation paused \u23F8\uFE0F");
|
|
1437
|
-
}
|
|
1438
|
-
});
|
|
1439
1367
|
}
|
|
1440
1368
|
clearData() {
|
|
1441
|
-
this.task?.
|
|
1369
|
+
this.task?.stop();
|
|
1442
1370
|
this.task = null;
|
|
1443
1371
|
this.lastActivity = null;
|
|
1444
1372
|
this.lastActivityIndex = 0;
|
|
@@ -1471,11 +1399,8 @@ var VimcordStatusManager = class {
|
|
|
1471
1399
|
}
|
|
1472
1400
|
async statusRotationTask(clientStatus) {
|
|
1473
1401
|
let activity;
|
|
1474
|
-
if (clientStatus.randomize) {
|
|
1475
|
-
activity =
|
|
1476
|
-
notEqualTo: this.lastActivity,
|
|
1477
|
-
clone: true
|
|
1478
|
-
});
|
|
1402
|
+
if (clientStatus.randomize && Array.isArray(clientStatus.activity)) {
|
|
1403
|
+
activity = import_qznt2.$.rnd.choice(clientStatus.activity, { not: this.lastActivity });
|
|
1479
1404
|
this.lastActivity = activity;
|
|
1480
1405
|
} else {
|
|
1481
1406
|
const activityIndex = (this.lastActivityIndex + 1) % clientStatus.activity.length;
|
|
@@ -1487,34 +1412,22 @@ var VimcordStatusManager = class {
|
|
|
1487
1412
|
}
|
|
1488
1413
|
async scheduleStatusRotation(clientStatus) {
|
|
1489
1414
|
if (!clientStatus.interval) throw new Error("Cannot create client activity interval without interval time");
|
|
1490
|
-
this.task?.
|
|
1415
|
+
this.task?.stop();
|
|
1491
1416
|
this.task = null;
|
|
1492
|
-
|
|
1493
|
-
this.task = import_node_cron.default.createTask(
|
|
1494
|
-
`*/${clientStatus.interval} * * * * *`,
|
|
1495
|
-
async () => await this.statusRotationTask(clientStatus),
|
|
1496
|
-
{ noOverlap: true }
|
|
1497
|
-
);
|
|
1417
|
+
this.task = new import_qznt2.$.Loop(() => this.statusRotationTask(clientStatus), import_qznt2.$.math.ms(clientStatus.interval), true);
|
|
1498
1418
|
this.start();
|
|
1499
|
-
this.emitter.emit("rotationStarted", this.task);
|
|
1500
1419
|
}
|
|
1501
1420
|
start() {
|
|
1502
1421
|
if (this.task) {
|
|
1503
1422
|
this.task.start();
|
|
1504
|
-
this.emitter.emit("
|
|
1505
|
-
if (this.client.config.app.verbose) {
|
|
1506
|
-
this.logger.debug("Status rotation started");
|
|
1507
|
-
}
|
|
1423
|
+
this.emitter.emit("started", this.task);
|
|
1508
1424
|
}
|
|
1509
1425
|
return this;
|
|
1510
1426
|
}
|
|
1511
1427
|
pause() {
|
|
1512
1428
|
if (this.task) {
|
|
1513
1429
|
this.task.stop();
|
|
1514
|
-
this.emitter.emit("
|
|
1515
|
-
if (this.client.config.app.verbose) {
|
|
1516
|
-
this.logger.debug("Status rotation paused");
|
|
1517
|
-
}
|
|
1430
|
+
this.emitter.emit("paused", this.task);
|
|
1518
1431
|
}
|
|
1519
1432
|
return this;
|
|
1520
1433
|
}
|
|
@@ -1528,21 +1441,16 @@ var VimcordStatusManager = class {
|
|
|
1528
1441
|
}
|
|
1529
1442
|
if (!clientStatus.interval) {
|
|
1530
1443
|
await this.setActivity(Array.isArray(clientStatus.activity) ? clientStatus.activity[0] : clientStatus.activity);
|
|
1531
|
-
|
|
1532
|
-
}
|
|
1533
|
-
if (clientStatus.interval) {
|
|
1444
|
+
} else {
|
|
1534
1445
|
await this.scheduleStatusRotation(clientStatus);
|
|
1535
1446
|
}
|
|
1536
1447
|
return this;
|
|
1537
1448
|
}
|
|
1538
1449
|
async destroy() {
|
|
1539
1450
|
if (this.task) {
|
|
1540
|
-
this.task.
|
|
1451
|
+
this.task.stop();
|
|
1541
1452
|
this.task = null;
|
|
1542
|
-
this.emitter.emit("
|
|
1543
|
-
if (this.client.config.app.verbose) {
|
|
1544
|
-
this.logger.debug("Status rotation destroyed");
|
|
1545
|
-
}
|
|
1453
|
+
this.emitter.emit("destroyed");
|
|
1546
1454
|
await this.clear();
|
|
1547
1455
|
}
|
|
1548
1456
|
return this;
|
|
@@ -1552,245 +1460,193 @@ var VimcordStatusManager = class {
|
|
|
1552
1460
|
this.clearData();
|
|
1553
1461
|
client.user.setActivity({ name: "" });
|
|
1554
1462
|
this.emitter.emit("cleared");
|
|
1555
|
-
if (this.client.config.app.verbose) {
|
|
1556
|
-
this.logger.debug("Status cleared");
|
|
1557
|
-
}
|
|
1558
1463
|
return this;
|
|
1559
1464
|
}
|
|
1560
1465
|
};
|
|
1561
1466
|
|
|
1562
1467
|
// src/modules/command.manager.ts
|
|
1563
1468
|
var import_discord5 = require("discord.js");
|
|
1564
|
-
var
|
|
1565
|
-
|
|
1566
|
-
prefix;
|
|
1567
|
-
context;
|
|
1568
|
-
constructor(client) {
|
|
1569
|
-
this.slash = new VimcordSlashCommandManager(client);
|
|
1570
|
-
this.prefix = new VimcordPrefixCommandManager(client);
|
|
1571
|
-
this.context = new VimcordContextCommandManager(client);
|
|
1572
|
-
}
|
|
1573
|
-
};
|
|
1574
|
-
var VimcordSlashCommandManager = class {
|
|
1575
|
-
constructor(client) {
|
|
1469
|
+
var VimcordAppCommandManager = class {
|
|
1470
|
+
constructor(client, typeName) {
|
|
1576
1471
|
this.client = client;
|
|
1577
|
-
|
|
1472
|
+
this.typeName = typeName;
|
|
1473
|
+
this.client.whenReady().then((c) => this.rest = new import_discord5.REST().setToken(c.token));
|
|
1578
1474
|
}
|
|
1579
1475
|
commands = /* @__PURE__ */ new Map();
|
|
1580
1476
|
rest;
|
|
1581
1477
|
get(name) {
|
|
1582
1478
|
return this.commands.get(name);
|
|
1583
1479
|
}
|
|
1480
|
+
/**
|
|
1481
|
+
* Filters and returns commands based on deployment options
|
|
1482
|
+
*/
|
|
1584
1483
|
getAll(options) {
|
|
1585
1484
|
const matchedCommands = /* @__PURE__ */ new Map();
|
|
1485
|
+
const isDev = this.client.config.app.devMode;
|
|
1586
1486
|
for (const cmd of this.commands.values()) {
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
options.fuzzyNames?.some((fuzzyCommand) => cmd.builder.name.includes(fuzzyCommand))
|
|
1593
|
-
);
|
|
1594
|
-
if ((options.names || options.fuzzyNames) && !nameMatched) continue;
|
|
1595
|
-
const guildMatched = cmd.deployment?.guilds?.some((guildId) => options.guilds?.includes(guildId));
|
|
1596
|
-
if (options.guilds && !guildMatched) continue;
|
|
1597
|
-
matched = cmd;
|
|
1598
|
-
} else {
|
|
1599
|
-
matched = cmd;
|
|
1487
|
+
const config = cmd.toConfig();
|
|
1488
|
+
const name = cmd.builder.name;
|
|
1489
|
+
if (options?.names || options?.fuzzyNames) {
|
|
1490
|
+
const nameMatched = options.names?.includes(name) || options.fuzzyNames?.some((fuzzy) => name.includes(fuzzy));
|
|
1491
|
+
if (!nameMatched) continue;
|
|
1600
1492
|
}
|
|
1601
|
-
if (!matched) continue;
|
|
1602
1493
|
if (options?.ignoreDeploymentOptions) {
|
|
1603
|
-
|
|
1604
|
-
matchedCommands.set(matched.builder.name, matched);
|
|
1494
|
+
matchedCommands.set(name, cmd);
|
|
1605
1495
|
continue;
|
|
1606
1496
|
}
|
|
1607
|
-
const
|
|
1608
|
-
|
|
1609
|
-
);
|
|
1610
|
-
if (
|
|
1611
|
-
|
|
1612
|
-
}
|
|
1497
|
+
const deployment = config.deployment || {};
|
|
1498
|
+
const isProperEnv = !deployment.environments || deployment.environments.includes(isDev ? "development" : "production");
|
|
1499
|
+
if (!isProperEnv) continue;
|
|
1500
|
+
if (options?.globalOnly && deployment.global === false) continue;
|
|
1501
|
+
matchedCommands.set(name, cmd);
|
|
1613
1502
|
}
|
|
1614
1503
|
return matchedCommands;
|
|
1615
1504
|
}
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
this.
|
|
1505
|
+
async registerGlobal(options) {
|
|
1506
|
+
const client = await this.client.whenReady();
|
|
1507
|
+
const commands = Array.from(
|
|
1508
|
+
this.getAll({
|
|
1509
|
+
names: options?.commands,
|
|
1510
|
+
fuzzyNames: options?.fuzzyCommands,
|
|
1511
|
+
globalOnly: true
|
|
1512
|
+
}).values()
|
|
1513
|
+
).map((cmd) => cmd.builder.toJSON());
|
|
1514
|
+
if (!commands.length) {
|
|
1515
|
+
console.log(`[${this.typeName}] No commands to register`);
|
|
1516
|
+
return;
|
|
1620
1517
|
}
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
const isProperEnvironment = command.module.default.deployment?.environments?.includes(
|
|
1628
|
-
this.client.config.app.devMode ? "development" : "production"
|
|
1629
|
-
);
|
|
1630
|
-
if (isProperEnvironment ?? true) {
|
|
1631
|
-
this.commands.set(command.module.default.builder.name, command.module.default);
|
|
1632
|
-
importedCommands++;
|
|
1633
|
-
}
|
|
1518
|
+
console.log(`[${this.typeName}] Registering ${commands.length} commands globally...`);
|
|
1519
|
+
try {
|
|
1520
|
+
await this.rest.put(import_discord5.Routes.applicationCommands(client.user.id), { body: commands });
|
|
1521
|
+
console.log(`[${this.typeName}] \u2714 Registered app commands globally`);
|
|
1522
|
+
} catch (err) {
|
|
1523
|
+
console.log(`[${this.typeName}] \u2716 Failed to register app commands globally`, err);
|
|
1634
1524
|
}
|
|
1635
|
-
this.client.logger.moduleLoaded("Slash Commands", importedCommands);
|
|
1636
|
-
return this.commands;
|
|
1637
1525
|
}
|
|
1638
1526
|
async registerGuild(options) {
|
|
1639
1527
|
const client = await this.client.whenReady();
|
|
1640
|
-
const
|
|
1528
|
+
const commands = Array.from(
|
|
1641
1529
|
this.getAll({
|
|
1642
1530
|
names: options?.commands,
|
|
1643
1531
|
fuzzyNames: options?.fuzzyCommands
|
|
1644
1532
|
}).values()
|
|
1645
1533
|
).map((cmd) => cmd.builder.toJSON());
|
|
1646
|
-
if (!
|
|
1647
|
-
console.log(
|
|
1534
|
+
if (!commands.length) {
|
|
1535
|
+
console.log(`[${this.typeName}] No commands to register`);
|
|
1648
1536
|
return;
|
|
1649
1537
|
}
|
|
1650
|
-
const guildIds = options?.guilds || client.guilds.cache.map((
|
|
1651
|
-
console.log(
|
|
1652
|
-
`[SlashCommandManager] Registering ${commandsToRegister.length} app (/) ${commandsToRegister.length === 1 ? "command" : "commands"} for ${guildIds.length} ${guildIds.length === 1 ? "guild" : "guilds"}...`
|
|
1653
|
-
);
|
|
1538
|
+
const guildIds = options?.guilds || client.guilds.cache.map((g) => g.id);
|
|
1539
|
+
console.log(`[${this.typeName}] Registering ${commands.length} commands for ${guildIds.length} guilds...`);
|
|
1654
1540
|
await Promise.all(
|
|
1655
1541
|
guildIds.map(
|
|
1656
|
-
(guildId) => this.rest.put(import_discord5.Routes.applicationGuildCommands(client.user.id, guildId), {
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
)
|
|
1662
|
-
)
|
|
1663
|
-
(err) => console.log(
|
|
1664
|
-
`[SlashCommandManager] \u2716 Failed to set app (/) commands in guild: ${guildId} (${client.guilds.cache.find((g) => g.id === guildId)?.name || "n/a"})`,
|
|
1665
|
-
err
|
|
1666
|
-
)
|
|
1667
|
-
)
|
|
1542
|
+
(guildId) => this.rest.put(import_discord5.Routes.applicationGuildCommands(client.user.id, guildId), { body: commands }).then(() => {
|
|
1543
|
+
const gName = client.guilds.cache.get(guildId)?.name || "n/a";
|
|
1544
|
+
console.log(`[${this.typeName}] \u2714 Set app commands in guild: ${guildId} (${gName})`);
|
|
1545
|
+
}).catch((err) => {
|
|
1546
|
+
const gName = client.guilds.cache.get(guildId)?.name || "n/a";
|
|
1547
|
+
console.log(`[${this.typeName}] \u2716 Failed to set app commands in guild: ${guildId} (${gName})`, err);
|
|
1548
|
+
})
|
|
1668
1549
|
)
|
|
1669
1550
|
);
|
|
1670
|
-
console.log(
|
|
1671
|
-
`[SlashCommandManager] \u2714 Finished registering app (/) commands for ${guildIds.length} ${guildIds.length === 1 ? "guild" : "guilds"}`
|
|
1672
|
-
);
|
|
1673
1551
|
}
|
|
1674
1552
|
async unregisterGuild(options) {
|
|
1675
1553
|
const client = await this.client.whenReady();
|
|
1676
|
-
const guildIds = options?.guilds || client.guilds.cache.map((
|
|
1677
|
-
console.log(
|
|
1678
|
-
`[SlashCommandManager] Unregistering app (/) commands from ${guildIds.length} ${guildIds.length === 1 ? "guild" : "guilds"}...`
|
|
1679
|
-
);
|
|
1554
|
+
const guildIds = options?.guilds || client.guilds.cache.map((g) => g.id);
|
|
1555
|
+
console.log(`[${this.typeName}] Unregistering commands from ${guildIds.length} guilds...`);
|
|
1680
1556
|
await Promise.all(
|
|
1681
1557
|
guildIds.map(
|
|
1682
|
-
(guildId) => this.rest.put(import_discord5.Routes.applicationGuildCommands(client.user.id, guildId), {
|
|
1683
|
-
|
|
1684
|
-
}).then(
|
|
1685
|
-
() => console.log(
|
|
1686
|
-
`[SlashCommandManager] \u2714 Removed app (/) commands in guild: ${guildId} (${client.guilds.cache.find((g) => g.id === guildId)?.name || "n/a"})`
|
|
1687
|
-
)
|
|
1688
|
-
).catch(
|
|
1689
|
-
(err) => console.log(
|
|
1690
|
-
`[SlashCommandManager] \u2716 Failed to remove app (/) commands in guild: ${guildId} (${client.guilds.cache.find((g) => g.id === guildId)?.name || "n/a"})`,
|
|
1691
|
-
err
|
|
1692
|
-
)
|
|
1558
|
+
(guildId) => this.rest.put(import_discord5.Routes.applicationGuildCommands(client.user.id, guildId), { body: [] }).then(() => console.log(`[${this.typeName}] \u2714 Removed app commands in guild: ${guildId}`)).catch(
|
|
1559
|
+
(err) => console.log(`[${this.typeName}] \u2716 Failed to remove app commands in guild: ${guildId}`, err)
|
|
1693
1560
|
)
|
|
1694
1561
|
)
|
|
1695
1562
|
);
|
|
1696
|
-
console.log(
|
|
1697
|
-
`[SlashCommandManager] \u2714 Finished unregistering app (/) commands for ${guildIds.length} ${guildIds.length === 1 ? "guild" : "guilds"}`
|
|
1698
|
-
);
|
|
1699
|
-
}
|
|
1700
|
-
async registerGlobal(options) {
|
|
1701
|
-
const client = await this.client.whenReady();
|
|
1702
|
-
const commandsToRegister = Array.from(
|
|
1703
|
-
this.getAll({
|
|
1704
|
-
names: options?.commands,
|
|
1705
|
-
fuzzyNames: options?.fuzzyCommands,
|
|
1706
|
-
globalOnly: true
|
|
1707
|
-
}).values()
|
|
1708
|
-
).map((cmd) => cmd.builder.toJSON());
|
|
1709
|
-
if (!commandsToRegister.length) {
|
|
1710
|
-
console.log("[SlashCommandManager] No commands to register");
|
|
1711
|
-
return;
|
|
1712
|
-
}
|
|
1713
|
-
console.log(
|
|
1714
|
-
`[SlashCommandManager] Registering ${commandsToRegister.length} app (/) ${commandsToRegister.length === 1 ? "command" : "commands"} globally...`
|
|
1715
|
-
);
|
|
1716
|
-
try {
|
|
1717
|
-
await this.rest.put(import_discord5.Routes.applicationCommands(client.user.id), { body: commandsToRegister });
|
|
1718
|
-
console.log("[SlashCommandManager] \u2714 Registered app (/) commands globally");
|
|
1719
|
-
} catch (err) {
|
|
1720
|
-
console.log("[SlashCommandManager] \u2716 Failed to register app (/) commands globally", err);
|
|
1721
|
-
}
|
|
1722
1563
|
}
|
|
1723
1564
|
async unregisterGlobal() {
|
|
1724
1565
|
const client = await this.client.whenReady();
|
|
1725
|
-
console.log("[SlashCommandManager] Unregistering app (/) commands globally...");
|
|
1726
1566
|
try {
|
|
1727
1567
|
await this.rest.put(import_discord5.Routes.applicationCommands(client.user.id), { body: [] });
|
|
1728
|
-
console.log(
|
|
1568
|
+
console.log(`[${this.typeName}] \u2714 Removed app commands globally`);
|
|
1729
1569
|
} catch (err) {
|
|
1730
|
-
console.log(
|
|
1570
|
+
console.log(`[${this.typeName}] \u2716 Failed to remove app commands globally`, err);
|
|
1731
1571
|
}
|
|
1732
1572
|
}
|
|
1733
1573
|
};
|
|
1734
|
-
var
|
|
1574
|
+
var VimcordSlashCommandManager = class extends VimcordAppCommandManager {
|
|
1735
1575
|
constructor(client) {
|
|
1736
|
-
|
|
1737
|
-
}
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
return Array.from(this.commands.values()).find((cmd) => cmd.aliases?.includes(alias));
|
|
1750
|
-
}
|
|
1751
|
-
return Array.from(this.commands.values()).find((cmd) => cmd.aliases?.includes(alias));
|
|
1576
|
+
super(client, "SlashCommandManager");
|
|
1577
|
+
}
|
|
1578
|
+
async importFrom(dir, replaceAll = false) {
|
|
1579
|
+
if (replaceAll) this.commands.clear();
|
|
1580
|
+
const dirs = Array.isArray(dir) ? dir : [dir];
|
|
1581
|
+
const modules = (await Promise.all(
|
|
1582
|
+
dirs.map((d) => importModulesFromDir(d, "slash"))
|
|
1583
|
+
)).flat();
|
|
1584
|
+
for (const { module: module2 } of modules) {
|
|
1585
|
+
this.commands.set(module2.default.builder.name, module2.default);
|
|
1586
|
+
}
|
|
1587
|
+
this.client.logger.moduleLoaded("Slash Commands", modules.length);
|
|
1588
|
+
return this.commands;
|
|
1752
1589
|
}
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
}
|
|
1767
|
-
this.client.logger.moduleLoaded("
|
|
1590
|
+
};
|
|
1591
|
+
var VimcordContextCommandManager = class extends VimcordAppCommandManager {
|
|
1592
|
+
constructor(client) {
|
|
1593
|
+
super(client, "ContextCommandManager");
|
|
1594
|
+
}
|
|
1595
|
+
async importFrom(dir, replaceAll = false) {
|
|
1596
|
+
if (replaceAll) this.commands.clear();
|
|
1597
|
+
const dirs = Array.isArray(dir) ? dir : [dir];
|
|
1598
|
+
const modules = (await Promise.all(
|
|
1599
|
+
dirs.map((d) => importModulesFromDir(d, "ctx"))
|
|
1600
|
+
)).flat();
|
|
1601
|
+
for (const { module: module2 } of modules) {
|
|
1602
|
+
this.commands.set(module2.default.builder.name, module2.default);
|
|
1603
|
+
}
|
|
1604
|
+
this.client.logger.moduleLoaded("Context Commands", modules.length);
|
|
1768
1605
|
return this.commands;
|
|
1769
1606
|
}
|
|
1770
1607
|
};
|
|
1771
|
-
var
|
|
1608
|
+
var VimcordPrefixCommandManager = class {
|
|
1772
1609
|
constructor(client) {
|
|
1773
1610
|
this.client = client;
|
|
1774
1611
|
}
|
|
1775
1612
|
commands = /* @__PURE__ */ new Map();
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1613
|
+
resolve(trigger) {
|
|
1614
|
+
const config = this.client.config.prefixCommands;
|
|
1615
|
+
const search = config.allowCaseInsensitiveCommandNames ? trigger.toLowerCase() : trigger;
|
|
1616
|
+
return Array.from(this.commands.values()).find((cmd) => {
|
|
1617
|
+
const opts = cmd.toConfig();
|
|
1618
|
+
const name = config.allowCaseInsensitiveCommandNames ? opts.name.toLowerCase() : opts.name;
|
|
1619
|
+
if (name === search) return true;
|
|
1620
|
+
return opts.aliases?.some(
|
|
1621
|
+
(a) => config.allowCaseInsensitiveCommandNames ? a.toLowerCase() === search : a === search
|
|
1622
|
+
);
|
|
1623
|
+
});
|
|
1624
|
+
}
|
|
1625
|
+
async importFrom(dir, replaceAll = false) {
|
|
1626
|
+
if (replaceAll) this.commands.clear();
|
|
1627
|
+
const dirs = Array.isArray(dir) ? dir : [dir];
|
|
1628
|
+
const modules = (await Promise.all(
|
|
1629
|
+
dirs.map(
|
|
1630
|
+
(d) => importModulesFromDir(d, "prefix")
|
|
1631
|
+
)
|
|
1632
|
+
)).flat();
|
|
1633
|
+
for (const { module: module2 } of modules) {
|
|
1634
|
+
this.commands.set(module2.default.toConfig().name, module2.default);
|
|
1789
1635
|
}
|
|
1790
|
-
this.client.logger.moduleLoaded("
|
|
1636
|
+
this.client.logger.moduleLoaded("Prefix Commands", modules.length);
|
|
1791
1637
|
return this.commands;
|
|
1792
1638
|
}
|
|
1793
1639
|
};
|
|
1640
|
+
var VimcordCommandManager = class {
|
|
1641
|
+
slash;
|
|
1642
|
+
prefix;
|
|
1643
|
+
context;
|
|
1644
|
+
constructor(client) {
|
|
1645
|
+
this.slash = new VimcordSlashCommandManager(client);
|
|
1646
|
+
this.prefix = new VimcordPrefixCommandManager(client);
|
|
1647
|
+
this.context = new VimcordContextCommandManager(client);
|
|
1648
|
+
}
|
|
1649
|
+
};
|
|
1794
1650
|
|
|
1795
1651
|
// src/modules/event.manager.ts
|
|
1796
1652
|
var import_discord6 = require("discord.js");
|
|
@@ -2168,7 +2024,7 @@ var BetterEmbed = class _BetterEmbed {
|
|
|
2168
2024
|
}
|
|
2169
2025
|
if (this.data.description) {
|
|
2170
2026
|
this.data.description = formatString(
|
|
2171
|
-
Array.isArray(this.data.description) ? this.data.description.join("\n") : this.data.description
|
|
2027
|
+
Array.isArray(this.data.description) ? this.data.description.filter((s) => s !== null && s !== void 0).join("\n") : this.data.description
|
|
2172
2028
|
);
|
|
2173
2029
|
}
|
|
2174
2030
|
if (this.data.footer && typeof this.data.footer === "object") {
|
|
@@ -2180,7 +2036,7 @@ var BetterEmbed = class _BetterEmbed {
|
|
|
2180
2036
|
if (this.data.imageUrl) {
|
|
2181
2037
|
this.data.imageUrl = formatString(this.data.imageUrl);
|
|
2182
2038
|
}
|
|
2183
|
-
this.data.fields = this.data.fields.map((field) => ({
|
|
2039
|
+
this.data.fields = this.data.fields.filter(Boolean).map((field) => ({
|
|
2184
2040
|
...field,
|
|
2185
2041
|
name: formatString(field.name),
|
|
2186
2042
|
value: formatString(field.value)
|
|
@@ -2405,7 +2261,7 @@ async function retryExponentialBackoff(fn, maxRetries = 3, retryDelay = 1e3) {
|
|
|
2405
2261
|
}
|
|
2406
2262
|
|
|
2407
2263
|
// package.json
|
|
2408
|
-
var version = "1.0.
|
|
2264
|
+
var version = "1.0.1";
|
|
2409
2265
|
|
|
2410
2266
|
// src/client.ts
|
|
2411
2267
|
var import_node_crypto3 = require("crypto");
|
|
@@ -2671,62 +2527,63 @@ var Vimcord = class _Vimcord extends import_discord10.Client {
|
|
|
2671
2527
|
return fetchGuild(client, id);
|
|
2672
2528
|
}
|
|
2673
2529
|
};
|
|
2674
|
-
var defaultSlashCommandHandler = new EventBuilder({
|
|
2675
|
-
event: "interactionCreate",
|
|
2676
|
-
name: "SlashCommandHandler",
|
|
2677
|
-
async execute(client, interaction) {
|
|
2678
|
-
if (!interaction.isChatInputCommand()) return;
|
|
2679
|
-
const command = client.commands.slash.get(interaction.commandName);
|
|
2680
|
-
if (!command) {
|
|
2681
|
-
return interaction.reply({
|
|
2682
|
-
content: `**/\`${interaction.commandName}\`** is not a command`,
|
|
2683
|
-
flags: "Ephemeral"
|
|
2684
|
-
});
|
|
2685
|
-
}
|
|
2686
|
-
if (command.deferReply && !interaction.replied && !interaction.deferred) {
|
|
2687
|
-
await interaction.deferReply(typeof command.deferReply === "object" ? command.deferReply : void 0);
|
|
2688
|
-
}
|
|
2689
|
-
try {
|
|
2690
|
-
return command.executeCommand(client, interaction);
|
|
2691
|
-
} catch (err) {
|
|
2692
|
-
sendCommandErrorEmbed(client, err, interaction.guild, interaction);
|
|
2693
|
-
throw err;
|
|
2694
|
-
}
|
|
2695
|
-
}
|
|
2696
|
-
});
|
|
2697
2530
|
var defaultPrefixCommandHandler = new EventBuilder({
|
|
2698
2531
|
event: "messageCreate",
|
|
2699
2532
|
name: "PrefixCommandHandler",
|
|
2700
2533
|
async execute(client, message) {
|
|
2701
|
-
if (message.author.bot) return;
|
|
2534
|
+
if (message.author.bot || !message.guild) return;
|
|
2535
|
+
const config = client.config.prefixCommands;
|
|
2536
|
+
let activePrefix = config.defaultPrefix;
|
|
2537
|
+
if (config.guildPrefixResolver) {
|
|
2538
|
+
try {
|
|
2539
|
+
const customPrefix = await config.guildPrefixResolver(client, message.guild.id);
|
|
2540
|
+
if (customPrefix) activePrefix = customPrefix;
|
|
2541
|
+
} catch (err) {
|
|
2542
|
+
client.logger.error(`Error in guildPrefixResolver for guild ${message.guild.id}:`, err);
|
|
2543
|
+
}
|
|
2544
|
+
}
|
|
2702
2545
|
let prefixUsed;
|
|
2703
|
-
if (
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
}
|
|
2710
|
-
} else {
|
|
2711
|
-
return;
|
|
2546
|
+
if (message.content.startsWith(activePrefix)) {
|
|
2547
|
+
prefixUsed = activePrefix;
|
|
2548
|
+
} else if (config.allowMentionAsPrefix) {
|
|
2549
|
+
const mention = (0, import_discord10.userMention)(client.user.id);
|
|
2550
|
+
if (message.content.startsWith(mention)) {
|
|
2551
|
+
prefixUsed = message.content.startsWith(`${mention} `) ? `${mention} ` : mention;
|
|
2712
2552
|
}
|
|
2713
|
-
} else {
|
|
2714
|
-
prefixUsed = client.config.prefixCommands.defaultPrefix;
|
|
2715
2553
|
}
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2554
|
+
if (!prefixUsed) return;
|
|
2555
|
+
const contentWithoutPrefix = message.content.slice(prefixUsed.length).trim();
|
|
2556
|
+
const args = contentWithoutPrefix.split(/\s+/);
|
|
2557
|
+
const trigger = args.shift();
|
|
2558
|
+
if (!trigger) return;
|
|
2559
|
+
const command = client.commands.prefix.resolve(trigger);
|
|
2560
|
+
if (!command) return;
|
|
2561
|
+
message.content = args.join(" ");
|
|
2562
|
+
try {
|
|
2563
|
+
return await command.run(client, client, message);
|
|
2564
|
+
} catch (err) {
|
|
2565
|
+
await sendCommandErrorEmbed(client, err, message.guild, message);
|
|
2566
|
+
throw err;
|
|
2720
2567
|
}
|
|
2721
|
-
|
|
2568
|
+
}
|
|
2569
|
+
});
|
|
2570
|
+
var defaultSlashCommandHandler = new EventBuilder({
|
|
2571
|
+
event: "interactionCreate",
|
|
2572
|
+
name: "SlashCommandHandler",
|
|
2573
|
+
async execute(client, interaction) {
|
|
2574
|
+
if (!interaction.isChatInputCommand()) return;
|
|
2575
|
+
const command = client.commands.slash.get(interaction.commandName);
|
|
2722
2576
|
if (!command) {
|
|
2723
|
-
|
|
2577
|
+
const content = `**/\`${interaction.commandName}\`** is not a registered command.`;
|
|
2578
|
+
if (interaction.replied || interaction.deferred) {
|
|
2579
|
+
return interaction.followUp({ content, flags: "Ephemeral" });
|
|
2580
|
+
}
|
|
2581
|
+
return interaction.reply({ content, flags: "Ephemeral" });
|
|
2724
2582
|
}
|
|
2725
|
-
message.content = message.content.slice(commandName.length + 1);
|
|
2726
2583
|
try {
|
|
2727
|
-
return command.
|
|
2584
|
+
return await command.run(client, client, interaction);
|
|
2728
2585
|
} catch (err) {
|
|
2729
|
-
sendCommandErrorEmbed(client, err,
|
|
2586
|
+
await sendCommandErrorEmbed(client, err, interaction.guild, interaction);
|
|
2730
2587
|
throw err;
|
|
2731
2588
|
}
|
|
2732
2589
|
}
|
|
@@ -2734,9 +2591,22 @@ var defaultPrefixCommandHandler = new EventBuilder({
|
|
|
2734
2591
|
var defaultContextCommandHandler = new EventBuilder({
|
|
2735
2592
|
event: "interactionCreate",
|
|
2736
2593
|
name: "ContextCommandHandler",
|
|
2737
|
-
execute(client, interaction) {
|
|
2594
|
+
async execute(client, interaction) {
|
|
2738
2595
|
if (!interaction.isContextMenuCommand()) return;
|
|
2739
|
-
|
|
2596
|
+
const command = client.commands.context.get(interaction.commandName);
|
|
2597
|
+
if (!command) {
|
|
2598
|
+
const content = `**${interaction.commandName}** is not a registered context command.`;
|
|
2599
|
+
if (interaction.replied || interaction.deferred) {
|
|
2600
|
+
return interaction.followUp({ content, flags: "Ephemeral" });
|
|
2601
|
+
}
|
|
2602
|
+
return interaction.reply({ content, flags: "Ephemeral" });
|
|
2603
|
+
}
|
|
2604
|
+
try {
|
|
2605
|
+
return await command.run(client, client, interaction);
|
|
2606
|
+
} catch (err) {
|
|
2607
|
+
await sendCommandErrorEmbed(client, err, interaction.guild, interaction);
|
|
2608
|
+
throw err;
|
|
2609
|
+
}
|
|
2740
2610
|
}
|
|
2741
2611
|
});
|
|
2742
2612
|
|
|
@@ -2751,8 +2621,8 @@ try {
|
|
|
2751
2621
|
}
|
|
2752
2622
|
var globalInstanceEmitter = new import_node_events2.default();
|
|
2753
2623
|
var instances = [];
|
|
2754
|
-
async function useMongoDatabase(
|
|
2755
|
-
const instance = instances.at(
|
|
2624
|
+
async function useMongoDatabase(instanceIndex) {
|
|
2625
|
+
const instance = instances.at(instanceIndex ?? 0);
|
|
2756
2626
|
if (!instance) {
|
|
2757
2627
|
return new Promise((resolve, reject) => {
|
|
2758
2628
|
const timeout = setTimeout(() => reject("useMongoDatabase timed out"), 45e3);
|
|
@@ -2764,6 +2634,15 @@ async function useMongoDatabase(index) {
|
|
|
2764
2634
|
}
|
|
2765
2635
|
return instance;
|
|
2766
2636
|
}
|
|
2637
|
+
async function useReadyMongoDatabase(instanceIndex) {
|
|
2638
|
+
const instance = await useMongoDatabase(instanceIndex);
|
|
2639
|
+
await instance.waitForReady();
|
|
2640
|
+
return instance;
|
|
2641
|
+
}
|
|
2642
|
+
async function createMongoSession(instanceIndex, options) {
|
|
2643
|
+
const instance = await useReadyMongoDatabase(instanceIndex);
|
|
2644
|
+
return instance.mongoose.startSession(options);
|
|
2645
|
+
}
|
|
2767
2646
|
var MongoDatabase = class {
|
|
2768
2647
|
constructor(client, options) {
|
|
2769
2648
|
this.client = client;
|
|
@@ -2918,6 +2797,7 @@ var MongoSchemaBuilder = class {
|
|
|
2918
2797
|
this.eventEmitter.off(event, listener);
|
|
2919
2798
|
return this;
|
|
2920
2799
|
}
|
|
2800
|
+
/** Execute a function while ensuring the connection is ready. On error it will retry using an exponential backoff. */
|
|
2921
2801
|
async execute(fn) {
|
|
2922
2802
|
try {
|
|
2923
2803
|
if (!this.isReady) {
|
|
@@ -2954,9 +2834,9 @@ var MongoSchemaBuilder = class {
|
|
|
2954
2834
|
return id;
|
|
2955
2835
|
});
|
|
2956
2836
|
}
|
|
2957
|
-
async count(filter) {
|
|
2837
|
+
async count(filter, options) {
|
|
2958
2838
|
return await this.execute(async () => {
|
|
2959
|
-
return this.model.countDocuments(filter);
|
|
2839
|
+
return this.model.countDocuments(filter, options);
|
|
2960
2840
|
});
|
|
2961
2841
|
}
|
|
2962
2842
|
async exists(filter) {
|
|
@@ -2964,29 +2844,29 @@ var MongoSchemaBuilder = class {
|
|
|
2964
2844
|
return await this.model.exists(filter) ? true : false;
|
|
2965
2845
|
});
|
|
2966
2846
|
}
|
|
2967
|
-
async create(query) {
|
|
2847
|
+
async create(query, options) {
|
|
2968
2848
|
return await this.execute(async () => {
|
|
2969
|
-
return this.model.create(query);
|
|
2970
|
-
});
|
|
2849
|
+
return this.model.create(query, options);
|
|
2850
|
+
}) ?? [];
|
|
2971
2851
|
}
|
|
2972
2852
|
async upsert(filter, query, options) {
|
|
2973
2853
|
return await this.execute(async () => {
|
|
2974
2854
|
return this.model.findOneAndUpdate(filter, query, { ...options, upsert: true, new: true });
|
|
2975
2855
|
});
|
|
2976
2856
|
}
|
|
2977
|
-
async delete(filter) {
|
|
2857
|
+
async delete(filter, options) {
|
|
2978
2858
|
return await this.execute(async () => {
|
|
2979
|
-
return this.model.deleteOne(filter);
|
|
2859
|
+
return this.model.deleteOne(filter, options);
|
|
2980
2860
|
});
|
|
2981
2861
|
}
|
|
2982
|
-
async deleteAll(filter) {
|
|
2862
|
+
async deleteAll(filter, options) {
|
|
2983
2863
|
return await this.execute(async () => {
|
|
2984
|
-
return this.model.deleteMany(filter);
|
|
2864
|
+
return this.model.deleteMany(filter, options);
|
|
2985
2865
|
});
|
|
2986
2866
|
}
|
|
2987
|
-
async distinct(key, filter) {
|
|
2867
|
+
async distinct(key, filter, options) {
|
|
2988
2868
|
return await this.execute(async () => {
|
|
2989
|
-
return this.model.distinct(key, filter);
|
|
2869
|
+
return this.model.distinct(key, filter, options);
|
|
2990
2870
|
});
|
|
2991
2871
|
}
|
|
2992
2872
|
async fetch(filter, projection, options) {
|
|
@@ -3017,6 +2897,215 @@ var MongoSchemaBuilder = class {
|
|
|
3017
2897
|
}
|
|
3018
2898
|
};
|
|
3019
2899
|
|
|
2900
|
+
// src/tools/BetterCollector.ts
|
|
2901
|
+
var CollectorTimeoutType = /* @__PURE__ */ ((CollectorTimeoutType2) => {
|
|
2902
|
+
CollectorTimeoutType2[CollectorTimeoutType2["DisableComponents"] = 0] = "DisableComponents";
|
|
2903
|
+
CollectorTimeoutType2[CollectorTimeoutType2["DeleteMessage"] = 1] = "DeleteMessage";
|
|
2904
|
+
CollectorTimeoutType2[CollectorTimeoutType2["DoNothing"] = 2] = "DoNothing";
|
|
2905
|
+
return CollectorTimeoutType2;
|
|
2906
|
+
})(CollectorTimeoutType || {});
|
|
2907
|
+
var BetterCollector = class _BetterCollector {
|
|
2908
|
+
message;
|
|
2909
|
+
collector;
|
|
2910
|
+
options;
|
|
2911
|
+
activeUsers = /* @__PURE__ */ new Set();
|
|
2912
|
+
participantWarningCooldowns = /* @__PURE__ */ new Map();
|
|
2913
|
+
config;
|
|
2914
|
+
events = {
|
|
2915
|
+
collectId: /* @__PURE__ */ new Map(),
|
|
2916
|
+
collect: [],
|
|
2917
|
+
end: [],
|
|
2918
|
+
timeout: []
|
|
2919
|
+
};
|
|
2920
|
+
static create(message, options) {
|
|
2921
|
+
return new _BetterCollector(message, options);
|
|
2922
|
+
}
|
|
2923
|
+
async validateParticipant(interaction, participants) {
|
|
2924
|
+
const allowedParticipants = participants || this.options?.participants || [];
|
|
2925
|
+
if (!allowedParticipants.length) return true;
|
|
2926
|
+
const isAllowed = allowedParticipants.some((user) => {
|
|
2927
|
+
if (typeof user === "string") return user === interaction.user.id;
|
|
2928
|
+
if (typeof user === "object" && "id" in user) return user.id === interaction.user.id;
|
|
2929
|
+
return false;
|
|
2930
|
+
});
|
|
2931
|
+
if (!isAllowed) {
|
|
2932
|
+
const now = Date.now();
|
|
2933
|
+
const lastWarned = this.participantWarningCooldowns.get(interaction.user.id) || 0;
|
|
2934
|
+
if (now - lastWarned > this.config.collector.notAParticipantWarningCooldown) {
|
|
2935
|
+
this.participantWarningCooldowns.set(interaction.user.id, now);
|
|
2936
|
+
if (this.config.collector.notAParticipantMessage) {
|
|
2937
|
+
await interaction.reply({
|
|
2938
|
+
content: this.config.collector.notAParticipantMessage,
|
|
2939
|
+
flags: "Ephemeral"
|
|
2940
|
+
}).catch(() => {
|
|
2941
|
+
});
|
|
2942
|
+
} else {
|
|
2943
|
+
await interaction.deferUpdate().catch(() => {
|
|
2944
|
+
});
|
|
2945
|
+
}
|
|
2946
|
+
} else {
|
|
2947
|
+
await interaction.deferUpdate().catch(() => {
|
|
2948
|
+
});
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
return isAllowed;
|
|
2952
|
+
}
|
|
2953
|
+
build() {
|
|
2954
|
+
if (!this.message) return;
|
|
2955
|
+
if (this.collector) return;
|
|
2956
|
+
this.collector = this.message.createMessageComponentCollector({
|
|
2957
|
+
idle: this.options?.idle ?? this.config.timeouts.collectorIdle,
|
|
2958
|
+
time: this.options?.timeout ?? this.config.timeouts.collectorTimeout,
|
|
2959
|
+
componentType: this.options?.type,
|
|
2960
|
+
max: this.options?.max,
|
|
2961
|
+
maxComponents: this.options?.maxComponents,
|
|
2962
|
+
maxUsers: this.options?.maxUsers
|
|
2963
|
+
});
|
|
2964
|
+
this.setupListeners();
|
|
2965
|
+
}
|
|
2966
|
+
setupListeners() {
|
|
2967
|
+
if (!this.collector) return;
|
|
2968
|
+
this.collector.on("collect", async (interaction) => {
|
|
2969
|
+
if (this.options?.userLock && this.activeUsers.has(interaction.user.id)) {
|
|
2970
|
+
return interaction.reply({ content: this.config.collector.userLockMessage, flags: "Ephemeral" }).catch(() => {
|
|
2971
|
+
});
|
|
2972
|
+
}
|
|
2973
|
+
if (this.options?.userLock) {
|
|
2974
|
+
this.activeUsers.add(interaction.user.id);
|
|
2975
|
+
}
|
|
2976
|
+
const globalListeners = this.events.collect;
|
|
2977
|
+
const idListeners = this.events.collectId.get(interaction.customId) || [];
|
|
2978
|
+
const allListeners = [...globalListeners, ...idListeners];
|
|
2979
|
+
const shouldBeDeferred = allListeners.find((l) => l.options?.defer)?.options?.defer;
|
|
2980
|
+
const validListeners = [];
|
|
2981
|
+
for (const listener of allListeners) {
|
|
2982
|
+
const isAllowed = await this.validateParticipant(interaction, listener.options?.participants);
|
|
2983
|
+
if (isAllowed) validListeners.push(listener);
|
|
2984
|
+
}
|
|
2985
|
+
if (validListeners.length === 0) return;
|
|
2986
|
+
try {
|
|
2987
|
+
if (shouldBeDeferred) {
|
|
2988
|
+
if (typeof shouldBeDeferred === "object") {
|
|
2989
|
+
if (shouldBeDeferred.update) {
|
|
2990
|
+
await interaction.deferUpdate().catch(Boolean);
|
|
2991
|
+
} else {
|
|
2992
|
+
await interaction.deferReply({ flags: shouldBeDeferred.ephemeral ? "Ephemeral" : void 0 }).catch(Boolean);
|
|
2993
|
+
}
|
|
2994
|
+
} else {
|
|
2995
|
+
await interaction.deferReply().catch(Boolean);
|
|
2996
|
+
}
|
|
2997
|
+
}
|
|
2998
|
+
if (this.options?.sequential) {
|
|
2999
|
+
for (const listener of allListeners) {
|
|
3000
|
+
try {
|
|
3001
|
+
const isAllowed = await this.validateParticipant(interaction, listener.options?.participants);
|
|
3002
|
+
if (!isAllowed) return;
|
|
3003
|
+
await listener.fn(interaction).finally(() => listener.options?.finally?.(interaction));
|
|
3004
|
+
} catch (err) {
|
|
3005
|
+
this.handleListenerError(err);
|
|
3006
|
+
}
|
|
3007
|
+
}
|
|
3008
|
+
} else {
|
|
3009
|
+
Promise.all(
|
|
3010
|
+
allListeners.map((l) => {
|
|
3011
|
+
const isAllowed = this.validateParticipant(interaction, l.options?.participants);
|
|
3012
|
+
if (!isAllowed) return;
|
|
3013
|
+
return l.fn(interaction).catch(this.handleListenerError).finally(() => l.options?.finally?.(interaction));
|
|
3014
|
+
})
|
|
3015
|
+
);
|
|
3016
|
+
}
|
|
3017
|
+
} finally {
|
|
3018
|
+
if (this.options?.userLock) {
|
|
3019
|
+
this.activeUsers.delete(interaction.user.id);
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
3022
|
+
});
|
|
3023
|
+
this.collector.on("end", async (collected, reason) => {
|
|
3024
|
+
if (this.options?.sequential) {
|
|
3025
|
+
for (const listener of this.events.end) {
|
|
3026
|
+
try {
|
|
3027
|
+
await listener.fn(collected, reason);
|
|
3028
|
+
} catch (err) {
|
|
3029
|
+
this.handleListenerError(err);
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
} else {
|
|
3033
|
+
Promise.all(this.events.end.map((l) => l.fn(collected, reason).catch(this.handleListenerError)));
|
|
3034
|
+
}
|
|
3035
|
+
switch (this.options?.onTimeout) {
|
|
3036
|
+
case 0 /* DisableComponents */:
|
|
3037
|
+
if (!this.message?.editable) break;
|
|
3038
|
+
try {
|
|
3039
|
+
const disabledRows = this.message.components.map((row) => {
|
|
3040
|
+
const updatedRow = row.toJSON();
|
|
3041
|
+
if ("components" in updatedRow) {
|
|
3042
|
+
updatedRow.components = updatedRow.components.map((component) => ({
|
|
3043
|
+
...component,
|
|
3044
|
+
disabled: true
|
|
3045
|
+
}));
|
|
3046
|
+
}
|
|
3047
|
+
return updatedRow;
|
|
3048
|
+
});
|
|
3049
|
+
await this.message.edit({ components: disabledRows });
|
|
3050
|
+
} catch (err) {
|
|
3051
|
+
if (!(err instanceof Error && err.message.includes("Unknown Message"))) {
|
|
3052
|
+
this.handleListenerError(err);
|
|
3053
|
+
}
|
|
3054
|
+
}
|
|
3055
|
+
break;
|
|
3056
|
+
case 1 /* DeleteMessage */:
|
|
3057
|
+
if (!this.message?.deletable) break;
|
|
3058
|
+
await this.message.delete().catch(Boolean);
|
|
3059
|
+
break;
|
|
3060
|
+
case 2 /* DoNothing */:
|
|
3061
|
+
default:
|
|
3062
|
+
break;
|
|
3063
|
+
}
|
|
3064
|
+
});
|
|
3065
|
+
}
|
|
3066
|
+
handleListenerError(err) {
|
|
3067
|
+
console.error("[BetterCollector] Listener Error:", err);
|
|
3068
|
+
}
|
|
3069
|
+
constructor(message, options) {
|
|
3070
|
+
this.config = options?.config || globalVimcordToolsConfig;
|
|
3071
|
+
this.message = message || void 0;
|
|
3072
|
+
this.options = options;
|
|
3073
|
+
this.build();
|
|
3074
|
+
}
|
|
3075
|
+
on(idOrFunc, fnOrOptions, options) {
|
|
3076
|
+
let finalFn;
|
|
3077
|
+
let finalOptions;
|
|
3078
|
+
let customId;
|
|
3079
|
+
if (typeof idOrFunc === "function") {
|
|
3080
|
+
finalFn = idOrFunc;
|
|
3081
|
+
finalOptions = fnOrOptions;
|
|
3082
|
+
} else {
|
|
3083
|
+
if (typeof fnOrOptions !== "function") {
|
|
3084
|
+
throw new Error("[BetterCollector] Second argument must be a function when a customId is provided.");
|
|
3085
|
+
}
|
|
3086
|
+
customId = idOrFunc;
|
|
3087
|
+
finalFn = fnOrOptions;
|
|
3088
|
+
finalOptions = options;
|
|
3089
|
+
}
|
|
3090
|
+
if (customId) {
|
|
3091
|
+
const listeners = this.events.collectId.get(customId) || [];
|
|
3092
|
+
listeners.push({ fn: finalFn, options: finalOptions });
|
|
3093
|
+
this.events.collectId.set(customId, listeners);
|
|
3094
|
+
} else {
|
|
3095
|
+
this.events.collect.push({ fn: finalFn, options: finalOptions });
|
|
3096
|
+
}
|
|
3097
|
+
return this;
|
|
3098
|
+
}
|
|
3099
|
+
onEnd(fn, options) {
|
|
3100
|
+
this.events.end.push({ fn, options });
|
|
3101
|
+
return this;
|
|
3102
|
+
}
|
|
3103
|
+
/** Manually stop the collector and trigger cleanup */
|
|
3104
|
+
stop(reason = "manual") {
|
|
3105
|
+
this.collector?.stop(reason);
|
|
3106
|
+
}
|
|
3107
|
+
};
|
|
3108
|
+
|
|
3020
3109
|
// src/tools/BetterContainer.ts
|
|
3021
3110
|
var import_discord11 = require("discord.js");
|
|
3022
3111
|
var BetterContainer = class {
|
|
@@ -3057,7 +3146,9 @@ var BetterContainer = class {
|
|
|
3057
3146
|
return this;
|
|
3058
3147
|
}
|
|
3059
3148
|
addText(text) {
|
|
3060
|
-
this.container.addTextDisplayComponents(
|
|
3149
|
+
this.container.addTextDisplayComponents(
|
|
3150
|
+
(tdb) => tdb.setContent(Array.isArray(text) ? text.filter((t) => t !== null && t !== void 0).join("\n") : text)
|
|
3151
|
+
);
|
|
3061
3152
|
return this;
|
|
3062
3153
|
}
|
|
3063
3154
|
addMedia(...media) {
|
|
@@ -3081,7 +3172,9 @@ var BetterContainer = class {
|
|
|
3081
3172
|
this.container.addSectionComponents((sb) => {
|
|
3082
3173
|
if (data.text) {
|
|
3083
3174
|
sb.addTextDisplayComponents(
|
|
3084
|
-
(tdb) => tdb.setContent(
|
|
3175
|
+
(tdb) => tdb.setContent(
|
|
3176
|
+
Array.isArray(data.text) ? data.text.filter((t) => t !== null && t !== void 0).join("\n") : data.text
|
|
3177
|
+
)
|
|
3085
3178
|
);
|
|
3086
3179
|
}
|
|
3087
3180
|
if (data.thumbnail) sb.setThumbnailAccessory(new import_discord11.ThumbnailBuilder(data.thumbnail));
|
|
@@ -3312,6 +3405,7 @@ var PaginationTimeoutType = /* @__PURE__ */ ((PaginationTimeoutType2) => {
|
|
|
3312
3405
|
PaginationTimeoutType2[PaginationTimeoutType2["DisableComponents"] = 0] = "DisableComponents";
|
|
3313
3406
|
PaginationTimeoutType2[PaginationTimeoutType2["ClearComponents"] = 1] = "ClearComponents";
|
|
3314
3407
|
PaginationTimeoutType2[PaginationTimeoutType2["DeleteMessage"] = 2] = "DeleteMessage";
|
|
3408
|
+
PaginationTimeoutType2[PaginationTimeoutType2["DoNothing"] = 3] = "DoNothing";
|
|
3315
3409
|
return PaginationTimeoutType2;
|
|
3316
3410
|
})(PaginationTimeoutType || {});
|
|
3317
3411
|
function wrapPositive(num, max) {
|
|
@@ -3392,7 +3486,8 @@ var Paginator = class {
|
|
|
3392
3486
|
last: [],
|
|
3393
3487
|
collect: [],
|
|
3394
3488
|
react: [],
|
|
3395
|
-
|
|
3489
|
+
preTimeout: [],
|
|
3490
|
+
postTimeout: []
|
|
3396
3491
|
};
|
|
3397
3492
|
if (this.options.pages.length) {
|
|
3398
3493
|
this.addChapter(this.options.pages, { label: "Default" });
|
|
@@ -3459,16 +3554,23 @@ var Paginator = class {
|
|
|
3459
3554
|
embeds: [],
|
|
3460
3555
|
components: [],
|
|
3461
3556
|
flags: [],
|
|
3557
|
+
files: [],
|
|
3558
|
+
// Explicitly empty to clear previous files on page switch
|
|
3462
3559
|
...options,
|
|
3463
3560
|
withResponse: true
|
|
3464
3561
|
};
|
|
3465
3562
|
const page = this.data.page.current;
|
|
3563
|
+
const currentChapter = this.chapters[this.data.page.index.chapter];
|
|
3564
|
+
const chapterFile = currentChapter?.files?.[this.data.page.index.nested];
|
|
3565
|
+
if (chapterFile) sendOptions.files.push(chapterFile);
|
|
3466
3566
|
if (Array.isArray(page)) {
|
|
3467
3567
|
sendOptions.embeds.push(...page);
|
|
3468
3568
|
} else if (typeof page === "string") {
|
|
3469
3569
|
sendOptions.content = page;
|
|
3470
3570
|
} else if (isEmbed(page)) {
|
|
3471
3571
|
sendOptions.embeds.push(page);
|
|
3572
|
+
} else if (page instanceof import_discord13.AttachmentBuilder) {
|
|
3573
|
+
sendOptions.files.push(page);
|
|
3472
3574
|
} else if (page instanceof import_discord13.ContainerBuilder || page instanceof BetterContainer) {
|
|
3473
3575
|
sendOptions.components.push(page);
|
|
3474
3576
|
if (!sendOptions.flags.includes("IsComponentsV2")) {
|
|
@@ -3480,7 +3582,7 @@ var Paginator = class {
|
|
|
3480
3582
|
}
|
|
3481
3583
|
async handlePostTimeout() {
|
|
3482
3584
|
if (!this.data.message) return;
|
|
3483
|
-
this.callEventStack("
|
|
3585
|
+
this.callEventStack("preTimeout", this.data.message);
|
|
3484
3586
|
this.data.collectors.component?.stop();
|
|
3485
3587
|
this.data.collectors.reaction?.stop();
|
|
3486
3588
|
switch (this.options.onTimeout) {
|
|
@@ -3524,7 +3626,10 @@ var Paginator = class {
|
|
|
3524
3626
|
case 2 /* DeleteMessage */:
|
|
3525
3627
|
await this.data.message.delete().catch(Boolean);
|
|
3526
3628
|
break;
|
|
3629
|
+
case 3 /* DoNothing */:
|
|
3630
|
+
break;
|
|
3527
3631
|
}
|
|
3632
|
+
this.callEventStack("postTimeout", this.data.message);
|
|
3528
3633
|
}
|
|
3529
3634
|
async nav_removeFromMessage() {
|
|
3530
3635
|
if (!this.data.message?.editable) return;
|
|
@@ -3571,35 +3676,43 @@ var Paginator = class {
|
|
|
3571
3676
|
await i.reply({ content: "Jump not implemented yet.", flags: "Ephemeral" });
|
|
3572
3677
|
return;
|
|
3573
3678
|
}
|
|
3574
|
-
await i.deferUpdate().catch(Boolean);
|
|
3575
3679
|
switch (i.customId) {
|
|
3576
3680
|
case "ssm_chapterSelect":
|
|
3681
|
+
await i.deferUpdate().catch(Boolean);
|
|
3577
3682
|
const chapterIndex = this.chapters.findIndex(
|
|
3578
3683
|
(c) => c.id === i.values[0]
|
|
3579
3684
|
);
|
|
3580
3685
|
await this.setPage(chapterIndex, 0);
|
|
3686
|
+
await this.refresh();
|
|
3581
3687
|
break;
|
|
3582
3688
|
case "btn_first":
|
|
3689
|
+
await i.deferUpdate().catch(Boolean);
|
|
3583
3690
|
this.callEventStack("first", this.data.page.current, this.data.page.index);
|
|
3584
3691
|
await this.setPage(this.data.page.index.chapter, 0);
|
|
3692
|
+
await this.refresh();
|
|
3585
3693
|
break;
|
|
3586
3694
|
case "btn_back":
|
|
3695
|
+
await i.deferUpdate().catch(Boolean);
|
|
3587
3696
|
this.callEventStack("back", this.data.page.current, this.data.page.index);
|
|
3588
3697
|
await this.setPage(this.data.page.index.chapter, this.data.page.index.nested - 1);
|
|
3698
|
+
await this.refresh();
|
|
3589
3699
|
break;
|
|
3590
3700
|
case "btn_next":
|
|
3701
|
+
await i.deferUpdate().catch(Boolean);
|
|
3591
3702
|
this.callEventStack("next", this.data.page.current, this.data.page.index);
|
|
3592
3703
|
await this.setPage(this.data.page.index.chapter, this.data.page.index.nested + 1);
|
|
3704
|
+
await this.refresh();
|
|
3593
3705
|
break;
|
|
3594
3706
|
case "btn_last":
|
|
3707
|
+
await i.deferUpdate().catch(Boolean);
|
|
3595
3708
|
this.callEventStack("last", this.data.page.current, this.data.page.index);
|
|
3596
3709
|
await this.setPage(
|
|
3597
3710
|
this.data.page.index.chapter,
|
|
3598
3711
|
this.chapters[this.data.page.index.chapter].pages.length - 1
|
|
3599
3712
|
);
|
|
3713
|
+
await this.refresh();
|
|
3600
3714
|
break;
|
|
3601
3715
|
}
|
|
3602
|
-
await this.refresh();
|
|
3603
3716
|
} catch (err) {
|
|
3604
3717
|
console.error("[Paginator] Component navigation error", err);
|
|
3605
3718
|
}
|
|
@@ -3639,7 +3752,7 @@ var Paginator = class {
|
|
|
3639
3752
|
data.value = `ssm_c:${this.chapters.length}`;
|
|
3640
3753
|
}
|
|
3641
3754
|
const normalizedPages = resolvePages(pages);
|
|
3642
|
-
this.chapters.push({ id: data.value, pages: normalizedPages });
|
|
3755
|
+
this.chapters.push({ id: data.value, pages: normalizedPages, files: data.files });
|
|
3643
3756
|
this.data.components.chapterSelect.addOptions(data);
|
|
3644
3757
|
return this;
|
|
3645
3758
|
}
|
|
@@ -3747,6 +3860,7 @@ var Prompt = class {
|
|
|
3747
3860
|
content;
|
|
3748
3861
|
embed;
|
|
3749
3862
|
container;
|
|
3863
|
+
textOnly;
|
|
3750
3864
|
buttons;
|
|
3751
3865
|
customButtons;
|
|
3752
3866
|
onResolve;
|
|
@@ -3760,6 +3874,7 @@ var Prompt = class {
|
|
|
3760
3874
|
this.content = options.content;
|
|
3761
3875
|
this.embed = options.embed ?? this.createDefaultForm();
|
|
3762
3876
|
this.container = options?.container;
|
|
3877
|
+
this.textOnly = options.textOnly;
|
|
3763
3878
|
this.buttons = this.createButtons(options.buttons);
|
|
3764
3879
|
this.customButtons = this.createCustomButtons(options.customButtons);
|
|
3765
3880
|
this.onResolve = options.onResolve ?? [3 /* DeleteOnConfirm */, 4 /* DeleteOnReject */];
|
|
@@ -3839,7 +3954,7 @@ var Prompt = class {
|
|
|
3839
3954
|
}
|
|
3840
3955
|
buildSendOptions(options) {
|
|
3841
3956
|
const sendData = { ...options };
|
|
3842
|
-
if (this.container) {
|
|
3957
|
+
if (!this.textOnly && this.container) {
|
|
3843
3958
|
sendData.components = Array.isArray(sendData.components) ? [...sendData.components, this.container] : [this.container];
|
|
3844
3959
|
const existingFlags = sendData.flags ? Array.isArray(sendData.flags) ? sendData.flags : [sendData.flags] : [];
|
|
3845
3960
|
if (!existingFlags.includes("IsComponentsV2")) {
|
|
@@ -3848,7 +3963,9 @@ var Prompt = class {
|
|
|
3848
3963
|
sendData.flags = existingFlags;
|
|
3849
3964
|
}
|
|
3850
3965
|
} else {
|
|
3851
|
-
|
|
3966
|
+
if (!this.textOnly) {
|
|
3967
|
+
sendData.embeds = Array.isArray(sendData.embeds) ? [this.embed, ...sendData.embeds] : [this.embed];
|
|
3968
|
+
}
|
|
3852
3969
|
}
|
|
3853
3970
|
if (this.content) {
|
|
3854
3971
|
sendData.content = this.content;
|
|
@@ -3934,7 +4051,7 @@ async function prompt(handler, options, sendOptions) {
|
|
|
3934
4051
|
|
|
3935
4052
|
// src/utils/VimcordCLI.ts
|
|
3936
4053
|
var import_node_readline = require("readline");
|
|
3937
|
-
var
|
|
4054
|
+
var import_qznt3 = require("qznt");
|
|
3938
4055
|
var VimcordCLI = class {
|
|
3939
4056
|
rl;
|
|
3940
4057
|
options;
|
|
@@ -3973,7 +4090,7 @@ var VimcordCLI = class {
|
|
|
3973
4090
|
return { isCommand: true, commandName, content: args.join(" "), args };
|
|
3974
4091
|
}
|
|
3975
4092
|
getClientInstance(line) {
|
|
3976
|
-
const clientIndex =
|
|
4093
|
+
const clientIndex = import_qznt3.$.str.getFlag(line, "--client", 1) || import_qznt3.$.str.getFlag(line, "-c", 1);
|
|
3977
4094
|
if (clientIndex) {
|
|
3978
4095
|
const idx = Number(clientIndex);
|
|
3979
4096
|
if (isNaN(idx)) {
|
|
@@ -4016,21 +4133,25 @@ CLI.addCommand("help", "View information about a command, or the available CLI o
|
|
|
4016
4133
|
}
|
|
4017
4134
|
CLI.logger.table("(help)", helpList);
|
|
4018
4135
|
});
|
|
4019
|
-
CLI.addCommand("register", "Register app commands globally, or per guild", async (args, content) => {
|
|
4136
|
+
CLI.addCommand("register", "Register app commands (slash & context) globally, or per guild", async (args, content) => {
|
|
4020
4137
|
const client = CLI.getClientInstance(content);
|
|
4021
4138
|
if (!client) return;
|
|
4022
4139
|
const mode = args[0]?.toLowerCase() || "";
|
|
4023
4140
|
if (!["guild", "global"].includes(mode)) {
|
|
4024
4141
|
return CLI.logger.error(`'${mode}' is not a valid option. Your options are [guild|global]`);
|
|
4025
4142
|
}
|
|
4026
|
-
let guildIds = (
|
|
4143
|
+
let guildIds = (import_qznt3.$.str.getFlag(content, "--guilds", 1) || import_qznt3.$.str.getFlag(content, "-g", 1) || "").replaceAll(/["']/g, "").split(" ").filter(Boolean).map((s) => s.replaceAll(",", "").trim());
|
|
4027
4144
|
if (!guildIds.length) guildIds = client.guilds.cache.map((g) => g.id);
|
|
4028
4145
|
switch (mode) {
|
|
4029
4146
|
case "guild":
|
|
4147
|
+
CLI.logger.info("Registering guild commands...");
|
|
4030
4148
|
await client.commands.slash.registerGuild({ guilds: guildIds });
|
|
4149
|
+
await client.commands.context.registerGuild({ guilds: guildIds });
|
|
4031
4150
|
break;
|
|
4032
4151
|
case "global":
|
|
4152
|
+
CLI.logger.info("Registering global commands...");
|
|
4033
4153
|
await client.commands.slash.registerGlobal();
|
|
4154
|
+
await client.commands.context.registerGlobal();
|
|
4034
4155
|
break;
|
|
4035
4156
|
}
|
|
4036
4157
|
});
|
|
@@ -4041,14 +4162,18 @@ CLI.addCommand("unregister", "Unregister app commands globally, or per guild", a
|
|
|
4041
4162
|
if (!["guild", "global"].includes(mode)) {
|
|
4042
4163
|
return CLI.logger.error(`'${mode}' is not a valid option. Your options are [guild|global]`);
|
|
4043
4164
|
}
|
|
4044
|
-
let guildIds = (
|
|
4165
|
+
let guildIds = (import_qznt3.$.str.getFlag(content, "--guilds", 1) || import_qznt3.$.str.getFlag(content, "-g", 1) || "").replaceAll(/["']/g, "").split(" ").filter(Boolean).map((s) => s.replaceAll(",", "").trim());
|
|
4045
4166
|
if (!guildIds.length) guildIds = client.guilds.cache.map((g) => g.id);
|
|
4046
4167
|
switch (mode) {
|
|
4047
4168
|
case "guild":
|
|
4169
|
+
CLI.logger.info("Unregistering guild commands...");
|
|
4048
4170
|
await client.commands.slash.unregisterGuild({ guilds: guildIds });
|
|
4171
|
+
await client.commands.context.unregisterGuild({ guilds: guildIds });
|
|
4049
4172
|
break;
|
|
4050
4173
|
case "global":
|
|
4174
|
+
CLI.logger.info("Unregistering global commands...");
|
|
4051
4175
|
await client.commands.slash.unregisterGlobal();
|
|
4176
|
+
await client.commands.context.unregisterGlobal();
|
|
4052
4177
|
break;
|
|
4053
4178
|
}
|
|
4054
4179
|
});
|
|
@@ -4056,53 +4181,55 @@ CLI.addCommand("stats", "View statistics about a client instance", (args, conten
|
|
|
4056
4181
|
const client = CLI.getClientInstance(content);
|
|
4057
4182
|
if (!client) return;
|
|
4058
4183
|
CLI.logger.table(`(stats) ~ ${client.config.app.name}`, {
|
|
4059
|
-
"Guilds:":
|
|
4184
|
+
"Guilds:": import_qznt3.$.format.number(client.guilds.cache.size),
|
|
4060
4185
|
"Ping:": `${client.ws.ping || 0}ms`,
|
|
4061
|
-
"Uptime:": `${
|
|
4186
|
+
"Uptime:": `${import_qznt3.$.math.secs(client.uptime || 0)}s`,
|
|
4062
4187
|
"Process Uptime:": `${Math.floor(process.uptime())}s`,
|
|
4063
4188
|
"Memory Usage:": `${(process.memoryUsage().rss / 1024 / 1024).toFixed(2)} MB`
|
|
4064
4189
|
});
|
|
4065
4190
|
});
|
|
4066
|
-
CLI.addCommand("cmds", "List the loaded commands", (args, content) => {
|
|
4191
|
+
CLI.addCommand("cmds", "List the loaded commands", async (args, content) => {
|
|
4067
4192
|
const client = CLI.getClientInstance(content);
|
|
4068
4193
|
if (!client) return;
|
|
4069
|
-
const mode = args[0] || "slash";
|
|
4194
|
+
const mode = (args[0] || "slash").toLowerCase();
|
|
4070
4195
|
switch (mode) {
|
|
4071
|
-
case "slash":
|
|
4072
|
-
const
|
|
4073
|
-
|
|
4074
|
-
const
|
|
4075
|
-
for (const cmd of
|
|
4076
|
-
|
|
4196
|
+
case "slash": {
|
|
4197
|
+
const commands = Array.from(client.commands.slash.commands.values());
|
|
4198
|
+
commands.sort((a, b) => a.builder.name.localeCompare(b.builder.name));
|
|
4199
|
+
const tableData = {};
|
|
4200
|
+
for (const cmd of commands) {
|
|
4201
|
+
tableData[`/${cmd.builder.name}`] = `~ ${cmd.builder.description || "No description"}`;
|
|
4077
4202
|
}
|
|
4078
|
-
return CLI.logger.table(
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
);
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4203
|
+
return CLI.logger.table(`(cmds) ~ slash (${import_qznt3.$.format.number(commands.length)})`, tableData);
|
|
4204
|
+
}
|
|
4205
|
+
case "prefix": {
|
|
4206
|
+
const commands = Array.from(client.commands.prefix.commands.values());
|
|
4207
|
+
commands.sort((a, b) => {
|
|
4208
|
+
const nameA = a.toConfig().name;
|
|
4209
|
+
const nameB = b.toConfig().name;
|
|
4210
|
+
return nameA.localeCompare(nameB);
|
|
4211
|
+
});
|
|
4212
|
+
const tableData = {};
|
|
4213
|
+
const defaultPrefix = client.config.prefixCommands.defaultPrefix;
|
|
4214
|
+
for (const cmd of commands) {
|
|
4215
|
+
const config = cmd.toConfig();
|
|
4216
|
+
const aliasIndicator = config.aliases?.length ? ` [${config.aliases.join(", ")}]` : "";
|
|
4217
|
+
tableData[`${defaultPrefix}${config.name}${aliasIndicator}`] = `~ ${config.description || "No description"}`;
|
|
4088
4218
|
}
|
|
4089
|
-
return CLI.logger.table(
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
);
|
|
4093
|
-
|
|
4094
|
-
const
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
contextCommands_f[`${cmd.builder.name}`] = "";
|
|
4219
|
+
return CLI.logger.table(`(cmds) ~ prefix (${import_qznt3.$.format.number(commands.length)})`, tableData);
|
|
4220
|
+
}
|
|
4221
|
+
case "ctx": {
|
|
4222
|
+
const commands = Array.from(client.commands.context.commands.values());
|
|
4223
|
+
commands.sort((a, b) => a.builder.name.localeCompare(b.builder.name));
|
|
4224
|
+
const tableData = {};
|
|
4225
|
+
for (const cmd of commands) {
|
|
4226
|
+
const type = cmd.builder.type === 2 ? "User" : "Msg";
|
|
4227
|
+
tableData[`[${type}] ${cmd.builder.name}`] = "";
|
|
4099
4228
|
}
|
|
4100
|
-
return CLI.logger.table(
|
|
4101
|
-
|
|
4102
|
-
contextCommands_f
|
|
4103
|
-
);
|
|
4229
|
+
return CLI.logger.table(`(cmds) ~ ctx (${import_qznt3.$.format.number(commands.length)})`, tableData);
|
|
4230
|
+
}
|
|
4104
4231
|
default:
|
|
4105
|
-
return CLI.logger.error(`'${mode}' is not a valid option.
|
|
4232
|
+
return CLI.logger.error(`'${mode}' is not a valid option. Valid options: [slash|prefix|ctx]`);
|
|
4106
4233
|
}
|
|
4107
4234
|
});
|
|
4108
4235
|
function initCLI() {
|
|
@@ -4126,17 +4253,39 @@ function createClient(options, features = {}, config = {}) {
|
|
|
4126
4253
|
function getClientInstances() {
|
|
4127
4254
|
return clientInstances;
|
|
4128
4255
|
}
|
|
4256
|
+
|
|
4257
|
+
// src/utils/random.ts
|
|
4258
|
+
function pickRandom(arr, options) {
|
|
4259
|
+
const _rnd = () => {
|
|
4260
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
4261
|
+
};
|
|
4262
|
+
let att = 0;
|
|
4263
|
+
let candidate = _rnd();
|
|
4264
|
+
if (options?.notEqualTo !== void 0 && arr.length > 1) {
|
|
4265
|
+
while (candidate === options.notEqualTo) {
|
|
4266
|
+
if (att < (options?.maxRerollAttempts ?? 100)) {
|
|
4267
|
+
throw new Error(`pickRandom reached max reroll attempts (${options?.maxRerollAttempts ?? 100})`);
|
|
4268
|
+
}
|
|
4269
|
+
candidate = _rnd();
|
|
4270
|
+
att++;
|
|
4271
|
+
}
|
|
4272
|
+
}
|
|
4273
|
+
return options?.clone ? structuredClone(candidate) : candidate;
|
|
4274
|
+
}
|
|
4129
4275
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4130
4276
|
0 && (module.exports = {
|
|
4131
4277
|
BaseCommandBuilder,
|
|
4278
|
+
BetterCollector,
|
|
4132
4279
|
BetterContainer,
|
|
4133
4280
|
BetterEmbed,
|
|
4134
4281
|
BetterModal,
|
|
4135
4282
|
CLI,
|
|
4283
|
+
CollectorTimeoutType,
|
|
4136
4284
|
CommandType,
|
|
4137
4285
|
ContextCommandBuilder,
|
|
4138
4286
|
DynaSend,
|
|
4139
4287
|
EventBuilder,
|
|
4288
|
+
LOGGER_COLORS,
|
|
4140
4289
|
LogLevel,
|
|
4141
4290
|
Logger,
|
|
4142
4291
|
MissingPermissionReason,
|
|
@@ -4165,6 +4314,7 @@ function getClientInstances() {
|
|
|
4165
4314
|
clientInstances,
|
|
4166
4315
|
createClient,
|
|
4167
4316
|
createMongoSchema,
|
|
4317
|
+
createMongoSession,
|
|
4168
4318
|
createToolsConfig,
|
|
4169
4319
|
createVimcordAppConfig,
|
|
4170
4320
|
createVimcordContextCommandConfig,
|
|
@@ -4198,6 +4348,7 @@ function getClientInstances() {
|
|
|
4198
4348
|
useClient,
|
|
4199
4349
|
useMongoDatabase,
|
|
4200
4350
|
useReadyClient,
|
|
4351
|
+
useReadyMongoDatabase,
|
|
4201
4352
|
validateCommandPermissions
|
|
4202
4353
|
});
|
|
4203
4354
|
//# sourceMappingURL=index.cjs.map
|