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.js
CHANGED
|
@@ -6,11 +6,11 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
// src/types/command.base.ts
|
|
9
|
-
var CommandType = /* @__PURE__ */ ((
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return
|
|
9
|
+
var CommandType = /* @__PURE__ */ ((CommandType2) => {
|
|
10
|
+
CommandType2[CommandType2["Slash"] = 0] = "Slash";
|
|
11
|
+
CommandType2[CommandType2["Prefix"] = 1] = "Prefix";
|
|
12
|
+
CommandType2[CommandType2["Context"] = 2] = "Context";
|
|
13
|
+
return CommandType2;
|
|
14
14
|
})(CommandType || {});
|
|
15
15
|
var MissingPermissionReason = /* @__PURE__ */ ((MissingPermissionReason2) => {
|
|
16
16
|
MissingPermissionReason2[MissingPermissionReason2["User"] = 0] = "User";
|
|
@@ -134,270 +134,239 @@ import _ from "lodash";
|
|
|
134
134
|
var BaseCommandBuilder = class {
|
|
135
135
|
uuid = randomUUID();
|
|
136
136
|
commandType;
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
channelRateLimitData = /* @__PURE__ */ new Map();
|
|
155
|
-
constructor(type, config) {
|
|
137
|
+
/** Local command configuration and hooks */
|
|
138
|
+
options;
|
|
139
|
+
/** Internal state for rate limiting across different scopes */
|
|
140
|
+
rlStores = {
|
|
141
|
+
[3 /* Global */]: { executions: 0, timestamp: 0 },
|
|
142
|
+
[0 /* User */]: /* @__PURE__ */ new Map(),
|
|
143
|
+
[1 /* Guild */]: /* @__PURE__ */ new Map(),
|
|
144
|
+
[2 /* Channel */]: /* @__PURE__ */ new Map()
|
|
145
|
+
};
|
|
146
|
+
/** * Mapping of CommandTypes to their respective config keys in the Vimcord client
|
|
147
|
+
*/
|
|
148
|
+
typeConfigMapping = {
|
|
149
|
+
[0 /* Slash */]: "slashCommands",
|
|
150
|
+
[1 /* Prefix */]: "prefixCommands",
|
|
151
|
+
[2 /* Context */]: "contextCommands"
|
|
152
|
+
};
|
|
153
|
+
constructor(type, options = {}) {
|
|
156
154
|
this.commandType = type;
|
|
157
|
-
this.
|
|
158
|
-
this.conditions = config?.conditions;
|
|
159
|
-
this.permissions = config?.permissions;
|
|
160
|
-
this.metadata = config?.metadata;
|
|
161
|
-
this.rateLimit = config?.rateLimit;
|
|
162
|
-
this.beforeExecute = config?.beforeExecute;
|
|
163
|
-
this.execute = config?.execute;
|
|
164
|
-
this.afterExecute = config?.afterExecute;
|
|
165
|
-
this.onRateLimit = config?.onRateLimit;
|
|
166
|
-
this.onMissingPermissions = config?.onMissingPermissions;
|
|
167
|
-
this.onConditionsNotMet = config?.onConditionsNotMet;
|
|
168
|
-
this.onUsedWhenDisabled = config?.onUsedWhenDisabled;
|
|
169
|
-
this.onError = config?.onError;
|
|
170
|
-
this.validateBaseConfig();
|
|
155
|
+
this.options = { enabled: true, ...options };
|
|
171
156
|
}
|
|
172
157
|
validateBaseConfig() {
|
|
173
|
-
if (this.rateLimit) {
|
|
174
|
-
|
|
175
|
-
|
|
158
|
+
if (this.options.rateLimit) {
|
|
159
|
+
const { max, interval } = this.options.rateLimit;
|
|
160
|
+
if (max <= 0 || interval <= 0) {
|
|
161
|
+
throw new Error(`[Vimcord:${this.constructor.name}] Rate limit values must be positive.`);
|
|
176
162
|
}
|
|
177
|
-
|
|
178
|
-
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Resolves the final configuration by merging layers:
|
|
167
|
+
* Client Defaults < Client Type-Specific < Local Command Options
|
|
168
|
+
*/
|
|
169
|
+
resolveConfig(client) {
|
|
170
|
+
const typeKey = this.typeConfigMapping[this.commandType];
|
|
171
|
+
const typeSpecificGlobals = client.config?.[typeKey] || {};
|
|
172
|
+
return _.merge({}, typeSpecificGlobals, this.options);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Executes the command lifecycle.
|
|
176
|
+
* Merges global client config with local command options at runtime.
|
|
177
|
+
*/
|
|
178
|
+
async run(client, ...args) {
|
|
179
|
+
const config = this.resolveConfig(client);
|
|
180
|
+
const ctx = this.extractContext(args);
|
|
181
|
+
try {
|
|
182
|
+
if (!config.enabled) {
|
|
183
|
+
return await config.onUsedWhenDisabled?.(...args);
|
|
184
|
+
}
|
|
185
|
+
if (this.isRateLimited(config, ctx)) {
|
|
186
|
+
return await config.onRateLimit?.(...args);
|
|
179
187
|
}
|
|
188
|
+
const perms = this.checkPermissions(client, ctx.member || ctx.user, args[1]);
|
|
189
|
+
if (!perms.validated) {
|
|
190
|
+
return await config.onMissingPermissions?.(perms, ...args);
|
|
191
|
+
}
|
|
192
|
+
if (!await this.checkConditions(config, ...args)) {
|
|
193
|
+
return await config.onConditionsNotMet?.(...args);
|
|
194
|
+
}
|
|
195
|
+
await config.beforeExecute?.(...args);
|
|
196
|
+
if (config.logExecution !== false) {
|
|
197
|
+
const cmdName = this.options.name || this.builder?.name || "Unknown";
|
|
198
|
+
const location = ctx.guild ? `${ctx.guild.name} (${ctx.guild.id})` : "Direct Messages";
|
|
199
|
+
client.logger.commandExecuted(cmdName, ctx.user.username, location);
|
|
200
|
+
}
|
|
201
|
+
const result = await config.execute?.(...args);
|
|
202
|
+
await config.afterExecute?.(result, ...args);
|
|
203
|
+
} catch (error) {
|
|
204
|
+
await this.handleError(error, config, ...args);
|
|
180
205
|
}
|
|
181
206
|
}
|
|
182
|
-
|
|
207
|
+
/**
|
|
208
|
+
* Internal logic to determine if a command execution should be throttled.
|
|
209
|
+
* @param config The merged configuration to use for limits.
|
|
210
|
+
* @param ctx Extracted Discord context (User, Guild, Channel).
|
|
211
|
+
*/
|
|
212
|
+
isRateLimited(config, ctx) {
|
|
213
|
+
if (!config.rateLimit) return false;
|
|
214
|
+
const { scope, interval, max } = config.rateLimit;
|
|
215
|
+
const now = Date.now();
|
|
216
|
+
const key = this.getScopeKey(scope, ctx);
|
|
217
|
+
if (scope !== 3 /* Global */ && !key) return false;
|
|
218
|
+
let data;
|
|
219
|
+
if (scope === 3 /* Global */) {
|
|
220
|
+
data = this.rlStores[3 /* Global */];
|
|
221
|
+
} else {
|
|
222
|
+
const store = this.rlStores[scope];
|
|
223
|
+
data = store.get(key) ?? { executions: 0, timestamp: now };
|
|
224
|
+
store.set(key, data);
|
|
225
|
+
}
|
|
226
|
+
if (now - data.timestamp > interval) {
|
|
227
|
+
data.executions = 0;
|
|
228
|
+
data.timestamp = now;
|
|
229
|
+
}
|
|
230
|
+
if (data.executions >= max) return true;
|
|
231
|
+
data.executions++;
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Validates if the user has required permissions.
|
|
236
|
+
*/
|
|
237
|
+
checkPermissions(client, user, target) {
|
|
238
|
+
if (!this.options.permissions) return { validated: true };
|
|
239
|
+
return validateCommandPermissions(this.options.permissions, client, user, target);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Evaluates all custom conditions defined for the command.
|
|
243
|
+
*/
|
|
244
|
+
async checkConditions(config, ...args) {
|
|
245
|
+
if (!config.conditions?.length) return true;
|
|
246
|
+
const results = await Promise.all(config.conditions.map((c) => c(...args)));
|
|
247
|
+
return results.every(Boolean);
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Normalizes the trigger arguments into a standard context object.
|
|
251
|
+
*/
|
|
252
|
+
extractContext(args) {
|
|
253
|
+
const event = args[1];
|
|
183
254
|
return {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
rateLimit: this.rateLimit,
|
|
189
|
-
beforeExecute: this.beforeExecute,
|
|
190
|
-
execute: this.execute,
|
|
191
|
-
afterExecute: this.afterExecute,
|
|
192
|
-
onMissingPermissions: this.onMissingPermissions,
|
|
193
|
-
onConditionsNotMet: this.onConditionsNotMet,
|
|
194
|
-
onUsedWhenDisabled: this.onUsedWhenDisabled,
|
|
195
|
-
onRateLimit: this.onRateLimit,
|
|
196
|
-
onError: this.onError
|
|
255
|
+
user: event.user || event.author,
|
|
256
|
+
member: event.member,
|
|
257
|
+
guild: event.guild,
|
|
258
|
+
channel: event.channel
|
|
197
259
|
};
|
|
198
260
|
}
|
|
261
|
+
/**
|
|
262
|
+
* Resolves the storage key based on the RateLimit scope.
|
|
263
|
+
*/
|
|
264
|
+
getScopeKey(scope, ctx) {
|
|
265
|
+
switch (scope) {
|
|
266
|
+
case 0 /* User */:
|
|
267
|
+
return ctx.user.id;
|
|
268
|
+
case 1 /* Guild */:
|
|
269
|
+
return ctx.guild?.id ?? null;
|
|
270
|
+
case 2 /* Channel */:
|
|
271
|
+
return ctx.channel?.id ?? null;
|
|
272
|
+
default:
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Handles command errors by checking local handlers before falling back to global handlers.
|
|
278
|
+
*/
|
|
279
|
+
async handleError(err, config, ...args) {
|
|
280
|
+
if (config.onError) return config.onError(err, ...args);
|
|
281
|
+
throw err;
|
|
282
|
+
}
|
|
283
|
+
/** Toggle command availability */
|
|
199
284
|
setEnabled(enabled) {
|
|
200
|
-
this.enabled = enabled;
|
|
285
|
+
this.options.enabled = enabled;
|
|
286
|
+
return this;
|
|
287
|
+
}
|
|
288
|
+
/** Merge new permission requirements into the existing ones */
|
|
289
|
+
setPermissions(perms) {
|
|
290
|
+
this.options.permissions = _.merge(this.options.permissions || {}, perms);
|
|
201
291
|
return this;
|
|
202
292
|
}
|
|
293
|
+
/** Add custom logic checks that run before execution */
|
|
203
294
|
addConditions(...conditions) {
|
|
204
|
-
|
|
205
|
-
this.conditions.push(...conditions);
|
|
295
|
+
this.options.conditions = [...this.options.conditions || [], ...conditions];
|
|
206
296
|
return this;
|
|
207
297
|
}
|
|
208
|
-
|
|
209
|
-
|
|
298
|
+
/** Set the primary command execution logic */
|
|
299
|
+
setExecute(fn) {
|
|
300
|
+
this.options.execute = fn;
|
|
210
301
|
return this;
|
|
211
302
|
}
|
|
212
|
-
|
|
213
|
-
|
|
303
|
+
/** * Set the custom conditions that must be met for this command to execute
|
|
304
|
+
*/
|
|
305
|
+
setConditions(conditions) {
|
|
306
|
+
this.options.conditions = conditions;
|
|
214
307
|
return this;
|
|
215
308
|
}
|
|
309
|
+
/** * Set the command metadata configuration
|
|
310
|
+
*/
|
|
216
311
|
setMetadata(metadata) {
|
|
217
|
-
this.metadata = _.merge(this.metadata, metadata);
|
|
312
|
+
this.options.metadata = _.merge(this.options.metadata || {}, metadata);
|
|
218
313
|
return this;
|
|
219
314
|
}
|
|
315
|
+
/** * Set the rate limiting options for this command
|
|
316
|
+
*/
|
|
220
317
|
setRateLimit(options) {
|
|
221
|
-
this.rateLimit = options;
|
|
318
|
+
this.options.rateLimit = options;
|
|
319
|
+
this.validateBaseConfig();
|
|
222
320
|
return this;
|
|
223
321
|
}
|
|
224
|
-
|
|
225
|
-
|
|
322
|
+
/** * Set whether to log whenever this command is executed
|
|
323
|
+
* @default true
|
|
324
|
+
*/
|
|
325
|
+
setLogExecution(log) {
|
|
326
|
+
this.options.logExecution = log;
|
|
226
327
|
return this;
|
|
227
328
|
}
|
|
228
|
-
|
|
229
|
-
|
|
329
|
+
/** * Set the function to execute before the main command logic
|
|
330
|
+
*/
|
|
331
|
+
setBeforeExecute(callback) {
|
|
332
|
+
this.options.beforeExecute = callback;
|
|
230
333
|
return this;
|
|
231
334
|
}
|
|
335
|
+
/** * Set the function to execute after successful command execution
|
|
336
|
+
*/
|
|
232
337
|
setAfterExecute(callback) {
|
|
233
|
-
this.afterExecute = callback;
|
|
234
|
-
return this;
|
|
235
|
-
}
|
|
236
|
-
setOnRateLimit(callback) {
|
|
237
|
-
this.onRateLimit = callback;
|
|
338
|
+
this.options.afterExecute = callback;
|
|
238
339
|
return this;
|
|
239
340
|
}
|
|
341
|
+
/** * Set the function to execute when the required permissions are not met
|
|
342
|
+
*/
|
|
240
343
|
setOnMissingPermissions(callback) {
|
|
241
|
-
this.onMissingPermissions = callback;
|
|
344
|
+
this.options.onMissingPermissions = callback;
|
|
242
345
|
return this;
|
|
243
346
|
}
|
|
347
|
+
/** * Set the function to execute when the required conditions are not met
|
|
348
|
+
*/
|
|
244
349
|
setOnConditionsNotMet(callback) {
|
|
245
|
-
this.onConditionsNotMet = callback;
|
|
350
|
+
this.options.onConditionsNotMet = callback;
|
|
246
351
|
return this;
|
|
247
352
|
}
|
|
353
|
+
/** * Set the function to execute when this command is used when its disabled
|
|
354
|
+
*/
|
|
248
355
|
setOnUsedWhenDisabled(callback) {
|
|
249
|
-
this.onUsedWhenDisabled = callback;
|
|
356
|
+
this.options.onUsedWhenDisabled = callback;
|
|
250
357
|
return this;
|
|
251
358
|
}
|
|
252
|
-
|
|
253
|
-
|
|
359
|
+
/** * Set the function to execute when the rate limit is hit
|
|
360
|
+
*/
|
|
361
|
+
setOnRateLimit(callback) {
|
|
362
|
+
this.options.onRateLimit = callback;
|
|
254
363
|
return this;
|
|
255
364
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
if (!user) return null;
|
|
262
|
-
rateLimitData = this.userRateLimitData.get(user.id) ?? { executions: 0, timestamp: 0 };
|
|
263
|
-
break;
|
|
264
|
-
case 1 /* Guild */:
|
|
265
|
-
if (!guild) return null;
|
|
266
|
-
rateLimitData = this.guildRateLimitData.get(guild.id) ?? { executions: 0, timestamp: 0 };
|
|
267
|
-
break;
|
|
268
|
-
case 2 /* Channel */:
|
|
269
|
-
if (!channel) return null;
|
|
270
|
-
rateLimitData = this.channelRateLimitData.get(channel.id) ?? { executions: 0, timestamp: 0 };
|
|
271
|
-
break;
|
|
272
|
-
case 3 /* Global */:
|
|
273
|
-
rateLimitData = this.globalRateLimitData;
|
|
274
|
-
break;
|
|
275
|
-
default:
|
|
276
|
-
return null;
|
|
277
|
-
}
|
|
278
|
-
return { ...rateLimitData, isLimited: this.isRateLimited(user, guild, channel, false) };
|
|
279
|
-
}
|
|
280
|
-
isRateLimited(user, guild, channel, updateExecutions = true) {
|
|
281
|
-
if (!this.rateLimit) return false;
|
|
282
|
-
const now = Date.now();
|
|
283
|
-
let rateLimitData;
|
|
284
|
-
switch (this.rateLimit.scope) {
|
|
285
|
-
case 0 /* User */:
|
|
286
|
-
if (!user) return false;
|
|
287
|
-
rateLimitData = this.userRateLimitData.get(user.id) ?? { executions: 0, timestamp: 0 };
|
|
288
|
-
if (now - rateLimitData.timestamp >= this.rateLimit.interval) {
|
|
289
|
-
rateLimitData.executions = 0;
|
|
290
|
-
rateLimitData.timestamp = now;
|
|
291
|
-
}
|
|
292
|
-
if (updateExecutions) rateLimitData.executions++;
|
|
293
|
-
this.userRateLimitData.set(user.id, rateLimitData);
|
|
294
|
-
break;
|
|
295
|
-
case 1 /* Guild */:
|
|
296
|
-
if (!guild) return false;
|
|
297
|
-
rateLimitData = this.guildRateLimitData.get(guild.id) ?? { executions: 0, timestamp: 0 };
|
|
298
|
-
if (now - rateLimitData.timestamp >= this.rateLimit.interval) {
|
|
299
|
-
rateLimitData.executions = 0;
|
|
300
|
-
rateLimitData.timestamp = now;
|
|
301
|
-
}
|
|
302
|
-
if (updateExecutions) rateLimitData.executions++;
|
|
303
|
-
this.guildRateLimitData.set(guild.id, rateLimitData);
|
|
304
|
-
break;
|
|
305
|
-
case 2 /* Channel */:
|
|
306
|
-
if (!channel) return false;
|
|
307
|
-
rateLimitData = this.guildRateLimitData.get(channel.id) ?? { executions: 0, timestamp: 0 };
|
|
308
|
-
if (now - rateLimitData.timestamp >= this.rateLimit.interval) {
|
|
309
|
-
rateLimitData.executions = 0;
|
|
310
|
-
rateLimitData.timestamp = now;
|
|
311
|
-
}
|
|
312
|
-
if (updateExecutions) rateLimitData.executions++;
|
|
313
|
-
this.channelRateLimitData.set(channel.id, rateLimitData);
|
|
314
|
-
break;
|
|
315
|
-
case 3 /* Global */:
|
|
316
|
-
rateLimitData = this.globalRateLimitData;
|
|
317
|
-
if (now - rateLimitData.timestamp >= this.rateLimit.interval) {
|
|
318
|
-
rateLimitData.executions = 0;
|
|
319
|
-
rateLimitData.timestamp = now;
|
|
320
|
-
}
|
|
321
|
-
if (updateExecutions) rateLimitData.executions++;
|
|
322
|
-
this.globalRateLimitData = rateLimitData;
|
|
323
|
-
break;
|
|
324
|
-
}
|
|
325
|
-
return rateLimitData.executions >= this.rateLimit.max;
|
|
326
|
-
}
|
|
327
|
-
checkPermissions(client, user, command) {
|
|
328
|
-
if (!this.permissions) return { validated: true };
|
|
329
|
-
return validateCommandPermissions(this.permissions, client, user, command);
|
|
330
|
-
}
|
|
331
|
-
async checkConditions(...args) {
|
|
332
|
-
if (!this.conditions?.length) return true;
|
|
333
|
-
const results = await Promise.all(this.conditions.map((condition) => condition(...args)));
|
|
334
|
-
return results.every(Boolean);
|
|
335
|
-
}
|
|
336
|
-
async _runPreflight(clientConfig, command, ...args) {
|
|
337
|
-
try {
|
|
338
|
-
if (!this.enabled) {
|
|
339
|
-
await clientConfig.onUsedWhenDisabled?.(...args);
|
|
340
|
-
await this.onUsedWhenDisabled?.(...args);
|
|
341
|
-
return;
|
|
342
|
-
}
|
|
343
|
-
if (this.isRateLimited(args[1]?.member || args[1]?.author, args[1].guild, args[1].channel)) {
|
|
344
|
-
await clientConfig.onRateLimit?.(...args);
|
|
345
|
-
await this.rateLimit?.onRateLimit?.(...args);
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
const permissionResults = this.checkPermissions(
|
|
349
|
-
args[0],
|
|
350
|
-
args[1]?.member || args[1]?.author || args[1]?.user,
|
|
351
|
-
command
|
|
352
|
-
);
|
|
353
|
-
if (!permissionResults.validated) {
|
|
354
|
-
await clientConfig.onMissingPermissions?.(permissionResults, ...args);
|
|
355
|
-
await this.onMissingPermissions?.(permissionResults, ...args);
|
|
356
|
-
return;
|
|
357
|
-
}
|
|
358
|
-
if (!await this.checkConditions(...args)) {
|
|
359
|
-
await clientConfig.onConditionsNotMet?.(...args);
|
|
360
|
-
await this.onConditionsNotMet?.(...args);
|
|
361
|
-
return;
|
|
362
|
-
}
|
|
363
|
-
} catch (err) {
|
|
364
|
-
if (this.onError) {
|
|
365
|
-
return this.onError(err, ...args);
|
|
366
|
-
} else if (clientConfig.onError) {
|
|
367
|
-
return clientConfig.onError(err, ...args);
|
|
368
|
-
} else {
|
|
369
|
-
throw err;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
async _runCabinCheck(clientConfig, ...args) {
|
|
374
|
-
try {
|
|
375
|
-
await clientConfig.beforeExecute?.(...args);
|
|
376
|
-
await this.beforeExecute?.(...args);
|
|
377
|
-
} catch (err) {
|
|
378
|
-
if (this.onError) {
|
|
379
|
-
return this.onError(err, ...args);
|
|
380
|
-
} else if (clientConfig.onError) {
|
|
381
|
-
return clientConfig.onError(err, ...args);
|
|
382
|
-
} else {
|
|
383
|
-
throw err;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
async _runFlyAndLand(clientConfig, ...args) {
|
|
388
|
-
try {
|
|
389
|
-
const result = await this.execute?.(...args);
|
|
390
|
-
await clientConfig?.afterExecute?.(result, ...args);
|
|
391
|
-
await this.afterExecute?.(result, ...args);
|
|
392
|
-
} catch (err) {
|
|
393
|
-
if (this.onError) {
|
|
394
|
-
return this.onError(err, ...args);
|
|
395
|
-
} else if (clientConfig.onError) {
|
|
396
|
-
return clientConfig.onError(err, ...args);
|
|
397
|
-
} else {
|
|
398
|
-
throw err;
|
|
399
|
-
}
|
|
400
|
-
}
|
|
365
|
+
/** * Set a custom error handler for this command
|
|
366
|
+
*/
|
|
367
|
+
setOnError(callback) {
|
|
368
|
+
this.options.onError = callback;
|
|
369
|
+
return this;
|
|
401
370
|
}
|
|
402
371
|
};
|
|
403
372
|
|
|
@@ -406,79 +375,54 @@ import { ContextMenuCommandBuilder } from "discord.js";
|
|
|
406
375
|
import _2 from "lodash";
|
|
407
376
|
var ContextCommandBuilder = class extends BaseCommandBuilder {
|
|
408
377
|
builder;
|
|
409
|
-
deferReply;
|
|
410
|
-
deployment;
|
|
411
378
|
constructor(config) {
|
|
412
379
|
super(2 /* Context */, config);
|
|
413
380
|
this.setBuilder(config.builder);
|
|
414
|
-
|
|
415
|
-
this.
|
|
416
|
-
|
|
381
|
+
const originalExecute = this.options.execute;
|
|
382
|
+
this.options.execute = async (client, interaction) => {
|
|
383
|
+
return await this.handleExecution(client, interaction, originalExecute);
|
|
384
|
+
};
|
|
417
385
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
try {
|
|
423
|
-
this.builder.toJSON();
|
|
424
|
-
} catch (err) {
|
|
425
|
-
throw new Error("VContextCommandBuilder: Invalid command builder", { cause: err });
|
|
386
|
+
async handleExecution(client, interaction, originalExecute) {
|
|
387
|
+
const config = this.resolveConfig(client);
|
|
388
|
+
if (config.deferReply && !interaction.replied && !interaction.deferred) {
|
|
389
|
+
await interaction.deferReply(typeof config.deferReply === "object" ? config.deferReply : void 0);
|
|
426
390
|
}
|
|
391
|
+
return await originalExecute?.(client, interaction);
|
|
427
392
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
return {
|
|
432
|
-
...super.toConfig(),
|
|
433
|
-
builder: this.builder,
|
|
434
|
-
deferReply: this.deferReply,
|
|
435
|
-
deployment: this.deployment
|
|
436
|
-
};
|
|
393
|
+
validateBuilder() {
|
|
394
|
+
if (!this.builder.name) throw new Error(`[Vimcord] ContextCommandBuilder: Command name is required.`);
|
|
395
|
+
this.builder.toJSON();
|
|
437
396
|
}
|
|
397
|
+
// --- Specialized Fluent API ---
|
|
438
398
|
setBuilder(builder) {
|
|
439
|
-
|
|
440
|
-
this.builder = builder(new ContextMenuCommandBuilder());
|
|
441
|
-
} else {
|
|
442
|
-
this.builder = builder;
|
|
443
|
-
}
|
|
399
|
+
this.builder = typeof builder === "function" ? builder(new ContextMenuCommandBuilder()) : builder;
|
|
444
400
|
this.validateBuilder();
|
|
445
401
|
return this;
|
|
446
402
|
}
|
|
447
403
|
setDeferReply(defer) {
|
|
448
|
-
this.deferReply = defer;
|
|
404
|
+
this.options.deferReply = defer;
|
|
449
405
|
return this;
|
|
450
406
|
}
|
|
451
407
|
setDeployment(deployment) {
|
|
452
|
-
this.deployment = _2.merge(this.deployment, deployment);
|
|
408
|
+
this.options.deployment = _2.merge(this.options.deployment || {}, deployment);
|
|
453
409
|
return this;
|
|
454
410
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
await this.
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
if (this.onError) {
|
|
465
|
-
return this.onError(err, client, interaction);
|
|
466
|
-
} else if (client.config.contextCommands.onError) {
|
|
467
|
-
return client.config.contextCommands.onError(err, client, interaction);
|
|
468
|
-
} else {
|
|
469
|
-
throw err;
|
|
470
|
-
}
|
|
471
|
-
} finally {
|
|
472
|
-
if (client.config.contextCommands.logExecution) {
|
|
473
|
-
client.logger.commandExecuted(this.builder.name, interaction.user.username, interaction.guild?.name);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
411
|
+
setExecute(fn) {
|
|
412
|
+
const originalExecute = fn;
|
|
413
|
+
this.options.execute = async (client, interaction) => {
|
|
414
|
+
return await this.handleExecution(client, interaction, originalExecute);
|
|
415
|
+
};
|
|
416
|
+
return this;
|
|
417
|
+
}
|
|
418
|
+
toConfig() {
|
|
419
|
+
return { ...this.options, builder: this.builder };
|
|
476
420
|
}
|
|
477
421
|
};
|
|
478
422
|
|
|
479
423
|
// src/utils/dir.ts
|
|
480
|
-
import jsTools from "jstools";
|
|
481
424
|
import path from "path";
|
|
425
|
+
import { $ } from "qznt";
|
|
482
426
|
function getProcessDir() {
|
|
483
427
|
const mainPath = process.argv[1];
|
|
484
428
|
if (!mainPath) return "";
|
|
@@ -488,7 +432,7 @@ async function importModulesFromDir(dir, fnPrefix) {
|
|
|
488
432
|
const cwd = getProcessDir();
|
|
489
433
|
const MODULE_RELATIVE_PATH = path.join(cwd, dir);
|
|
490
434
|
const MODULE_LOG_PATH = dir;
|
|
491
|
-
const files =
|
|
435
|
+
const files = $.fs.readDir(MODULE_RELATIVE_PATH).filter(
|
|
492
436
|
(fn) => fn.endsWith(`${fnPrefix ? `.${fnPrefix}` : ""}.js`) || fn.endsWith(`${fnPrefix ? `.${fnPrefix}` : ""}.ts`)
|
|
493
437
|
);
|
|
494
438
|
if (!files.length) {
|
|
@@ -719,39 +663,74 @@ var EventBuilder = class _EventBuilder {
|
|
|
719
663
|
|
|
720
664
|
// src/builders/prefixCommand.builder.ts
|
|
721
665
|
var PrefixCommandBuilder = class extends BaseCommandBuilder {
|
|
722
|
-
name;
|
|
723
|
-
aliases;
|
|
724
|
-
description;
|
|
725
666
|
constructor(config) {
|
|
726
667
|
super(1 /* Prefix */, config);
|
|
727
|
-
|
|
728
|
-
this.
|
|
729
|
-
|
|
668
|
+
const originalExecute = this.options.execute;
|
|
669
|
+
this.options.execute = async (client, message) => {
|
|
670
|
+
return await this.handleExecution(client, message, originalExecute);
|
|
671
|
+
};
|
|
672
|
+
this.validatePrefixConfig();
|
|
730
673
|
}
|
|
731
|
-
|
|
674
|
+
/**
|
|
675
|
+
* Specialized execution logic for Prefix Commands.
|
|
676
|
+
*/
|
|
677
|
+
async handleExecution(client, message, originalExecute) {
|
|
678
|
+
return await originalExecute?.(client, message);
|
|
679
|
+
}
|
|
680
|
+
validatePrefixConfig() {
|
|
681
|
+
if (!this.options.name) {
|
|
682
|
+
throw new Error(`[Vimcord] PrefixCommandBuilder: Command name is required.`);
|
|
683
|
+
}
|
|
732
684
|
}
|
|
685
|
+
// --- Fluent API (Prefix Specific Only) ---
|
|
686
|
+
/**
|
|
687
|
+
* Set the primary name of the command.
|
|
688
|
+
*/
|
|
689
|
+
setName(name) {
|
|
690
|
+
this.options.name = name;
|
|
691
|
+
return this;
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Set or replace the command aliases.
|
|
695
|
+
*/
|
|
696
|
+
setAliases(aliases) {
|
|
697
|
+
this.options.aliases = aliases;
|
|
698
|
+
return this;
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* Add additional aliases without clearing existing ones.
|
|
702
|
+
*/
|
|
703
|
+
addAliases(...aliases) {
|
|
704
|
+
this.options.aliases = [...this.options.aliases || [], ...aliases];
|
|
705
|
+
return this;
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Set the command description.
|
|
709
|
+
*/
|
|
710
|
+
setDescription(description) {
|
|
711
|
+
this.options.description = description;
|
|
712
|
+
return this;
|
|
713
|
+
}
|
|
714
|
+
// --- Overrides ---
|
|
715
|
+
/**
|
|
716
|
+
* Override setExecute to ensure handleExecution remains the entry point.
|
|
717
|
+
* This is the only base method we need to redefine.
|
|
718
|
+
*/
|
|
719
|
+
setExecute(fn) {
|
|
720
|
+
const originalExecute = fn;
|
|
721
|
+
this.options.execute = async (client, message) => {
|
|
722
|
+
return await this.handleExecution(client, message, originalExecute);
|
|
723
|
+
};
|
|
724
|
+
return this;
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* Converts the current builder state back into a config object.
|
|
728
|
+
*/
|
|
733
729
|
toConfig() {
|
|
734
730
|
return {
|
|
735
|
-
...
|
|
736
|
-
name: this.name,
|
|
737
|
-
description: this.description
|
|
731
|
+
...this.options
|
|
738
732
|
};
|
|
739
733
|
}
|
|
740
|
-
async executeCommand(client, message) {
|
|
741
|
-
try {
|
|
742
|
-
await this._runPreflight(client.config.prefixCommands, this.name, client, message);
|
|
743
|
-
await this._runCabinCheck(client.config.prefixCommands, client, message);
|
|
744
|
-
return this._runFlyAndLand(client.config.prefixCommands, client, message);
|
|
745
|
-
} catch (err) {
|
|
746
|
-
this.onError?.(err, client, message);
|
|
747
|
-
client.config.prefixCommands.onError?.(err, client, message);
|
|
748
|
-
throw err;
|
|
749
|
-
} finally {
|
|
750
|
-
if (client.config.prefixCommands.logExecution) {
|
|
751
|
-
client.logger.commandExecuted(this.name, message.author.username, message.guild?.name);
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
734
|
};
|
|
756
735
|
|
|
757
736
|
// src/builders/slashCommand.builder.ts
|
|
@@ -759,110 +738,81 @@ import { SlashCommandBuilder as DJSSlashCommandBuilder } from "discord.js";
|
|
|
759
738
|
import _4 from "lodash";
|
|
760
739
|
var SlashCommandBuilder = class extends BaseCommandBuilder {
|
|
761
740
|
builder;
|
|
762
|
-
deferReply;
|
|
763
|
-
deployment;
|
|
764
741
|
routes = /* @__PURE__ */ new Map();
|
|
765
|
-
onUnknownRouteHandler;
|
|
766
742
|
constructor(config) {
|
|
767
743
|
super(0 /* Slash */, config);
|
|
768
744
|
this.setBuilder(config.builder);
|
|
769
|
-
this.
|
|
770
|
-
|
|
771
|
-
this.
|
|
772
|
-
|
|
745
|
+
if (config.routes) this.addRoutes(...config.routes);
|
|
746
|
+
const originalExecute = this.options.execute;
|
|
747
|
+
this.options.execute = async (client, interaction) => {
|
|
748
|
+
return await this.handleExecution(client, interaction, originalExecute);
|
|
749
|
+
};
|
|
773
750
|
}
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
751
|
+
async handleExecution(client, interaction, originalExecute) {
|
|
752
|
+
const config = this.resolveConfig(client);
|
|
753
|
+
if (config.deferReply && !interaction.replied && !interaction.deferred) {
|
|
754
|
+
await interaction.deferReply(typeof config.deferReply === "object" ? config.deferReply : void 0);
|
|
777
755
|
}
|
|
778
|
-
|
|
779
|
-
|
|
756
|
+
const subCommand = interaction.options.getSubcommand(false);
|
|
757
|
+
if (subCommand) {
|
|
758
|
+
const handler = this.routes.get(subCommand.toLowerCase());
|
|
759
|
+
if (handler) return await handler(client, interaction);
|
|
760
|
+
if (config.onUnknownRouteHandler) return await config.onUnknownRouteHandler(client, interaction);
|
|
780
761
|
}
|
|
781
|
-
|
|
782
|
-
this.builder.toJSON();
|
|
783
|
-
} catch (err) {
|
|
784
|
-
throw new Error("VSlashCommandBuilder: Invalid command builder", { cause: err });
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
validateConfig() {
|
|
762
|
+
return await originalExecute?.(client, interaction);
|
|
788
763
|
}
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
deferReply: this.deferReply,
|
|
794
|
-
deployment: this.deployment,
|
|
795
|
-
routes: this.routes.size ? Array.from(this.routes.entries()).map(([k, v]) => ({ name: k, handler: v })) : void 0,
|
|
796
|
-
onUnknownRouteHandler: this.onUnknownRouteHandler
|
|
797
|
-
};
|
|
764
|
+
validateBuilder() {
|
|
765
|
+
if (!this.builder.name) throw new Error(`[Vimcord] SlashCommandBuilder: Command name is required.`);
|
|
766
|
+
if (!this.builder.description) throw new Error(`[Vimcord] SlashCommandBuilder: Command description is required.`);
|
|
767
|
+
this.builder.toJSON();
|
|
798
768
|
}
|
|
769
|
+
// --- Specialized Fluent API ---
|
|
799
770
|
setBuilder(builder) {
|
|
800
|
-
|
|
801
|
-
this.builder = builder(new DJSSlashCommandBuilder());
|
|
802
|
-
} else {
|
|
803
|
-
this.builder = builder;
|
|
804
|
-
}
|
|
771
|
+
this.builder = typeof builder === "function" ? builder(new DJSSlashCommandBuilder()) : builder;
|
|
805
772
|
this.validateBuilder();
|
|
806
773
|
return this;
|
|
807
774
|
}
|
|
808
775
|
setDeferReply(defer) {
|
|
809
|
-
this.deferReply = defer;
|
|
776
|
+
this.options.deferReply = defer;
|
|
810
777
|
return this;
|
|
811
778
|
}
|
|
812
779
|
setDeployment(deployment) {
|
|
813
|
-
this.deployment = _4.merge(this.deployment, deployment);
|
|
780
|
+
this.options.deployment = _4.merge(this.options.deployment || {}, deployment);
|
|
814
781
|
return this;
|
|
815
782
|
}
|
|
816
783
|
setRoutes(...routes) {
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
this.routes.set(route.name.toLowerCase(), route.handler);
|
|
820
|
-
}
|
|
821
|
-
} else {
|
|
822
|
-
this.routes = /* @__PURE__ */ new Map();
|
|
823
|
-
}
|
|
784
|
+
this.routes.clear();
|
|
785
|
+
this.addRoutes(...routes);
|
|
824
786
|
return this;
|
|
825
787
|
}
|
|
826
788
|
addRoutes(...routes) {
|
|
789
|
+
if (!this.options.routes) this.options.routes = [];
|
|
827
790
|
for (const route of routes) {
|
|
828
|
-
|
|
791
|
+
const name = route.name.toLowerCase();
|
|
792
|
+
this.routes.set(name, route.handler);
|
|
793
|
+
const existingIndex = this.options.routes.findIndex((r) => r.name.toLowerCase() === name);
|
|
794
|
+
if (existingIndex > -1) this.options.routes[existingIndex] = route;
|
|
795
|
+
else this.options.routes.push(route);
|
|
829
796
|
}
|
|
830
797
|
return this;
|
|
831
798
|
}
|
|
832
799
|
setUnknownRouteHandler(handler) {
|
|
833
|
-
this.onUnknownRouteHandler = handler;
|
|
800
|
+
this.options.onUnknownRouteHandler = handler;
|
|
834
801
|
return this;
|
|
835
802
|
}
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
await this.
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
return result;
|
|
850
|
-
} else if (this.onUnknownRouteHandler) {
|
|
851
|
-
const result = await this.onUnknownRouteHandler?.(client, interaction);
|
|
852
|
-
await this.afterExecute?.(result, client, interaction);
|
|
853
|
-
return result;
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
return this._runFlyAndLand(client.config.slashCommands, client, interaction);
|
|
857
|
-
} catch (err) {
|
|
858
|
-
this.onError?.(err, client, interaction);
|
|
859
|
-
client.config.slashCommands.onError?.(err, client, interaction);
|
|
860
|
-
throw err;
|
|
861
|
-
} finally {
|
|
862
|
-
if (client.config.slashCommands.logExecution) {
|
|
863
|
-
client.logger.commandExecuted(this.builder.name, interaction.user.username, interaction.guild?.name);
|
|
864
|
-
}
|
|
865
|
-
}
|
|
803
|
+
setExecute(fn) {
|
|
804
|
+
const originalExecute = fn;
|
|
805
|
+
this.options.execute = async (client, interaction) => {
|
|
806
|
+
return await this.handleExecution(client, interaction, originalExecute);
|
|
807
|
+
};
|
|
808
|
+
return this;
|
|
809
|
+
}
|
|
810
|
+
toConfig() {
|
|
811
|
+
return {
|
|
812
|
+
...this.options,
|
|
813
|
+
builder: this.builder,
|
|
814
|
+
routes: Array.from(this.routes.entries()).map(([name, handler]) => ({ name, handler }))
|
|
815
|
+
};
|
|
866
816
|
}
|
|
867
817
|
};
|
|
868
818
|
|
|
@@ -877,12 +827,19 @@ var globalVimcordToolsConfig = {
|
|
|
877
827
|
embedColor: [],
|
|
878
828
|
embedColorDev: [],
|
|
879
829
|
timeouts: {
|
|
830
|
+
collectorTimeout: 6e4,
|
|
831
|
+
collectorIdle: 6e4,
|
|
880
832
|
pagination: 6e4,
|
|
881
833
|
prompt: 3e4,
|
|
882
834
|
modalSubmit: 6e4
|
|
883
835
|
},
|
|
836
|
+
collector: {
|
|
837
|
+
notAParticipantMessage: "You are not allowed to use this.",
|
|
838
|
+
userLockMessage: "Please wait until your current action is finished.",
|
|
839
|
+
notAParticipantWarningCooldown: 5e3
|
|
840
|
+
},
|
|
884
841
|
paginator: {
|
|
885
|
-
notAParticipantMessage: "You are not allowed to use this
|
|
842
|
+
notAParticipantMessage: "You are not allowed to use this.",
|
|
886
843
|
jumpableThreshold: 5,
|
|
887
844
|
longThreshold: 4,
|
|
888
845
|
buttons: {
|
|
@@ -895,7 +852,7 @@ var globalVimcordToolsConfig = {
|
|
|
895
852
|
},
|
|
896
853
|
prompt: {
|
|
897
854
|
defaultTitle: "Are you sure?",
|
|
898
|
-
defaultDescription: "Make sure you know what you're doing
|
|
855
|
+
defaultDescription: "Make sure you know what you're doing.",
|
|
899
856
|
confirmLabel: "Confirm",
|
|
900
857
|
rejectLabel: "Cancel"
|
|
901
858
|
}
|
|
@@ -985,7 +942,7 @@ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
|
985
942
|
LogLevel2[LogLevel2["ERROR"] = 4] = "ERROR";
|
|
986
943
|
return LogLevel2;
|
|
987
944
|
})(LogLevel || {});
|
|
988
|
-
var
|
|
945
|
+
var LOGGER_COLORS = {
|
|
989
946
|
primary: "#5865F2",
|
|
990
947
|
success: "#57F287",
|
|
991
948
|
warn: "#FEE75C",
|
|
@@ -1006,7 +963,7 @@ var Logger = class {
|
|
|
1006
963
|
this.minLevel = minLevel;
|
|
1007
964
|
this.showTimestamp = showTimestamp;
|
|
1008
965
|
this.colorScheme = {
|
|
1009
|
-
...
|
|
966
|
+
...LOGGER_COLORS,
|
|
1010
967
|
...options?.colors
|
|
1011
968
|
};
|
|
1012
969
|
}
|
|
@@ -1067,7 +1024,7 @@ var Logger = class {
|
|
|
1067
1024
|
}
|
|
1068
1025
|
setColors(colors) {
|
|
1069
1026
|
this.colorScheme = {
|
|
1070
|
-
...
|
|
1027
|
+
...LOGGER_COLORS,
|
|
1071
1028
|
...colors
|
|
1072
1029
|
};
|
|
1073
1030
|
return this;
|
|
@@ -1280,28 +1237,9 @@ function formatThousands(num, sep = ",") {
|
|
|
1280
1237
|
return `${num}`.replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, sep);
|
|
1281
1238
|
}
|
|
1282
1239
|
|
|
1283
|
-
// src/utils/random.ts
|
|
1284
|
-
function pickRandom(arr, options) {
|
|
1285
|
-
const _rnd = () => {
|
|
1286
|
-
return arr[Math.floor(Math.random() * arr.length)];
|
|
1287
|
-
};
|
|
1288
|
-
let att = 0;
|
|
1289
|
-
let candidate = _rnd();
|
|
1290
|
-
if (options?.notEqualTo !== void 0 && arr.length > 1) {
|
|
1291
|
-
while (candidate === options.notEqualTo) {
|
|
1292
|
-
if (att < (options?.maxRerollAttempts ?? 100)) {
|
|
1293
|
-
throw new Error(`pickRandom reached max reroll attempts (${options?.maxRerollAttempts ?? 100})`);
|
|
1294
|
-
}
|
|
1295
|
-
candidate = _rnd();
|
|
1296
|
-
att++;
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1299
|
-
return options?.clone ? structuredClone(candidate) : candidate;
|
|
1300
|
-
}
|
|
1301
|
-
|
|
1302
1240
|
// src/modules/status.manager.ts
|
|
1303
|
-
import cron from "node-cron";
|
|
1304
1241
|
import EventEmitter from "events";
|
|
1242
|
+
import { $ as $2 } from "qznt";
|
|
1305
1243
|
var VimcordStatusManager = class {
|
|
1306
1244
|
client;
|
|
1307
1245
|
logger;
|
|
@@ -1322,24 +1260,9 @@ var VimcordStatusManager = class {
|
|
|
1322
1260
|
this.logger.debug("Status cleared");
|
|
1323
1261
|
}
|
|
1324
1262
|
});
|
|
1325
|
-
this.emitter.on("rotation", () => {
|
|
1326
|
-
if (this.client.config.app.verbose) {
|
|
1327
|
-
this.logger.debug("Status rotated");
|
|
1328
|
-
}
|
|
1329
|
-
});
|
|
1330
|
-
this.emitter.on("rotationStarted", () => {
|
|
1331
|
-
if (this.client.config.app.verbose) {
|
|
1332
|
-
this.logger.debug("Status rotation resumed \u25B6\uFE0F");
|
|
1333
|
-
}
|
|
1334
|
-
});
|
|
1335
|
-
this.emitter.on("rotationPaused", () => {
|
|
1336
|
-
if (this.client.config.app.verbose) {
|
|
1337
|
-
this.logger.debug("Status rotation paused \u23F8\uFE0F");
|
|
1338
|
-
}
|
|
1339
|
-
});
|
|
1340
1263
|
}
|
|
1341
1264
|
clearData() {
|
|
1342
|
-
this.task?.
|
|
1265
|
+
this.task?.stop();
|
|
1343
1266
|
this.task = null;
|
|
1344
1267
|
this.lastActivity = null;
|
|
1345
1268
|
this.lastActivityIndex = 0;
|
|
@@ -1372,11 +1295,8 @@ var VimcordStatusManager = class {
|
|
|
1372
1295
|
}
|
|
1373
1296
|
async statusRotationTask(clientStatus) {
|
|
1374
1297
|
let activity;
|
|
1375
|
-
if (clientStatus.randomize) {
|
|
1376
|
-
activity =
|
|
1377
|
-
notEqualTo: this.lastActivity,
|
|
1378
|
-
clone: true
|
|
1379
|
-
});
|
|
1298
|
+
if (clientStatus.randomize && Array.isArray(clientStatus.activity)) {
|
|
1299
|
+
activity = $2.rnd.choice(clientStatus.activity, { not: this.lastActivity });
|
|
1380
1300
|
this.lastActivity = activity;
|
|
1381
1301
|
} else {
|
|
1382
1302
|
const activityIndex = (this.lastActivityIndex + 1) % clientStatus.activity.length;
|
|
@@ -1388,34 +1308,22 @@ var VimcordStatusManager = class {
|
|
|
1388
1308
|
}
|
|
1389
1309
|
async scheduleStatusRotation(clientStatus) {
|
|
1390
1310
|
if (!clientStatus.interval) throw new Error("Cannot create client activity interval without interval time");
|
|
1391
|
-
this.task?.
|
|
1311
|
+
this.task?.stop();
|
|
1392
1312
|
this.task = null;
|
|
1393
|
-
|
|
1394
|
-
this.task = cron.createTask(
|
|
1395
|
-
`*/${clientStatus.interval} * * * * *`,
|
|
1396
|
-
async () => await this.statusRotationTask(clientStatus),
|
|
1397
|
-
{ noOverlap: true }
|
|
1398
|
-
);
|
|
1313
|
+
this.task = new $2.Loop(() => this.statusRotationTask(clientStatus), $2.math.ms(clientStatus.interval), true);
|
|
1399
1314
|
this.start();
|
|
1400
|
-
this.emitter.emit("rotationStarted", this.task);
|
|
1401
1315
|
}
|
|
1402
1316
|
start() {
|
|
1403
1317
|
if (this.task) {
|
|
1404
1318
|
this.task.start();
|
|
1405
|
-
this.emitter.emit("
|
|
1406
|
-
if (this.client.config.app.verbose) {
|
|
1407
|
-
this.logger.debug("Status rotation started");
|
|
1408
|
-
}
|
|
1319
|
+
this.emitter.emit("started", this.task);
|
|
1409
1320
|
}
|
|
1410
1321
|
return this;
|
|
1411
1322
|
}
|
|
1412
1323
|
pause() {
|
|
1413
1324
|
if (this.task) {
|
|
1414
1325
|
this.task.stop();
|
|
1415
|
-
this.emitter.emit("
|
|
1416
|
-
if (this.client.config.app.verbose) {
|
|
1417
|
-
this.logger.debug("Status rotation paused");
|
|
1418
|
-
}
|
|
1326
|
+
this.emitter.emit("paused", this.task);
|
|
1419
1327
|
}
|
|
1420
1328
|
return this;
|
|
1421
1329
|
}
|
|
@@ -1429,21 +1337,16 @@ var VimcordStatusManager = class {
|
|
|
1429
1337
|
}
|
|
1430
1338
|
if (!clientStatus.interval) {
|
|
1431
1339
|
await this.setActivity(Array.isArray(clientStatus.activity) ? clientStatus.activity[0] : clientStatus.activity);
|
|
1432
|
-
|
|
1433
|
-
}
|
|
1434
|
-
if (clientStatus.interval) {
|
|
1340
|
+
} else {
|
|
1435
1341
|
await this.scheduleStatusRotation(clientStatus);
|
|
1436
1342
|
}
|
|
1437
1343
|
return this;
|
|
1438
1344
|
}
|
|
1439
1345
|
async destroy() {
|
|
1440
1346
|
if (this.task) {
|
|
1441
|
-
this.task.
|
|
1347
|
+
this.task.stop();
|
|
1442
1348
|
this.task = null;
|
|
1443
|
-
this.emitter.emit("
|
|
1444
|
-
if (this.client.config.app.verbose) {
|
|
1445
|
-
this.logger.debug("Status rotation destroyed");
|
|
1446
|
-
}
|
|
1349
|
+
this.emitter.emit("destroyed");
|
|
1447
1350
|
await this.clear();
|
|
1448
1351
|
}
|
|
1449
1352
|
return this;
|
|
@@ -1453,245 +1356,193 @@ var VimcordStatusManager = class {
|
|
|
1453
1356
|
this.clearData();
|
|
1454
1357
|
client.user.setActivity({ name: "" });
|
|
1455
1358
|
this.emitter.emit("cleared");
|
|
1456
|
-
if (this.client.config.app.verbose) {
|
|
1457
|
-
this.logger.debug("Status cleared");
|
|
1458
|
-
}
|
|
1459
1359
|
return this;
|
|
1460
1360
|
}
|
|
1461
1361
|
};
|
|
1462
1362
|
|
|
1463
1363
|
// src/modules/command.manager.ts
|
|
1464
1364
|
import { REST, Routes } from "discord.js";
|
|
1465
|
-
var
|
|
1466
|
-
|
|
1467
|
-
prefix;
|
|
1468
|
-
context;
|
|
1469
|
-
constructor(client) {
|
|
1470
|
-
this.slash = new VimcordSlashCommandManager(client);
|
|
1471
|
-
this.prefix = new VimcordPrefixCommandManager(client);
|
|
1472
|
-
this.context = new VimcordContextCommandManager(client);
|
|
1473
|
-
}
|
|
1474
|
-
};
|
|
1475
|
-
var VimcordSlashCommandManager = class {
|
|
1476
|
-
constructor(client) {
|
|
1365
|
+
var VimcordAppCommandManager = class {
|
|
1366
|
+
constructor(client, typeName) {
|
|
1477
1367
|
this.client = client;
|
|
1478
|
-
|
|
1368
|
+
this.typeName = typeName;
|
|
1369
|
+
this.client.whenReady().then((c) => this.rest = new REST().setToken(c.token));
|
|
1479
1370
|
}
|
|
1480
1371
|
commands = /* @__PURE__ */ new Map();
|
|
1481
1372
|
rest;
|
|
1482
1373
|
get(name) {
|
|
1483
1374
|
return this.commands.get(name);
|
|
1484
1375
|
}
|
|
1376
|
+
/**
|
|
1377
|
+
* Filters and returns commands based on deployment options
|
|
1378
|
+
*/
|
|
1485
1379
|
getAll(options) {
|
|
1486
1380
|
const matchedCommands = /* @__PURE__ */ new Map();
|
|
1381
|
+
const isDev = this.client.config.app.devMode;
|
|
1487
1382
|
for (const cmd of this.commands.values()) {
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
options.fuzzyNames?.some((fuzzyCommand) => cmd.builder.name.includes(fuzzyCommand))
|
|
1494
|
-
);
|
|
1495
|
-
if ((options.names || options.fuzzyNames) && !nameMatched) continue;
|
|
1496
|
-
const guildMatched = cmd.deployment?.guilds?.some((guildId) => options.guilds?.includes(guildId));
|
|
1497
|
-
if (options.guilds && !guildMatched) continue;
|
|
1498
|
-
matched = cmd;
|
|
1499
|
-
} else {
|
|
1500
|
-
matched = cmd;
|
|
1383
|
+
const config = cmd.toConfig();
|
|
1384
|
+
const name = cmd.builder.name;
|
|
1385
|
+
if (options?.names || options?.fuzzyNames) {
|
|
1386
|
+
const nameMatched = options.names?.includes(name) || options.fuzzyNames?.some((fuzzy) => name.includes(fuzzy));
|
|
1387
|
+
if (!nameMatched) continue;
|
|
1501
1388
|
}
|
|
1502
|
-
if (!matched) continue;
|
|
1503
1389
|
if (options?.ignoreDeploymentOptions) {
|
|
1504
|
-
|
|
1505
|
-
matchedCommands.set(matched.builder.name, matched);
|
|
1390
|
+
matchedCommands.set(name, cmd);
|
|
1506
1391
|
continue;
|
|
1507
1392
|
}
|
|
1508
|
-
const
|
|
1509
|
-
|
|
1510
|
-
);
|
|
1511
|
-
if (
|
|
1512
|
-
|
|
1513
|
-
}
|
|
1393
|
+
const deployment = config.deployment || {};
|
|
1394
|
+
const isProperEnv = !deployment.environments || deployment.environments.includes(isDev ? "development" : "production");
|
|
1395
|
+
if (!isProperEnv) continue;
|
|
1396
|
+
if (options?.globalOnly && deployment.global === false) continue;
|
|
1397
|
+
matchedCommands.set(name, cmd);
|
|
1514
1398
|
}
|
|
1515
1399
|
return matchedCommands;
|
|
1516
1400
|
}
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
this.
|
|
1401
|
+
async registerGlobal(options) {
|
|
1402
|
+
const client = await this.client.whenReady();
|
|
1403
|
+
const commands = Array.from(
|
|
1404
|
+
this.getAll({
|
|
1405
|
+
names: options?.commands,
|
|
1406
|
+
fuzzyNames: options?.fuzzyCommands,
|
|
1407
|
+
globalOnly: true
|
|
1408
|
+
}).values()
|
|
1409
|
+
).map((cmd) => cmd.builder.toJSON());
|
|
1410
|
+
if (!commands.length) {
|
|
1411
|
+
console.log(`[${this.typeName}] No commands to register`);
|
|
1412
|
+
return;
|
|
1521
1413
|
}
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
const isProperEnvironment = command.module.default.deployment?.environments?.includes(
|
|
1529
|
-
this.client.config.app.devMode ? "development" : "production"
|
|
1530
|
-
);
|
|
1531
|
-
if (isProperEnvironment ?? true) {
|
|
1532
|
-
this.commands.set(command.module.default.builder.name, command.module.default);
|
|
1533
|
-
importedCommands++;
|
|
1534
|
-
}
|
|
1414
|
+
console.log(`[${this.typeName}] Registering ${commands.length} commands globally...`);
|
|
1415
|
+
try {
|
|
1416
|
+
await this.rest.put(Routes.applicationCommands(client.user.id), { body: commands });
|
|
1417
|
+
console.log(`[${this.typeName}] \u2714 Registered app commands globally`);
|
|
1418
|
+
} catch (err) {
|
|
1419
|
+
console.log(`[${this.typeName}] \u2716 Failed to register app commands globally`, err);
|
|
1535
1420
|
}
|
|
1536
|
-
this.client.logger.moduleLoaded("Slash Commands", importedCommands);
|
|
1537
|
-
return this.commands;
|
|
1538
1421
|
}
|
|
1539
1422
|
async registerGuild(options) {
|
|
1540
1423
|
const client = await this.client.whenReady();
|
|
1541
|
-
const
|
|
1424
|
+
const commands = Array.from(
|
|
1542
1425
|
this.getAll({
|
|
1543
1426
|
names: options?.commands,
|
|
1544
1427
|
fuzzyNames: options?.fuzzyCommands
|
|
1545
1428
|
}).values()
|
|
1546
1429
|
).map((cmd) => cmd.builder.toJSON());
|
|
1547
|
-
if (!
|
|
1548
|
-
console.log(
|
|
1430
|
+
if (!commands.length) {
|
|
1431
|
+
console.log(`[${this.typeName}] No commands to register`);
|
|
1549
1432
|
return;
|
|
1550
1433
|
}
|
|
1551
|
-
const guildIds = options?.guilds || client.guilds.cache.map((
|
|
1552
|
-
console.log(
|
|
1553
|
-
`[SlashCommandManager] Registering ${commandsToRegister.length} app (/) ${commandsToRegister.length === 1 ? "command" : "commands"} for ${guildIds.length} ${guildIds.length === 1 ? "guild" : "guilds"}...`
|
|
1554
|
-
);
|
|
1434
|
+
const guildIds = options?.guilds || client.guilds.cache.map((g) => g.id);
|
|
1435
|
+
console.log(`[${this.typeName}] Registering ${commands.length} commands for ${guildIds.length} guilds...`);
|
|
1555
1436
|
await Promise.all(
|
|
1556
1437
|
guildIds.map(
|
|
1557
|
-
(guildId) => this.rest.put(Routes.applicationGuildCommands(client.user.id, guildId), {
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
)
|
|
1563
|
-
)
|
|
1564
|
-
(err) => console.log(
|
|
1565
|
-
`[SlashCommandManager] \u2716 Failed to set app (/) commands in guild: ${guildId} (${client.guilds.cache.find((g) => g.id === guildId)?.name || "n/a"})`,
|
|
1566
|
-
err
|
|
1567
|
-
)
|
|
1568
|
-
)
|
|
1438
|
+
(guildId) => this.rest.put(Routes.applicationGuildCommands(client.user.id, guildId), { body: commands }).then(() => {
|
|
1439
|
+
const gName = client.guilds.cache.get(guildId)?.name || "n/a";
|
|
1440
|
+
console.log(`[${this.typeName}] \u2714 Set app commands in guild: ${guildId} (${gName})`);
|
|
1441
|
+
}).catch((err) => {
|
|
1442
|
+
const gName = client.guilds.cache.get(guildId)?.name || "n/a";
|
|
1443
|
+
console.log(`[${this.typeName}] \u2716 Failed to set app commands in guild: ${guildId} (${gName})`, err);
|
|
1444
|
+
})
|
|
1569
1445
|
)
|
|
1570
1446
|
);
|
|
1571
|
-
console.log(
|
|
1572
|
-
`[SlashCommandManager] \u2714 Finished registering app (/) commands for ${guildIds.length} ${guildIds.length === 1 ? "guild" : "guilds"}`
|
|
1573
|
-
);
|
|
1574
1447
|
}
|
|
1575
1448
|
async unregisterGuild(options) {
|
|
1576
1449
|
const client = await this.client.whenReady();
|
|
1577
|
-
const guildIds = options?.guilds || client.guilds.cache.map((
|
|
1578
|
-
console.log(
|
|
1579
|
-
`[SlashCommandManager] Unregistering app (/) commands from ${guildIds.length} ${guildIds.length === 1 ? "guild" : "guilds"}...`
|
|
1580
|
-
);
|
|
1450
|
+
const guildIds = options?.guilds || client.guilds.cache.map((g) => g.id);
|
|
1451
|
+
console.log(`[${this.typeName}] Unregistering commands from ${guildIds.length} guilds...`);
|
|
1581
1452
|
await Promise.all(
|
|
1582
1453
|
guildIds.map(
|
|
1583
|
-
(guildId) => this.rest.put(Routes.applicationGuildCommands(client.user.id, guildId), {
|
|
1584
|
-
|
|
1585
|
-
}).then(
|
|
1586
|
-
() => console.log(
|
|
1587
|
-
`[SlashCommandManager] \u2714 Removed app (/) commands in guild: ${guildId} (${client.guilds.cache.find((g) => g.id === guildId)?.name || "n/a"})`
|
|
1588
|
-
)
|
|
1589
|
-
).catch(
|
|
1590
|
-
(err) => console.log(
|
|
1591
|
-
`[SlashCommandManager] \u2716 Failed to remove app (/) commands in guild: ${guildId} (${client.guilds.cache.find((g) => g.id === guildId)?.name || "n/a"})`,
|
|
1592
|
-
err
|
|
1593
|
-
)
|
|
1454
|
+
(guildId) => this.rest.put(Routes.applicationGuildCommands(client.user.id, guildId), { body: [] }).then(() => console.log(`[${this.typeName}] \u2714 Removed app commands in guild: ${guildId}`)).catch(
|
|
1455
|
+
(err) => console.log(`[${this.typeName}] \u2716 Failed to remove app commands in guild: ${guildId}`, err)
|
|
1594
1456
|
)
|
|
1595
1457
|
)
|
|
1596
1458
|
);
|
|
1597
|
-
console.log(
|
|
1598
|
-
`[SlashCommandManager] \u2714 Finished unregistering app (/) commands for ${guildIds.length} ${guildIds.length === 1 ? "guild" : "guilds"}`
|
|
1599
|
-
);
|
|
1600
|
-
}
|
|
1601
|
-
async registerGlobal(options) {
|
|
1602
|
-
const client = await this.client.whenReady();
|
|
1603
|
-
const commandsToRegister = Array.from(
|
|
1604
|
-
this.getAll({
|
|
1605
|
-
names: options?.commands,
|
|
1606
|
-
fuzzyNames: options?.fuzzyCommands,
|
|
1607
|
-
globalOnly: true
|
|
1608
|
-
}).values()
|
|
1609
|
-
).map((cmd) => cmd.builder.toJSON());
|
|
1610
|
-
if (!commandsToRegister.length) {
|
|
1611
|
-
console.log("[SlashCommandManager] No commands to register");
|
|
1612
|
-
return;
|
|
1613
|
-
}
|
|
1614
|
-
console.log(
|
|
1615
|
-
`[SlashCommandManager] Registering ${commandsToRegister.length} app (/) ${commandsToRegister.length === 1 ? "command" : "commands"} globally...`
|
|
1616
|
-
);
|
|
1617
|
-
try {
|
|
1618
|
-
await this.rest.put(Routes.applicationCommands(client.user.id), { body: commandsToRegister });
|
|
1619
|
-
console.log("[SlashCommandManager] \u2714 Registered app (/) commands globally");
|
|
1620
|
-
} catch (err) {
|
|
1621
|
-
console.log("[SlashCommandManager] \u2716 Failed to register app (/) commands globally", err);
|
|
1622
|
-
}
|
|
1623
1459
|
}
|
|
1624
1460
|
async unregisterGlobal() {
|
|
1625
1461
|
const client = await this.client.whenReady();
|
|
1626
|
-
console.log("[SlashCommandManager] Unregistering app (/) commands globally...");
|
|
1627
1462
|
try {
|
|
1628
1463
|
await this.rest.put(Routes.applicationCommands(client.user.id), { body: [] });
|
|
1629
|
-
console.log(
|
|
1464
|
+
console.log(`[${this.typeName}] \u2714 Removed app commands globally`);
|
|
1630
1465
|
} catch (err) {
|
|
1631
|
-
console.log(
|
|
1466
|
+
console.log(`[${this.typeName}] \u2716 Failed to remove app commands globally`, err);
|
|
1632
1467
|
}
|
|
1633
1468
|
}
|
|
1634
1469
|
};
|
|
1635
|
-
var
|
|
1470
|
+
var VimcordSlashCommandManager = class extends VimcordAppCommandManager {
|
|
1636
1471
|
constructor(client) {
|
|
1637
|
-
|
|
1638
|
-
}
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
return Array.from(this.commands.values()).find((cmd) => cmd.aliases?.includes(alias));
|
|
1651
|
-
}
|
|
1652
|
-
return Array.from(this.commands.values()).find((cmd) => cmd.aliases?.includes(alias));
|
|
1472
|
+
super(client, "SlashCommandManager");
|
|
1473
|
+
}
|
|
1474
|
+
async importFrom(dir, replaceAll = false) {
|
|
1475
|
+
if (replaceAll) this.commands.clear();
|
|
1476
|
+
const dirs = Array.isArray(dir) ? dir : [dir];
|
|
1477
|
+
const modules = (await Promise.all(
|
|
1478
|
+
dirs.map((d) => importModulesFromDir(d, "slash"))
|
|
1479
|
+
)).flat();
|
|
1480
|
+
for (const { module } of modules) {
|
|
1481
|
+
this.commands.set(module.default.builder.name, module.default);
|
|
1482
|
+
}
|
|
1483
|
+
this.client.logger.moduleLoaded("Slash Commands", modules.length);
|
|
1484
|
+
return this.commands;
|
|
1653
1485
|
}
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
}
|
|
1668
|
-
this.client.logger.moduleLoaded("
|
|
1486
|
+
};
|
|
1487
|
+
var VimcordContextCommandManager = class extends VimcordAppCommandManager {
|
|
1488
|
+
constructor(client) {
|
|
1489
|
+
super(client, "ContextCommandManager");
|
|
1490
|
+
}
|
|
1491
|
+
async importFrom(dir, replaceAll = false) {
|
|
1492
|
+
if (replaceAll) this.commands.clear();
|
|
1493
|
+
const dirs = Array.isArray(dir) ? dir : [dir];
|
|
1494
|
+
const modules = (await Promise.all(
|
|
1495
|
+
dirs.map((d) => importModulesFromDir(d, "ctx"))
|
|
1496
|
+
)).flat();
|
|
1497
|
+
for (const { module } of modules) {
|
|
1498
|
+
this.commands.set(module.default.builder.name, module.default);
|
|
1499
|
+
}
|
|
1500
|
+
this.client.logger.moduleLoaded("Context Commands", modules.length);
|
|
1669
1501
|
return this.commands;
|
|
1670
1502
|
}
|
|
1671
1503
|
};
|
|
1672
|
-
var
|
|
1504
|
+
var VimcordPrefixCommandManager = class {
|
|
1673
1505
|
constructor(client) {
|
|
1674
1506
|
this.client = client;
|
|
1675
1507
|
}
|
|
1676
1508
|
commands = /* @__PURE__ */ new Map();
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1509
|
+
resolve(trigger) {
|
|
1510
|
+
const config = this.client.config.prefixCommands;
|
|
1511
|
+
const search = config.allowCaseInsensitiveCommandNames ? trigger.toLowerCase() : trigger;
|
|
1512
|
+
return Array.from(this.commands.values()).find((cmd) => {
|
|
1513
|
+
const opts = cmd.toConfig();
|
|
1514
|
+
const name = config.allowCaseInsensitiveCommandNames ? opts.name.toLowerCase() : opts.name;
|
|
1515
|
+
if (name === search) return true;
|
|
1516
|
+
return opts.aliases?.some(
|
|
1517
|
+
(a) => config.allowCaseInsensitiveCommandNames ? a.toLowerCase() === search : a === search
|
|
1518
|
+
);
|
|
1519
|
+
});
|
|
1520
|
+
}
|
|
1521
|
+
async importFrom(dir, replaceAll = false) {
|
|
1522
|
+
if (replaceAll) this.commands.clear();
|
|
1523
|
+
const dirs = Array.isArray(dir) ? dir : [dir];
|
|
1524
|
+
const modules = (await Promise.all(
|
|
1525
|
+
dirs.map(
|
|
1526
|
+
(d) => importModulesFromDir(d, "prefix")
|
|
1527
|
+
)
|
|
1528
|
+
)).flat();
|
|
1529
|
+
for (const { module } of modules) {
|
|
1530
|
+
this.commands.set(module.default.toConfig().name, module.default);
|
|
1690
1531
|
}
|
|
1691
|
-
this.client.logger.moduleLoaded("
|
|
1532
|
+
this.client.logger.moduleLoaded("Prefix Commands", modules.length);
|
|
1692
1533
|
return this.commands;
|
|
1693
1534
|
}
|
|
1694
1535
|
};
|
|
1536
|
+
var VimcordCommandManager = class {
|
|
1537
|
+
slash;
|
|
1538
|
+
prefix;
|
|
1539
|
+
context;
|
|
1540
|
+
constructor(client) {
|
|
1541
|
+
this.slash = new VimcordSlashCommandManager(client);
|
|
1542
|
+
this.prefix = new VimcordPrefixCommandManager(client);
|
|
1543
|
+
this.context = new VimcordContextCommandManager(client);
|
|
1544
|
+
}
|
|
1545
|
+
};
|
|
1695
1546
|
|
|
1696
1547
|
// src/modules/event.manager.ts
|
|
1697
1548
|
import { Events } from "discord.js";
|
|
@@ -2087,7 +1938,7 @@ var BetterEmbed = class _BetterEmbed {
|
|
|
2087
1938
|
}
|
|
2088
1939
|
if (this.data.description) {
|
|
2089
1940
|
this.data.description = formatString(
|
|
2090
|
-
Array.isArray(this.data.description) ? this.data.description.join("\n") : this.data.description
|
|
1941
|
+
Array.isArray(this.data.description) ? this.data.description.filter((s) => s !== null && s !== void 0).join("\n") : this.data.description
|
|
2091
1942
|
);
|
|
2092
1943
|
}
|
|
2093
1944
|
if (this.data.footer && typeof this.data.footer === "object") {
|
|
@@ -2099,7 +1950,7 @@ var BetterEmbed = class _BetterEmbed {
|
|
|
2099
1950
|
if (this.data.imageUrl) {
|
|
2100
1951
|
this.data.imageUrl = formatString(this.data.imageUrl);
|
|
2101
1952
|
}
|
|
2102
|
-
this.data.fields = this.data.fields.map((field) => ({
|
|
1953
|
+
this.data.fields = this.data.fields.filter(Boolean).map((field) => ({
|
|
2103
1954
|
...field,
|
|
2104
1955
|
name: formatString(field.name),
|
|
2105
1956
|
value: formatString(field.value)
|
|
@@ -2324,7 +2175,7 @@ async function retryExponentialBackoff(fn, maxRetries = 3, retryDelay = 1e3) {
|
|
|
2324
2175
|
}
|
|
2325
2176
|
|
|
2326
2177
|
// package.json
|
|
2327
|
-
var version = "1.0.
|
|
2178
|
+
var version = "1.0.1";
|
|
2328
2179
|
|
|
2329
2180
|
// src/client.ts
|
|
2330
2181
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
@@ -2590,62 +2441,63 @@ var Vimcord = class _Vimcord extends Client2 {
|
|
|
2590
2441
|
return fetchGuild(client, id);
|
|
2591
2442
|
}
|
|
2592
2443
|
};
|
|
2593
|
-
var defaultSlashCommandHandler = new EventBuilder({
|
|
2594
|
-
event: "interactionCreate",
|
|
2595
|
-
name: "SlashCommandHandler",
|
|
2596
|
-
async execute(client, interaction) {
|
|
2597
|
-
if (!interaction.isChatInputCommand()) return;
|
|
2598
|
-
const command = client.commands.slash.get(interaction.commandName);
|
|
2599
|
-
if (!command) {
|
|
2600
|
-
return interaction.reply({
|
|
2601
|
-
content: `**/\`${interaction.commandName}\`** is not a command`,
|
|
2602
|
-
flags: "Ephemeral"
|
|
2603
|
-
});
|
|
2604
|
-
}
|
|
2605
|
-
if (command.deferReply && !interaction.replied && !interaction.deferred) {
|
|
2606
|
-
await interaction.deferReply(typeof command.deferReply === "object" ? command.deferReply : void 0);
|
|
2607
|
-
}
|
|
2608
|
-
try {
|
|
2609
|
-
return command.executeCommand(client, interaction);
|
|
2610
|
-
} catch (err) {
|
|
2611
|
-
sendCommandErrorEmbed(client, err, interaction.guild, interaction);
|
|
2612
|
-
throw err;
|
|
2613
|
-
}
|
|
2614
|
-
}
|
|
2615
|
-
});
|
|
2616
2444
|
var defaultPrefixCommandHandler = new EventBuilder({
|
|
2617
2445
|
event: "messageCreate",
|
|
2618
2446
|
name: "PrefixCommandHandler",
|
|
2619
2447
|
async execute(client, message) {
|
|
2620
|
-
if (message.author.bot) return;
|
|
2448
|
+
if (message.author.bot || !message.guild) return;
|
|
2449
|
+
const config = client.config.prefixCommands;
|
|
2450
|
+
let activePrefix = config.defaultPrefix;
|
|
2451
|
+
if (config.guildPrefixResolver) {
|
|
2452
|
+
try {
|
|
2453
|
+
const customPrefix = await config.guildPrefixResolver(client, message.guild.id);
|
|
2454
|
+
if (customPrefix) activePrefix = customPrefix;
|
|
2455
|
+
} catch (err) {
|
|
2456
|
+
client.logger.error(`Error in guildPrefixResolver for guild ${message.guild.id}:`, err);
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2621
2459
|
let prefixUsed;
|
|
2622
|
-
if (
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
}
|
|
2629
|
-
} else {
|
|
2630
|
-
return;
|
|
2460
|
+
if (message.content.startsWith(activePrefix)) {
|
|
2461
|
+
prefixUsed = activePrefix;
|
|
2462
|
+
} else if (config.allowMentionAsPrefix) {
|
|
2463
|
+
const mention = userMention(client.user.id);
|
|
2464
|
+
if (message.content.startsWith(mention)) {
|
|
2465
|
+
prefixUsed = message.content.startsWith(`${mention} `) ? `${mention} ` : mention;
|
|
2631
2466
|
}
|
|
2632
|
-
} else {
|
|
2633
|
-
prefixUsed = client.config.prefixCommands.defaultPrefix;
|
|
2634
2467
|
}
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2468
|
+
if (!prefixUsed) return;
|
|
2469
|
+
const contentWithoutPrefix = message.content.slice(prefixUsed.length).trim();
|
|
2470
|
+
const args = contentWithoutPrefix.split(/\s+/);
|
|
2471
|
+
const trigger = args.shift();
|
|
2472
|
+
if (!trigger) return;
|
|
2473
|
+
const command = client.commands.prefix.resolve(trigger);
|
|
2474
|
+
if (!command) return;
|
|
2475
|
+
message.content = args.join(" ");
|
|
2476
|
+
try {
|
|
2477
|
+
return await command.run(client, client, message);
|
|
2478
|
+
} catch (err) {
|
|
2479
|
+
await sendCommandErrorEmbed(client, err, message.guild, message);
|
|
2480
|
+
throw err;
|
|
2639
2481
|
}
|
|
2640
|
-
|
|
2482
|
+
}
|
|
2483
|
+
});
|
|
2484
|
+
var defaultSlashCommandHandler = new EventBuilder({
|
|
2485
|
+
event: "interactionCreate",
|
|
2486
|
+
name: "SlashCommandHandler",
|
|
2487
|
+
async execute(client, interaction) {
|
|
2488
|
+
if (!interaction.isChatInputCommand()) return;
|
|
2489
|
+
const command = client.commands.slash.get(interaction.commandName);
|
|
2641
2490
|
if (!command) {
|
|
2642
|
-
|
|
2491
|
+
const content = `**/\`${interaction.commandName}\`** is not a registered command.`;
|
|
2492
|
+
if (interaction.replied || interaction.deferred) {
|
|
2493
|
+
return interaction.followUp({ content, flags: "Ephemeral" });
|
|
2494
|
+
}
|
|
2495
|
+
return interaction.reply({ content, flags: "Ephemeral" });
|
|
2643
2496
|
}
|
|
2644
|
-
message.content = message.content.slice(commandName.length + 1);
|
|
2645
2497
|
try {
|
|
2646
|
-
return command.
|
|
2498
|
+
return await command.run(client, client, interaction);
|
|
2647
2499
|
} catch (err) {
|
|
2648
|
-
sendCommandErrorEmbed(client, err,
|
|
2500
|
+
await sendCommandErrorEmbed(client, err, interaction.guild, interaction);
|
|
2649
2501
|
throw err;
|
|
2650
2502
|
}
|
|
2651
2503
|
}
|
|
@@ -2653,9 +2505,22 @@ var defaultPrefixCommandHandler = new EventBuilder({
|
|
|
2653
2505
|
var defaultContextCommandHandler = new EventBuilder({
|
|
2654
2506
|
event: "interactionCreate",
|
|
2655
2507
|
name: "ContextCommandHandler",
|
|
2656
|
-
execute(client, interaction) {
|
|
2508
|
+
async execute(client, interaction) {
|
|
2657
2509
|
if (!interaction.isContextMenuCommand()) return;
|
|
2658
|
-
|
|
2510
|
+
const command = client.commands.context.get(interaction.commandName);
|
|
2511
|
+
if (!command) {
|
|
2512
|
+
const content = `**${interaction.commandName}** is not a registered context command.`;
|
|
2513
|
+
if (interaction.replied || interaction.deferred) {
|
|
2514
|
+
return interaction.followUp({ content, flags: "Ephemeral" });
|
|
2515
|
+
}
|
|
2516
|
+
return interaction.reply({ content, flags: "Ephemeral" });
|
|
2517
|
+
}
|
|
2518
|
+
try {
|
|
2519
|
+
return await command.run(client, client, interaction);
|
|
2520
|
+
} catch (err) {
|
|
2521
|
+
await sendCommandErrorEmbed(client, err, interaction.guild, interaction);
|
|
2522
|
+
throw err;
|
|
2523
|
+
}
|
|
2659
2524
|
}
|
|
2660
2525
|
});
|
|
2661
2526
|
|
|
@@ -2670,8 +2535,8 @@ try {
|
|
|
2670
2535
|
}
|
|
2671
2536
|
var globalInstanceEmitter = new EventEmitter2();
|
|
2672
2537
|
var instances = [];
|
|
2673
|
-
async function useMongoDatabase(
|
|
2674
|
-
const instance = instances.at(
|
|
2538
|
+
async function useMongoDatabase(instanceIndex) {
|
|
2539
|
+
const instance = instances.at(instanceIndex ?? 0);
|
|
2675
2540
|
if (!instance) {
|
|
2676
2541
|
return new Promise((resolve, reject) => {
|
|
2677
2542
|
const timeout = setTimeout(() => reject("useMongoDatabase timed out"), 45e3);
|
|
@@ -2683,6 +2548,15 @@ async function useMongoDatabase(index) {
|
|
|
2683
2548
|
}
|
|
2684
2549
|
return instance;
|
|
2685
2550
|
}
|
|
2551
|
+
async function useReadyMongoDatabase(instanceIndex) {
|
|
2552
|
+
const instance = await useMongoDatabase(instanceIndex);
|
|
2553
|
+
await instance.waitForReady();
|
|
2554
|
+
return instance;
|
|
2555
|
+
}
|
|
2556
|
+
async function createMongoSession(instanceIndex, options) {
|
|
2557
|
+
const instance = await useReadyMongoDatabase(instanceIndex);
|
|
2558
|
+
return instance.mongoose.startSession(options);
|
|
2559
|
+
}
|
|
2686
2560
|
var MongoDatabase = class {
|
|
2687
2561
|
constructor(client, options) {
|
|
2688
2562
|
this.client = client;
|
|
@@ -2839,6 +2713,7 @@ var MongoSchemaBuilder = class {
|
|
|
2839
2713
|
this.eventEmitter.off(event, listener);
|
|
2840
2714
|
return this;
|
|
2841
2715
|
}
|
|
2716
|
+
/** Execute a function while ensuring the connection is ready. On error it will retry using an exponential backoff. */
|
|
2842
2717
|
async execute(fn) {
|
|
2843
2718
|
try {
|
|
2844
2719
|
if (!this.isReady) {
|
|
@@ -2875,9 +2750,9 @@ var MongoSchemaBuilder = class {
|
|
|
2875
2750
|
return id;
|
|
2876
2751
|
});
|
|
2877
2752
|
}
|
|
2878
|
-
async count(filter) {
|
|
2753
|
+
async count(filter, options) {
|
|
2879
2754
|
return await this.execute(async () => {
|
|
2880
|
-
return this.model.countDocuments(filter);
|
|
2755
|
+
return this.model.countDocuments(filter, options);
|
|
2881
2756
|
});
|
|
2882
2757
|
}
|
|
2883
2758
|
async exists(filter) {
|
|
@@ -2885,29 +2760,29 @@ var MongoSchemaBuilder = class {
|
|
|
2885
2760
|
return await this.model.exists(filter) ? true : false;
|
|
2886
2761
|
});
|
|
2887
2762
|
}
|
|
2888
|
-
async create(query) {
|
|
2763
|
+
async create(query, options) {
|
|
2889
2764
|
return await this.execute(async () => {
|
|
2890
|
-
return this.model.create(query);
|
|
2891
|
-
});
|
|
2765
|
+
return this.model.create(query, options);
|
|
2766
|
+
}) ?? [];
|
|
2892
2767
|
}
|
|
2893
2768
|
async upsert(filter, query, options) {
|
|
2894
2769
|
return await this.execute(async () => {
|
|
2895
2770
|
return this.model.findOneAndUpdate(filter, query, { ...options, upsert: true, new: true });
|
|
2896
2771
|
});
|
|
2897
2772
|
}
|
|
2898
|
-
async delete(filter) {
|
|
2773
|
+
async delete(filter, options) {
|
|
2899
2774
|
return await this.execute(async () => {
|
|
2900
|
-
return this.model.deleteOne(filter);
|
|
2775
|
+
return this.model.deleteOne(filter, options);
|
|
2901
2776
|
});
|
|
2902
2777
|
}
|
|
2903
|
-
async deleteAll(filter) {
|
|
2778
|
+
async deleteAll(filter, options) {
|
|
2904
2779
|
return await this.execute(async () => {
|
|
2905
|
-
return this.model.deleteMany(filter);
|
|
2780
|
+
return this.model.deleteMany(filter, options);
|
|
2906
2781
|
});
|
|
2907
2782
|
}
|
|
2908
|
-
async distinct(key, filter) {
|
|
2783
|
+
async distinct(key, filter, options) {
|
|
2909
2784
|
return await this.execute(async () => {
|
|
2910
|
-
return this.model.distinct(key, filter);
|
|
2785
|
+
return this.model.distinct(key, filter, options);
|
|
2911
2786
|
});
|
|
2912
2787
|
}
|
|
2913
2788
|
async fetch(filter, projection, options) {
|
|
@@ -2938,6 +2813,215 @@ var MongoSchemaBuilder = class {
|
|
|
2938
2813
|
}
|
|
2939
2814
|
};
|
|
2940
2815
|
|
|
2816
|
+
// src/tools/BetterCollector.ts
|
|
2817
|
+
var CollectorTimeoutType = /* @__PURE__ */ ((CollectorTimeoutType2) => {
|
|
2818
|
+
CollectorTimeoutType2[CollectorTimeoutType2["DisableComponents"] = 0] = "DisableComponents";
|
|
2819
|
+
CollectorTimeoutType2[CollectorTimeoutType2["DeleteMessage"] = 1] = "DeleteMessage";
|
|
2820
|
+
CollectorTimeoutType2[CollectorTimeoutType2["DoNothing"] = 2] = "DoNothing";
|
|
2821
|
+
return CollectorTimeoutType2;
|
|
2822
|
+
})(CollectorTimeoutType || {});
|
|
2823
|
+
var BetterCollector = class _BetterCollector {
|
|
2824
|
+
message;
|
|
2825
|
+
collector;
|
|
2826
|
+
options;
|
|
2827
|
+
activeUsers = /* @__PURE__ */ new Set();
|
|
2828
|
+
participantWarningCooldowns = /* @__PURE__ */ new Map();
|
|
2829
|
+
config;
|
|
2830
|
+
events = {
|
|
2831
|
+
collectId: /* @__PURE__ */ new Map(),
|
|
2832
|
+
collect: [],
|
|
2833
|
+
end: [],
|
|
2834
|
+
timeout: []
|
|
2835
|
+
};
|
|
2836
|
+
static create(message, options) {
|
|
2837
|
+
return new _BetterCollector(message, options);
|
|
2838
|
+
}
|
|
2839
|
+
async validateParticipant(interaction, participants) {
|
|
2840
|
+
const allowedParticipants = participants || this.options?.participants || [];
|
|
2841
|
+
if (!allowedParticipants.length) return true;
|
|
2842
|
+
const isAllowed = allowedParticipants.some((user) => {
|
|
2843
|
+
if (typeof user === "string") return user === interaction.user.id;
|
|
2844
|
+
if (typeof user === "object" && "id" in user) return user.id === interaction.user.id;
|
|
2845
|
+
return false;
|
|
2846
|
+
});
|
|
2847
|
+
if (!isAllowed) {
|
|
2848
|
+
const now = Date.now();
|
|
2849
|
+
const lastWarned = this.participantWarningCooldowns.get(interaction.user.id) || 0;
|
|
2850
|
+
if (now - lastWarned > this.config.collector.notAParticipantWarningCooldown) {
|
|
2851
|
+
this.participantWarningCooldowns.set(interaction.user.id, now);
|
|
2852
|
+
if (this.config.collector.notAParticipantMessage) {
|
|
2853
|
+
await interaction.reply({
|
|
2854
|
+
content: this.config.collector.notAParticipantMessage,
|
|
2855
|
+
flags: "Ephemeral"
|
|
2856
|
+
}).catch(() => {
|
|
2857
|
+
});
|
|
2858
|
+
} else {
|
|
2859
|
+
await interaction.deferUpdate().catch(() => {
|
|
2860
|
+
});
|
|
2861
|
+
}
|
|
2862
|
+
} else {
|
|
2863
|
+
await interaction.deferUpdate().catch(() => {
|
|
2864
|
+
});
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2867
|
+
return isAllowed;
|
|
2868
|
+
}
|
|
2869
|
+
build() {
|
|
2870
|
+
if (!this.message) return;
|
|
2871
|
+
if (this.collector) return;
|
|
2872
|
+
this.collector = this.message.createMessageComponentCollector({
|
|
2873
|
+
idle: this.options?.idle ?? this.config.timeouts.collectorIdle,
|
|
2874
|
+
time: this.options?.timeout ?? this.config.timeouts.collectorTimeout,
|
|
2875
|
+
componentType: this.options?.type,
|
|
2876
|
+
max: this.options?.max,
|
|
2877
|
+
maxComponents: this.options?.maxComponents,
|
|
2878
|
+
maxUsers: this.options?.maxUsers
|
|
2879
|
+
});
|
|
2880
|
+
this.setupListeners();
|
|
2881
|
+
}
|
|
2882
|
+
setupListeners() {
|
|
2883
|
+
if (!this.collector) return;
|
|
2884
|
+
this.collector.on("collect", async (interaction) => {
|
|
2885
|
+
if (this.options?.userLock && this.activeUsers.has(interaction.user.id)) {
|
|
2886
|
+
return interaction.reply({ content: this.config.collector.userLockMessage, flags: "Ephemeral" }).catch(() => {
|
|
2887
|
+
});
|
|
2888
|
+
}
|
|
2889
|
+
if (this.options?.userLock) {
|
|
2890
|
+
this.activeUsers.add(interaction.user.id);
|
|
2891
|
+
}
|
|
2892
|
+
const globalListeners = this.events.collect;
|
|
2893
|
+
const idListeners = this.events.collectId.get(interaction.customId) || [];
|
|
2894
|
+
const allListeners = [...globalListeners, ...idListeners];
|
|
2895
|
+
const shouldBeDeferred = allListeners.find((l) => l.options?.defer)?.options?.defer;
|
|
2896
|
+
const validListeners = [];
|
|
2897
|
+
for (const listener of allListeners) {
|
|
2898
|
+
const isAllowed = await this.validateParticipant(interaction, listener.options?.participants);
|
|
2899
|
+
if (isAllowed) validListeners.push(listener);
|
|
2900
|
+
}
|
|
2901
|
+
if (validListeners.length === 0) return;
|
|
2902
|
+
try {
|
|
2903
|
+
if (shouldBeDeferred) {
|
|
2904
|
+
if (typeof shouldBeDeferred === "object") {
|
|
2905
|
+
if (shouldBeDeferred.update) {
|
|
2906
|
+
await interaction.deferUpdate().catch(Boolean);
|
|
2907
|
+
} else {
|
|
2908
|
+
await interaction.deferReply({ flags: shouldBeDeferred.ephemeral ? "Ephemeral" : void 0 }).catch(Boolean);
|
|
2909
|
+
}
|
|
2910
|
+
} else {
|
|
2911
|
+
await interaction.deferReply().catch(Boolean);
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
if (this.options?.sequential) {
|
|
2915
|
+
for (const listener of allListeners) {
|
|
2916
|
+
try {
|
|
2917
|
+
const isAllowed = await this.validateParticipant(interaction, listener.options?.participants);
|
|
2918
|
+
if (!isAllowed) return;
|
|
2919
|
+
await listener.fn(interaction).finally(() => listener.options?.finally?.(interaction));
|
|
2920
|
+
} catch (err) {
|
|
2921
|
+
this.handleListenerError(err);
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
} else {
|
|
2925
|
+
Promise.all(
|
|
2926
|
+
allListeners.map((l) => {
|
|
2927
|
+
const isAllowed = this.validateParticipant(interaction, l.options?.participants);
|
|
2928
|
+
if (!isAllowed) return;
|
|
2929
|
+
return l.fn(interaction).catch(this.handleListenerError).finally(() => l.options?.finally?.(interaction));
|
|
2930
|
+
})
|
|
2931
|
+
);
|
|
2932
|
+
}
|
|
2933
|
+
} finally {
|
|
2934
|
+
if (this.options?.userLock) {
|
|
2935
|
+
this.activeUsers.delete(interaction.user.id);
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
});
|
|
2939
|
+
this.collector.on("end", async (collected, reason) => {
|
|
2940
|
+
if (this.options?.sequential) {
|
|
2941
|
+
for (const listener of this.events.end) {
|
|
2942
|
+
try {
|
|
2943
|
+
await listener.fn(collected, reason);
|
|
2944
|
+
} catch (err) {
|
|
2945
|
+
this.handleListenerError(err);
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
} else {
|
|
2949
|
+
Promise.all(this.events.end.map((l) => l.fn(collected, reason).catch(this.handleListenerError)));
|
|
2950
|
+
}
|
|
2951
|
+
switch (this.options?.onTimeout) {
|
|
2952
|
+
case 0 /* DisableComponents */:
|
|
2953
|
+
if (!this.message?.editable) break;
|
|
2954
|
+
try {
|
|
2955
|
+
const disabledRows = this.message.components.map((row) => {
|
|
2956
|
+
const updatedRow = row.toJSON();
|
|
2957
|
+
if ("components" in updatedRow) {
|
|
2958
|
+
updatedRow.components = updatedRow.components.map((component) => ({
|
|
2959
|
+
...component,
|
|
2960
|
+
disabled: true
|
|
2961
|
+
}));
|
|
2962
|
+
}
|
|
2963
|
+
return updatedRow;
|
|
2964
|
+
});
|
|
2965
|
+
await this.message.edit({ components: disabledRows });
|
|
2966
|
+
} catch (err) {
|
|
2967
|
+
if (!(err instanceof Error && err.message.includes("Unknown Message"))) {
|
|
2968
|
+
this.handleListenerError(err);
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
break;
|
|
2972
|
+
case 1 /* DeleteMessage */:
|
|
2973
|
+
if (!this.message?.deletable) break;
|
|
2974
|
+
await this.message.delete().catch(Boolean);
|
|
2975
|
+
break;
|
|
2976
|
+
case 2 /* DoNothing */:
|
|
2977
|
+
default:
|
|
2978
|
+
break;
|
|
2979
|
+
}
|
|
2980
|
+
});
|
|
2981
|
+
}
|
|
2982
|
+
handleListenerError(err) {
|
|
2983
|
+
console.error("[BetterCollector] Listener Error:", err);
|
|
2984
|
+
}
|
|
2985
|
+
constructor(message, options) {
|
|
2986
|
+
this.config = options?.config || globalVimcordToolsConfig;
|
|
2987
|
+
this.message = message || void 0;
|
|
2988
|
+
this.options = options;
|
|
2989
|
+
this.build();
|
|
2990
|
+
}
|
|
2991
|
+
on(idOrFunc, fnOrOptions, options) {
|
|
2992
|
+
let finalFn;
|
|
2993
|
+
let finalOptions;
|
|
2994
|
+
let customId;
|
|
2995
|
+
if (typeof idOrFunc === "function") {
|
|
2996
|
+
finalFn = idOrFunc;
|
|
2997
|
+
finalOptions = fnOrOptions;
|
|
2998
|
+
} else {
|
|
2999
|
+
if (typeof fnOrOptions !== "function") {
|
|
3000
|
+
throw new Error("[BetterCollector] Second argument must be a function when a customId is provided.");
|
|
3001
|
+
}
|
|
3002
|
+
customId = idOrFunc;
|
|
3003
|
+
finalFn = fnOrOptions;
|
|
3004
|
+
finalOptions = options;
|
|
3005
|
+
}
|
|
3006
|
+
if (customId) {
|
|
3007
|
+
const listeners = this.events.collectId.get(customId) || [];
|
|
3008
|
+
listeners.push({ fn: finalFn, options: finalOptions });
|
|
3009
|
+
this.events.collectId.set(customId, listeners);
|
|
3010
|
+
} else {
|
|
3011
|
+
this.events.collect.push({ fn: finalFn, options: finalOptions });
|
|
3012
|
+
}
|
|
3013
|
+
return this;
|
|
3014
|
+
}
|
|
3015
|
+
onEnd(fn, options) {
|
|
3016
|
+
this.events.end.push({ fn, options });
|
|
3017
|
+
return this;
|
|
3018
|
+
}
|
|
3019
|
+
/** Manually stop the collector and trigger cleanup */
|
|
3020
|
+
stop(reason = "manual") {
|
|
3021
|
+
this.collector?.stop(reason);
|
|
3022
|
+
}
|
|
3023
|
+
};
|
|
3024
|
+
|
|
2941
3025
|
// src/tools/BetterContainer.ts
|
|
2942
3026
|
import {
|
|
2943
3027
|
ButtonBuilder as ButtonBuilder2,
|
|
@@ -2982,7 +3066,9 @@ var BetterContainer = class {
|
|
|
2982
3066
|
return this;
|
|
2983
3067
|
}
|
|
2984
3068
|
addText(text) {
|
|
2985
|
-
this.container.addTextDisplayComponents(
|
|
3069
|
+
this.container.addTextDisplayComponents(
|
|
3070
|
+
(tdb) => tdb.setContent(Array.isArray(text) ? text.filter((t) => t !== null && t !== void 0).join("\n") : text)
|
|
3071
|
+
);
|
|
2986
3072
|
return this;
|
|
2987
3073
|
}
|
|
2988
3074
|
addMedia(...media) {
|
|
@@ -3006,7 +3092,9 @@ var BetterContainer = class {
|
|
|
3006
3092
|
this.container.addSectionComponents((sb) => {
|
|
3007
3093
|
if (data.text) {
|
|
3008
3094
|
sb.addTextDisplayComponents(
|
|
3009
|
-
(tdb) => tdb.setContent(
|
|
3095
|
+
(tdb) => tdb.setContent(
|
|
3096
|
+
Array.isArray(data.text) ? data.text.filter((t) => t !== null && t !== void 0).join("\n") : data.text
|
|
3097
|
+
)
|
|
3010
3098
|
);
|
|
3011
3099
|
}
|
|
3012
3100
|
if (data.thumbnail) sb.setThumbnailAccessory(new ThumbnailBuilder(data.thumbnail));
|
|
@@ -3237,6 +3325,7 @@ var BetterModal = class {
|
|
|
3237
3325
|
// src/tools/Paginator.ts
|
|
3238
3326
|
import {
|
|
3239
3327
|
ActionRowBuilder as ActionRowBuilder4,
|
|
3328
|
+
AttachmentBuilder as AttachmentBuilder2,
|
|
3240
3329
|
ButtonBuilder as ButtonBuilder3,
|
|
3241
3330
|
ButtonStyle as ButtonStyle2,
|
|
3242
3331
|
ComponentType as ComponentType2,
|
|
@@ -3256,6 +3345,7 @@ var PaginationTimeoutType = /* @__PURE__ */ ((PaginationTimeoutType2) => {
|
|
|
3256
3345
|
PaginationTimeoutType2[PaginationTimeoutType2["DisableComponents"] = 0] = "DisableComponents";
|
|
3257
3346
|
PaginationTimeoutType2[PaginationTimeoutType2["ClearComponents"] = 1] = "ClearComponents";
|
|
3258
3347
|
PaginationTimeoutType2[PaginationTimeoutType2["DeleteMessage"] = 2] = "DeleteMessage";
|
|
3348
|
+
PaginationTimeoutType2[PaginationTimeoutType2["DoNothing"] = 3] = "DoNothing";
|
|
3259
3349
|
return PaginationTimeoutType2;
|
|
3260
3350
|
})(PaginationTimeoutType || {});
|
|
3261
3351
|
function wrapPositive(num, max) {
|
|
@@ -3336,7 +3426,8 @@ var Paginator = class {
|
|
|
3336
3426
|
last: [],
|
|
3337
3427
|
collect: [],
|
|
3338
3428
|
react: [],
|
|
3339
|
-
|
|
3429
|
+
preTimeout: [],
|
|
3430
|
+
postTimeout: []
|
|
3340
3431
|
};
|
|
3341
3432
|
if (this.options.pages.length) {
|
|
3342
3433
|
this.addChapter(this.options.pages, { label: "Default" });
|
|
@@ -3403,16 +3494,23 @@ var Paginator = class {
|
|
|
3403
3494
|
embeds: [],
|
|
3404
3495
|
components: [],
|
|
3405
3496
|
flags: [],
|
|
3497
|
+
files: [],
|
|
3498
|
+
// Explicitly empty to clear previous files on page switch
|
|
3406
3499
|
...options,
|
|
3407
3500
|
withResponse: true
|
|
3408
3501
|
};
|
|
3409
3502
|
const page = this.data.page.current;
|
|
3503
|
+
const currentChapter = this.chapters[this.data.page.index.chapter];
|
|
3504
|
+
const chapterFile = currentChapter?.files?.[this.data.page.index.nested];
|
|
3505
|
+
if (chapterFile) sendOptions.files.push(chapterFile);
|
|
3410
3506
|
if (Array.isArray(page)) {
|
|
3411
3507
|
sendOptions.embeds.push(...page);
|
|
3412
3508
|
} else if (typeof page === "string") {
|
|
3413
3509
|
sendOptions.content = page;
|
|
3414
3510
|
} else if (isEmbed(page)) {
|
|
3415
3511
|
sendOptions.embeds.push(page);
|
|
3512
|
+
} else if (page instanceof AttachmentBuilder2) {
|
|
3513
|
+
sendOptions.files.push(page);
|
|
3416
3514
|
} else if (page instanceof ContainerBuilder3 || page instanceof BetterContainer) {
|
|
3417
3515
|
sendOptions.components.push(page);
|
|
3418
3516
|
if (!sendOptions.flags.includes("IsComponentsV2")) {
|
|
@@ -3424,7 +3522,7 @@ var Paginator = class {
|
|
|
3424
3522
|
}
|
|
3425
3523
|
async handlePostTimeout() {
|
|
3426
3524
|
if (!this.data.message) return;
|
|
3427
|
-
this.callEventStack("
|
|
3525
|
+
this.callEventStack("preTimeout", this.data.message);
|
|
3428
3526
|
this.data.collectors.component?.stop();
|
|
3429
3527
|
this.data.collectors.reaction?.stop();
|
|
3430
3528
|
switch (this.options.onTimeout) {
|
|
@@ -3468,7 +3566,10 @@ var Paginator = class {
|
|
|
3468
3566
|
case 2 /* DeleteMessage */:
|
|
3469
3567
|
await this.data.message.delete().catch(Boolean);
|
|
3470
3568
|
break;
|
|
3569
|
+
case 3 /* DoNothing */:
|
|
3570
|
+
break;
|
|
3471
3571
|
}
|
|
3572
|
+
this.callEventStack("postTimeout", this.data.message);
|
|
3472
3573
|
}
|
|
3473
3574
|
async nav_removeFromMessage() {
|
|
3474
3575
|
if (!this.data.message?.editable) return;
|
|
@@ -3515,35 +3616,43 @@ var Paginator = class {
|
|
|
3515
3616
|
await i.reply({ content: "Jump not implemented yet.", flags: "Ephemeral" });
|
|
3516
3617
|
return;
|
|
3517
3618
|
}
|
|
3518
|
-
await i.deferUpdate().catch(Boolean);
|
|
3519
3619
|
switch (i.customId) {
|
|
3520
3620
|
case "ssm_chapterSelect":
|
|
3621
|
+
await i.deferUpdate().catch(Boolean);
|
|
3521
3622
|
const chapterIndex = this.chapters.findIndex(
|
|
3522
3623
|
(c) => c.id === i.values[0]
|
|
3523
3624
|
);
|
|
3524
3625
|
await this.setPage(chapterIndex, 0);
|
|
3626
|
+
await this.refresh();
|
|
3525
3627
|
break;
|
|
3526
3628
|
case "btn_first":
|
|
3629
|
+
await i.deferUpdate().catch(Boolean);
|
|
3527
3630
|
this.callEventStack("first", this.data.page.current, this.data.page.index);
|
|
3528
3631
|
await this.setPage(this.data.page.index.chapter, 0);
|
|
3632
|
+
await this.refresh();
|
|
3529
3633
|
break;
|
|
3530
3634
|
case "btn_back":
|
|
3635
|
+
await i.deferUpdate().catch(Boolean);
|
|
3531
3636
|
this.callEventStack("back", this.data.page.current, this.data.page.index);
|
|
3532
3637
|
await this.setPage(this.data.page.index.chapter, this.data.page.index.nested - 1);
|
|
3638
|
+
await this.refresh();
|
|
3533
3639
|
break;
|
|
3534
3640
|
case "btn_next":
|
|
3641
|
+
await i.deferUpdate().catch(Boolean);
|
|
3535
3642
|
this.callEventStack("next", this.data.page.current, this.data.page.index);
|
|
3536
3643
|
await this.setPage(this.data.page.index.chapter, this.data.page.index.nested + 1);
|
|
3644
|
+
await this.refresh();
|
|
3537
3645
|
break;
|
|
3538
3646
|
case "btn_last":
|
|
3647
|
+
await i.deferUpdate().catch(Boolean);
|
|
3539
3648
|
this.callEventStack("last", this.data.page.current, this.data.page.index);
|
|
3540
3649
|
await this.setPage(
|
|
3541
3650
|
this.data.page.index.chapter,
|
|
3542
3651
|
this.chapters[this.data.page.index.chapter].pages.length - 1
|
|
3543
3652
|
);
|
|
3653
|
+
await this.refresh();
|
|
3544
3654
|
break;
|
|
3545
3655
|
}
|
|
3546
|
-
await this.refresh();
|
|
3547
3656
|
} catch (err) {
|
|
3548
3657
|
console.error("[Paginator] Component navigation error", err);
|
|
3549
3658
|
}
|
|
@@ -3583,7 +3692,7 @@ var Paginator = class {
|
|
|
3583
3692
|
data.value = `ssm_c:${this.chapters.length}`;
|
|
3584
3693
|
}
|
|
3585
3694
|
const normalizedPages = resolvePages(pages);
|
|
3586
|
-
this.chapters.push({ id: data.value, pages: normalizedPages });
|
|
3695
|
+
this.chapters.push({ id: data.value, pages: normalizedPages, files: data.files });
|
|
3587
3696
|
this.data.components.chapterSelect.addOptions(data);
|
|
3588
3697
|
return this;
|
|
3589
3698
|
}
|
|
@@ -3696,6 +3805,7 @@ var Prompt = class {
|
|
|
3696
3805
|
content;
|
|
3697
3806
|
embed;
|
|
3698
3807
|
container;
|
|
3808
|
+
textOnly;
|
|
3699
3809
|
buttons;
|
|
3700
3810
|
customButtons;
|
|
3701
3811
|
onResolve;
|
|
@@ -3709,6 +3819,7 @@ var Prompt = class {
|
|
|
3709
3819
|
this.content = options.content;
|
|
3710
3820
|
this.embed = options.embed ?? this.createDefaultForm();
|
|
3711
3821
|
this.container = options?.container;
|
|
3822
|
+
this.textOnly = options.textOnly;
|
|
3712
3823
|
this.buttons = this.createButtons(options.buttons);
|
|
3713
3824
|
this.customButtons = this.createCustomButtons(options.customButtons);
|
|
3714
3825
|
this.onResolve = options.onResolve ?? [3 /* DeleteOnConfirm */, 4 /* DeleteOnReject */];
|
|
@@ -3788,7 +3899,7 @@ var Prompt = class {
|
|
|
3788
3899
|
}
|
|
3789
3900
|
buildSendOptions(options) {
|
|
3790
3901
|
const sendData = { ...options };
|
|
3791
|
-
if (this.container) {
|
|
3902
|
+
if (!this.textOnly && this.container) {
|
|
3792
3903
|
sendData.components = Array.isArray(sendData.components) ? [...sendData.components, this.container] : [this.container];
|
|
3793
3904
|
const existingFlags = sendData.flags ? Array.isArray(sendData.flags) ? sendData.flags : [sendData.flags] : [];
|
|
3794
3905
|
if (!existingFlags.includes("IsComponentsV2")) {
|
|
@@ -3797,7 +3908,9 @@ var Prompt = class {
|
|
|
3797
3908
|
sendData.flags = existingFlags;
|
|
3798
3909
|
}
|
|
3799
3910
|
} else {
|
|
3800
|
-
|
|
3911
|
+
if (!this.textOnly) {
|
|
3912
|
+
sendData.embeds = Array.isArray(sendData.embeds) ? [this.embed, ...sendData.embeds] : [this.embed];
|
|
3913
|
+
}
|
|
3801
3914
|
}
|
|
3802
3915
|
if (this.content) {
|
|
3803
3916
|
sendData.content = this.content;
|
|
@@ -3883,7 +3996,7 @@ async function prompt(handler, options, sendOptions) {
|
|
|
3883
3996
|
|
|
3884
3997
|
// src/utils/VimcordCLI.ts
|
|
3885
3998
|
import { createInterface } from "readline";
|
|
3886
|
-
import
|
|
3999
|
+
import { $ as $3 } from "qznt";
|
|
3887
4000
|
var VimcordCLI = class {
|
|
3888
4001
|
rl;
|
|
3889
4002
|
options;
|
|
@@ -3922,7 +4035,7 @@ var VimcordCLI = class {
|
|
|
3922
4035
|
return { isCommand: true, commandName, content: args.join(" "), args };
|
|
3923
4036
|
}
|
|
3924
4037
|
getClientInstance(line) {
|
|
3925
|
-
const clientIndex =
|
|
4038
|
+
const clientIndex = $3.str.getFlag(line, "--client", 1) || $3.str.getFlag(line, "-c", 1);
|
|
3926
4039
|
if (clientIndex) {
|
|
3927
4040
|
const idx = Number(clientIndex);
|
|
3928
4041
|
if (isNaN(idx)) {
|
|
@@ -3965,21 +4078,25 @@ CLI.addCommand("help", "View information about a command, or the available CLI o
|
|
|
3965
4078
|
}
|
|
3966
4079
|
CLI.logger.table("(help)", helpList);
|
|
3967
4080
|
});
|
|
3968
|
-
CLI.addCommand("register", "Register app commands globally, or per guild", async (args, content) => {
|
|
4081
|
+
CLI.addCommand("register", "Register app commands (slash & context) globally, or per guild", async (args, content) => {
|
|
3969
4082
|
const client = CLI.getClientInstance(content);
|
|
3970
4083
|
if (!client) return;
|
|
3971
4084
|
const mode = args[0]?.toLowerCase() || "";
|
|
3972
4085
|
if (!["guild", "global"].includes(mode)) {
|
|
3973
4086
|
return CLI.logger.error(`'${mode}' is not a valid option. Your options are [guild|global]`);
|
|
3974
4087
|
}
|
|
3975
|
-
let guildIds = (
|
|
4088
|
+
let guildIds = ($3.str.getFlag(content, "--guilds", 1) || $3.str.getFlag(content, "-g", 1) || "").replaceAll(/["']/g, "").split(" ").filter(Boolean).map((s) => s.replaceAll(",", "").trim());
|
|
3976
4089
|
if (!guildIds.length) guildIds = client.guilds.cache.map((g) => g.id);
|
|
3977
4090
|
switch (mode) {
|
|
3978
4091
|
case "guild":
|
|
4092
|
+
CLI.logger.info("Registering guild commands...");
|
|
3979
4093
|
await client.commands.slash.registerGuild({ guilds: guildIds });
|
|
4094
|
+
await client.commands.context.registerGuild({ guilds: guildIds });
|
|
3980
4095
|
break;
|
|
3981
4096
|
case "global":
|
|
4097
|
+
CLI.logger.info("Registering global commands...");
|
|
3982
4098
|
await client.commands.slash.registerGlobal();
|
|
4099
|
+
await client.commands.context.registerGlobal();
|
|
3983
4100
|
break;
|
|
3984
4101
|
}
|
|
3985
4102
|
});
|
|
@@ -3990,14 +4107,18 @@ CLI.addCommand("unregister", "Unregister app commands globally, or per guild", a
|
|
|
3990
4107
|
if (!["guild", "global"].includes(mode)) {
|
|
3991
4108
|
return CLI.logger.error(`'${mode}' is not a valid option. Your options are [guild|global]`);
|
|
3992
4109
|
}
|
|
3993
|
-
let guildIds = (
|
|
4110
|
+
let guildIds = ($3.str.getFlag(content, "--guilds", 1) || $3.str.getFlag(content, "-g", 1) || "").replaceAll(/["']/g, "").split(" ").filter(Boolean).map((s) => s.replaceAll(",", "").trim());
|
|
3994
4111
|
if (!guildIds.length) guildIds = client.guilds.cache.map((g) => g.id);
|
|
3995
4112
|
switch (mode) {
|
|
3996
4113
|
case "guild":
|
|
4114
|
+
CLI.logger.info("Unregistering guild commands...");
|
|
3997
4115
|
await client.commands.slash.unregisterGuild({ guilds: guildIds });
|
|
4116
|
+
await client.commands.context.unregisterGuild({ guilds: guildIds });
|
|
3998
4117
|
break;
|
|
3999
4118
|
case "global":
|
|
4119
|
+
CLI.logger.info("Unregistering global commands...");
|
|
4000
4120
|
await client.commands.slash.unregisterGlobal();
|
|
4121
|
+
await client.commands.context.unregisterGlobal();
|
|
4001
4122
|
break;
|
|
4002
4123
|
}
|
|
4003
4124
|
});
|
|
@@ -4005,53 +4126,55 @@ CLI.addCommand("stats", "View statistics about a client instance", (args, conten
|
|
|
4005
4126
|
const client = CLI.getClientInstance(content);
|
|
4006
4127
|
if (!client) return;
|
|
4007
4128
|
CLI.logger.table(`(stats) ~ ${client.config.app.name}`, {
|
|
4008
|
-
"Guilds:":
|
|
4129
|
+
"Guilds:": $3.format.number(client.guilds.cache.size),
|
|
4009
4130
|
"Ping:": `${client.ws.ping || 0}ms`,
|
|
4010
|
-
"Uptime:": `${
|
|
4131
|
+
"Uptime:": `${$3.math.secs(client.uptime || 0)}s`,
|
|
4011
4132
|
"Process Uptime:": `${Math.floor(process.uptime())}s`,
|
|
4012
4133
|
"Memory Usage:": `${(process.memoryUsage().rss / 1024 / 1024).toFixed(2)} MB`
|
|
4013
4134
|
});
|
|
4014
4135
|
});
|
|
4015
|
-
CLI.addCommand("cmds", "List the loaded commands", (args, content) => {
|
|
4136
|
+
CLI.addCommand("cmds", "List the loaded commands", async (args, content) => {
|
|
4016
4137
|
const client = CLI.getClientInstance(content);
|
|
4017
4138
|
if (!client) return;
|
|
4018
|
-
const mode = args[0] || "slash";
|
|
4139
|
+
const mode = (args[0] || "slash").toLowerCase();
|
|
4019
4140
|
switch (mode) {
|
|
4020
|
-
case "slash":
|
|
4021
|
-
const
|
|
4022
|
-
|
|
4023
|
-
const
|
|
4024
|
-
for (const cmd of
|
|
4025
|
-
|
|
4141
|
+
case "slash": {
|
|
4142
|
+
const commands = Array.from(client.commands.slash.commands.values());
|
|
4143
|
+
commands.sort((a, b) => a.builder.name.localeCompare(b.builder.name));
|
|
4144
|
+
const tableData = {};
|
|
4145
|
+
for (const cmd of commands) {
|
|
4146
|
+
tableData[`/${cmd.builder.name}`] = `~ ${cmd.builder.description || "No description"}`;
|
|
4026
4147
|
}
|
|
4027
|
-
return CLI.logger.table(
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
);
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4148
|
+
return CLI.logger.table(`(cmds) ~ slash (${$3.format.number(commands.length)})`, tableData);
|
|
4149
|
+
}
|
|
4150
|
+
case "prefix": {
|
|
4151
|
+
const commands = Array.from(client.commands.prefix.commands.values());
|
|
4152
|
+
commands.sort((a, b) => {
|
|
4153
|
+
const nameA = a.toConfig().name;
|
|
4154
|
+
const nameB = b.toConfig().name;
|
|
4155
|
+
return nameA.localeCompare(nameB);
|
|
4156
|
+
});
|
|
4157
|
+
const tableData = {};
|
|
4158
|
+
const defaultPrefix = client.config.prefixCommands.defaultPrefix;
|
|
4159
|
+
for (const cmd of commands) {
|
|
4160
|
+
const config = cmd.toConfig();
|
|
4161
|
+
const aliasIndicator = config.aliases?.length ? ` [${config.aliases.join(", ")}]` : "";
|
|
4162
|
+
tableData[`${defaultPrefix}${config.name}${aliasIndicator}`] = `~ ${config.description || "No description"}`;
|
|
4037
4163
|
}
|
|
4038
|
-
return CLI.logger.table(
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
);
|
|
4042
|
-
|
|
4043
|
-
const
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
contextCommands_f[`${cmd.builder.name}`] = "";
|
|
4164
|
+
return CLI.logger.table(`(cmds) ~ prefix (${$3.format.number(commands.length)})`, tableData);
|
|
4165
|
+
}
|
|
4166
|
+
case "ctx": {
|
|
4167
|
+
const commands = Array.from(client.commands.context.commands.values());
|
|
4168
|
+
commands.sort((a, b) => a.builder.name.localeCompare(b.builder.name));
|
|
4169
|
+
const tableData = {};
|
|
4170
|
+
for (const cmd of commands) {
|
|
4171
|
+
const type = cmd.builder.type === 2 ? "User" : "Msg";
|
|
4172
|
+
tableData[`[${type}] ${cmd.builder.name}`] = "";
|
|
4048
4173
|
}
|
|
4049
|
-
return CLI.logger.table(
|
|
4050
|
-
|
|
4051
|
-
contextCommands_f
|
|
4052
|
-
);
|
|
4174
|
+
return CLI.logger.table(`(cmds) ~ ctx (${$3.format.number(commands.length)})`, tableData);
|
|
4175
|
+
}
|
|
4053
4176
|
default:
|
|
4054
|
-
return CLI.logger.error(`'${mode}' is not a valid option.
|
|
4177
|
+
return CLI.logger.error(`'${mode}' is not a valid option. Valid options: [slash|prefix|ctx]`);
|
|
4055
4178
|
}
|
|
4056
4179
|
});
|
|
4057
4180
|
function initCLI() {
|
|
@@ -4075,16 +4198,38 @@ function createClient(options, features = {}, config = {}) {
|
|
|
4075
4198
|
function getClientInstances() {
|
|
4076
4199
|
return clientInstances;
|
|
4077
4200
|
}
|
|
4201
|
+
|
|
4202
|
+
// src/utils/random.ts
|
|
4203
|
+
function pickRandom(arr, options) {
|
|
4204
|
+
const _rnd = () => {
|
|
4205
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
4206
|
+
};
|
|
4207
|
+
let att = 0;
|
|
4208
|
+
let candidate = _rnd();
|
|
4209
|
+
if (options?.notEqualTo !== void 0 && arr.length > 1) {
|
|
4210
|
+
while (candidate === options.notEqualTo) {
|
|
4211
|
+
if (att < (options?.maxRerollAttempts ?? 100)) {
|
|
4212
|
+
throw new Error(`pickRandom reached max reroll attempts (${options?.maxRerollAttempts ?? 100})`);
|
|
4213
|
+
}
|
|
4214
|
+
candidate = _rnd();
|
|
4215
|
+
att++;
|
|
4216
|
+
}
|
|
4217
|
+
}
|
|
4218
|
+
return options?.clone ? structuredClone(candidate) : candidate;
|
|
4219
|
+
}
|
|
4078
4220
|
export {
|
|
4079
4221
|
BaseCommandBuilder,
|
|
4222
|
+
BetterCollector,
|
|
4080
4223
|
BetterContainer,
|
|
4081
4224
|
BetterEmbed,
|
|
4082
4225
|
BetterModal,
|
|
4083
4226
|
CLI,
|
|
4227
|
+
CollectorTimeoutType,
|
|
4084
4228
|
CommandType,
|
|
4085
4229
|
ContextCommandBuilder,
|
|
4086
4230
|
DynaSend,
|
|
4087
4231
|
EventBuilder,
|
|
4232
|
+
LOGGER_COLORS,
|
|
4088
4233
|
LogLevel,
|
|
4089
4234
|
Logger,
|
|
4090
4235
|
MissingPermissionReason,
|
|
@@ -4113,6 +4258,7 @@ export {
|
|
|
4113
4258
|
clientInstances,
|
|
4114
4259
|
createClient,
|
|
4115
4260
|
createMongoSchema,
|
|
4261
|
+
createMongoSession,
|
|
4116
4262
|
createToolsConfig,
|
|
4117
4263
|
createVimcordAppConfig,
|
|
4118
4264
|
createVimcordContextCommandConfig,
|
|
@@ -4146,6 +4292,7 @@ export {
|
|
|
4146
4292
|
useClient,
|
|
4147
4293
|
useMongoDatabase,
|
|
4148
4294
|
useReadyClient,
|
|
4295
|
+
useReadyMongoDatabase,
|
|
4149
4296
|
validateCommandPermissions
|
|
4150
4297
|
};
|
|
4151
4298
|
//# sourceMappingURL=index.js.map
|