vimcord 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +834 -649
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +287 -182
- package/dist/index.d.ts +287 -182
- package/dist/index.js +830 -649
- 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);
|
|
187
|
+
}
|
|
188
|
+
const perms = this.checkPermissions(client, ctx.member || ctx.user, args[1]);
|
|
189
|
+
if (!perms.validated) {
|
|
190
|
+
return await config.onMissingPermissions?.(perms, ...args);
|
|
179
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;
|
|
201
286
|
return this;
|
|
202
287
|
}
|
|
288
|
+
/** Merge new permission requirements into the existing ones */
|
|
289
|
+
setPermissions(perms) {
|
|
290
|
+
this.options.permissions = _.merge(this.options.permissions || {}, perms);
|
|
291
|
+
return this;
|
|
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,73 +375,48 @@ 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
|
|
|
@@ -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();
|
|
673
|
+
}
|
|
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
|
+
}
|
|
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;
|
|
730
706
|
}
|
|
731
|
-
|
|
707
|
+
/**
|
|
708
|
+
* Set the command description.
|
|
709
|
+
*/
|
|
710
|
+
setDescription(description) {
|
|
711
|
+
this.options.description = description;
|
|
712
|
+
return this;
|
|
732
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;
|
|
@@ -1462,236 +1419,187 @@ var VimcordStatusManager = class {
|
|
|
1462
1419
|
|
|
1463
1420
|
// src/modules/command.manager.ts
|
|
1464
1421
|
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) {
|
|
1422
|
+
var VimcordAppCommandManager = class {
|
|
1423
|
+
constructor(client, typeName) {
|
|
1477
1424
|
this.client = client;
|
|
1478
|
-
|
|
1425
|
+
this.typeName = typeName;
|
|
1426
|
+
this.client.whenReady().then((c) => this.rest = new REST().setToken(c.token));
|
|
1479
1427
|
}
|
|
1480
1428
|
commands = /* @__PURE__ */ new Map();
|
|
1481
1429
|
rest;
|
|
1482
1430
|
get(name) {
|
|
1483
1431
|
return this.commands.get(name);
|
|
1484
1432
|
}
|
|
1433
|
+
/**
|
|
1434
|
+
* Filters and returns commands based on deployment options
|
|
1435
|
+
*/
|
|
1485
1436
|
getAll(options) {
|
|
1486
1437
|
const matchedCommands = /* @__PURE__ */ new Map();
|
|
1438
|
+
const isDev = this.client.config.app.devMode;
|
|
1487
1439
|
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;
|
|
1440
|
+
const config = cmd.toConfig();
|
|
1441
|
+
const name = cmd.builder.name;
|
|
1442
|
+
if (options?.names || options?.fuzzyNames) {
|
|
1443
|
+
const nameMatched = options.names?.includes(name) || options.fuzzyNames?.some((fuzzy) => name.includes(fuzzy));
|
|
1444
|
+
if (!nameMatched) continue;
|
|
1501
1445
|
}
|
|
1502
|
-
if (!matched) continue;
|
|
1503
1446
|
if (options?.ignoreDeploymentOptions) {
|
|
1504
|
-
|
|
1505
|
-
matchedCommands.set(matched.builder.name, matched);
|
|
1447
|
+
matchedCommands.set(name, cmd);
|
|
1506
1448
|
continue;
|
|
1507
1449
|
}
|
|
1508
|
-
const
|
|
1509
|
-
|
|
1510
|
-
);
|
|
1511
|
-
if (
|
|
1512
|
-
|
|
1513
|
-
}
|
|
1450
|
+
const deployment = config.deployment || {};
|
|
1451
|
+
const isProperEnv = !deployment.environments || deployment.environments.includes(isDev ? "development" : "production");
|
|
1452
|
+
if (!isProperEnv) continue;
|
|
1453
|
+
if (options?.globalOnly && deployment.global === false) continue;
|
|
1454
|
+
matchedCommands.set(name, cmd);
|
|
1514
1455
|
}
|
|
1515
1456
|
return matchedCommands;
|
|
1516
1457
|
}
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
this.
|
|
1458
|
+
async registerGlobal(options) {
|
|
1459
|
+
const client = await this.client.whenReady();
|
|
1460
|
+
const commands = Array.from(
|
|
1461
|
+
this.getAll({
|
|
1462
|
+
names: options?.commands,
|
|
1463
|
+
fuzzyNames: options?.fuzzyCommands,
|
|
1464
|
+
globalOnly: true
|
|
1465
|
+
}).values()
|
|
1466
|
+
).map((cmd) => cmd.builder.toJSON());
|
|
1467
|
+
if (!commands.length) {
|
|
1468
|
+
console.log(`[${this.typeName}] No commands to register`);
|
|
1469
|
+
return;
|
|
1521
1470
|
}
|
|
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
|
-
}
|
|
1471
|
+
console.log(`[${this.typeName}] Registering ${commands.length} commands globally...`);
|
|
1472
|
+
try {
|
|
1473
|
+
await this.rest.put(Routes.applicationCommands(client.user.id), { body: commands });
|
|
1474
|
+
console.log(`[${this.typeName}] \u2714 Registered app commands globally`);
|
|
1475
|
+
} catch (err) {
|
|
1476
|
+
console.log(`[${this.typeName}] \u2716 Failed to register app commands globally`, err);
|
|
1535
1477
|
}
|
|
1536
|
-
this.client.logger.moduleLoaded("Slash Commands", importedCommands);
|
|
1537
|
-
return this.commands;
|
|
1538
1478
|
}
|
|
1539
1479
|
async registerGuild(options) {
|
|
1540
1480
|
const client = await this.client.whenReady();
|
|
1541
|
-
const
|
|
1481
|
+
const commands = Array.from(
|
|
1542
1482
|
this.getAll({
|
|
1543
1483
|
names: options?.commands,
|
|
1544
1484
|
fuzzyNames: options?.fuzzyCommands
|
|
1545
1485
|
}).values()
|
|
1546
1486
|
).map((cmd) => cmd.builder.toJSON());
|
|
1547
|
-
if (!
|
|
1548
|
-
console.log(
|
|
1487
|
+
if (!commands.length) {
|
|
1488
|
+
console.log(`[${this.typeName}] No commands to register`);
|
|
1549
1489
|
return;
|
|
1550
1490
|
}
|
|
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
|
-
);
|
|
1491
|
+
const guildIds = options?.guilds || client.guilds.cache.map((g) => g.id);
|
|
1492
|
+
console.log(`[${this.typeName}] Registering ${commands.length} commands for ${guildIds.length} guilds...`);
|
|
1555
1493
|
await Promise.all(
|
|
1556
1494
|
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
|
-
)
|
|
1495
|
+
(guildId) => this.rest.put(Routes.applicationGuildCommands(client.user.id, guildId), { body: commands }).then(() => {
|
|
1496
|
+
const gName = client.guilds.cache.get(guildId)?.name || "n/a";
|
|
1497
|
+
console.log(`[${this.typeName}] \u2714 Set app commands in guild: ${guildId} (${gName})`);
|
|
1498
|
+
}).catch((err) => {
|
|
1499
|
+
const gName = client.guilds.cache.get(guildId)?.name || "n/a";
|
|
1500
|
+
console.log(`[${this.typeName}] \u2716 Failed to set app commands in guild: ${guildId} (${gName})`, err);
|
|
1501
|
+
})
|
|
1569
1502
|
)
|
|
1570
1503
|
);
|
|
1571
|
-
console.log(
|
|
1572
|
-
`[SlashCommandManager] \u2714 Finished registering app (/) commands for ${guildIds.length} ${guildIds.length === 1 ? "guild" : "guilds"}`
|
|
1573
|
-
);
|
|
1574
1504
|
}
|
|
1575
1505
|
async unregisterGuild(options) {
|
|
1576
1506
|
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
|
-
);
|
|
1507
|
+
const guildIds = options?.guilds || client.guilds.cache.map((g) => g.id);
|
|
1508
|
+
console.log(`[${this.typeName}] Unregistering commands from ${guildIds.length} guilds...`);
|
|
1581
1509
|
await Promise.all(
|
|
1582
1510
|
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
|
-
)
|
|
1511
|
+
(guildId) => this.rest.put(Routes.applicationGuildCommands(client.user.id, guildId), { body: [] }).then(() => console.log(`[${this.typeName}] \u2714 Removed app commands in guild: ${guildId}`)).catch(
|
|
1512
|
+
(err) => console.log(`[${this.typeName}] \u2716 Failed to remove app commands in guild: ${guildId}`, err)
|
|
1594
1513
|
)
|
|
1595
1514
|
)
|
|
1596
1515
|
);
|
|
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
1516
|
}
|
|
1624
1517
|
async unregisterGlobal() {
|
|
1625
1518
|
const client = await this.client.whenReady();
|
|
1626
|
-
console.log("[SlashCommandManager] Unregistering app (/) commands globally...");
|
|
1627
1519
|
try {
|
|
1628
1520
|
await this.rest.put(Routes.applicationCommands(client.user.id), { body: [] });
|
|
1629
|
-
console.log(
|
|
1521
|
+
console.log(`[${this.typeName}] \u2714 Removed app commands globally`);
|
|
1630
1522
|
} catch (err) {
|
|
1631
|
-
console.log(
|
|
1523
|
+
console.log(`[${this.typeName}] \u2716 Failed to remove app commands globally`, err);
|
|
1632
1524
|
}
|
|
1633
1525
|
}
|
|
1634
1526
|
};
|
|
1635
|
-
var
|
|
1527
|
+
var VimcordSlashCommandManager = class extends VimcordAppCommandManager {
|
|
1636
1528
|
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));
|
|
1529
|
+
super(client, "SlashCommandManager");
|
|
1530
|
+
}
|
|
1531
|
+
async importFrom(dir, replaceAll = false) {
|
|
1532
|
+
if (replaceAll) this.commands.clear();
|
|
1533
|
+
const dirs = Array.isArray(dir) ? dir : [dir];
|
|
1534
|
+
const modules = (await Promise.all(
|
|
1535
|
+
dirs.map((d) => importModulesFromDir(d, "slash"))
|
|
1536
|
+
)).flat();
|
|
1537
|
+
for (const { module } of modules) {
|
|
1538
|
+
this.commands.set(module.default.builder.name, module.default);
|
|
1539
|
+
}
|
|
1540
|
+
this.client.logger.moduleLoaded("Slash Commands", modules.length);
|
|
1541
|
+
return this.commands;
|
|
1653
1542
|
}
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
}
|
|
1668
|
-
this.client.logger.moduleLoaded("
|
|
1543
|
+
};
|
|
1544
|
+
var VimcordContextCommandManager = class extends VimcordAppCommandManager {
|
|
1545
|
+
constructor(client) {
|
|
1546
|
+
super(client, "ContextCommandManager");
|
|
1547
|
+
}
|
|
1548
|
+
async importFrom(dir, replaceAll = false) {
|
|
1549
|
+
if (replaceAll) this.commands.clear();
|
|
1550
|
+
const dirs = Array.isArray(dir) ? dir : [dir];
|
|
1551
|
+
const modules = (await Promise.all(
|
|
1552
|
+
dirs.map((d) => importModulesFromDir(d, "ctx"))
|
|
1553
|
+
)).flat();
|
|
1554
|
+
for (const { module } of modules) {
|
|
1555
|
+
this.commands.set(module.default.builder.name, module.default);
|
|
1556
|
+
}
|
|
1557
|
+
this.client.logger.moduleLoaded("Context Commands", modules.length);
|
|
1669
1558
|
return this.commands;
|
|
1670
1559
|
}
|
|
1671
1560
|
};
|
|
1672
|
-
var
|
|
1561
|
+
var VimcordPrefixCommandManager = class {
|
|
1673
1562
|
constructor(client) {
|
|
1674
1563
|
this.client = client;
|
|
1675
1564
|
}
|
|
1676
1565
|
commands = /* @__PURE__ */ new Map();
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1566
|
+
resolve(trigger) {
|
|
1567
|
+
const config = this.client.config.prefixCommands;
|
|
1568
|
+
const search = config.allowCaseInsensitiveCommandNames ? trigger.toLowerCase() : trigger;
|
|
1569
|
+
return Array.from(this.commands.values()).find((cmd) => {
|
|
1570
|
+
const opts = cmd.toConfig();
|
|
1571
|
+
const name = config.allowCaseInsensitiveCommandNames ? opts.name.toLowerCase() : opts.name;
|
|
1572
|
+
if (name === search) return true;
|
|
1573
|
+
return opts.aliases?.some(
|
|
1574
|
+
(a) => config.allowCaseInsensitiveCommandNames ? a.toLowerCase() === search : a === search
|
|
1575
|
+
);
|
|
1576
|
+
});
|
|
1577
|
+
}
|
|
1578
|
+
async importFrom(dir, replaceAll = false) {
|
|
1579
|
+
if (replaceAll) this.commands.clear();
|
|
1580
|
+
const dirs = Array.isArray(dir) ? dir : [dir];
|
|
1581
|
+
const modules = (await Promise.all(
|
|
1582
|
+
dirs.map(
|
|
1583
|
+
(d) => importModulesFromDir(d, "prefix")
|
|
1584
|
+
)
|
|
1585
|
+
)).flat();
|
|
1586
|
+
for (const { module } of modules) {
|
|
1587
|
+
this.commands.set(module.default.toConfig().name, module.default);
|
|
1690
1588
|
}
|
|
1691
|
-
this.client.logger.moduleLoaded("
|
|
1589
|
+
this.client.logger.moduleLoaded("Prefix Commands", modules.length);
|
|
1692
1590
|
return this.commands;
|
|
1693
1591
|
}
|
|
1694
1592
|
};
|
|
1593
|
+
var VimcordCommandManager = class {
|
|
1594
|
+
slash;
|
|
1595
|
+
prefix;
|
|
1596
|
+
context;
|
|
1597
|
+
constructor(client) {
|
|
1598
|
+
this.slash = new VimcordSlashCommandManager(client);
|
|
1599
|
+
this.prefix = new VimcordPrefixCommandManager(client);
|
|
1600
|
+
this.context = new VimcordContextCommandManager(client);
|
|
1601
|
+
}
|
|
1602
|
+
};
|
|
1695
1603
|
|
|
1696
1604
|
// src/modules/event.manager.ts
|
|
1697
1605
|
import { Events } from "discord.js";
|
|
@@ -2087,7 +1995,7 @@ var BetterEmbed = class _BetterEmbed {
|
|
|
2087
1995
|
}
|
|
2088
1996
|
if (this.data.description) {
|
|
2089
1997
|
this.data.description = formatString(
|
|
2090
|
-
Array.isArray(this.data.description) ? this.data.description.join("\n") : this.data.description
|
|
1998
|
+
Array.isArray(this.data.description) ? this.data.description.filter((s) => s !== null && s !== void 0).join("\n") : this.data.description
|
|
2091
1999
|
);
|
|
2092
2000
|
}
|
|
2093
2001
|
if (this.data.footer && typeof this.data.footer === "object") {
|
|
@@ -2099,7 +2007,7 @@ var BetterEmbed = class _BetterEmbed {
|
|
|
2099
2007
|
if (this.data.imageUrl) {
|
|
2100
2008
|
this.data.imageUrl = formatString(this.data.imageUrl);
|
|
2101
2009
|
}
|
|
2102
|
-
this.data.fields = this.data.fields.map((field) => ({
|
|
2010
|
+
this.data.fields = this.data.fields.filter(Boolean).map((field) => ({
|
|
2103
2011
|
...field,
|
|
2104
2012
|
name: formatString(field.name),
|
|
2105
2013
|
value: formatString(field.value)
|
|
@@ -2324,7 +2232,7 @@ async function retryExponentialBackoff(fn, maxRetries = 3, retryDelay = 1e3) {
|
|
|
2324
2232
|
}
|
|
2325
2233
|
|
|
2326
2234
|
// package.json
|
|
2327
|
-
var version = "1.0.
|
|
2235
|
+
var version = "1.0.1";
|
|
2328
2236
|
|
|
2329
2237
|
// src/client.ts
|
|
2330
2238
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
@@ -2590,62 +2498,63 @@ var Vimcord = class _Vimcord extends Client2 {
|
|
|
2590
2498
|
return fetchGuild(client, id);
|
|
2591
2499
|
}
|
|
2592
2500
|
};
|
|
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
2501
|
var defaultPrefixCommandHandler = new EventBuilder({
|
|
2617
2502
|
event: "messageCreate",
|
|
2618
2503
|
name: "PrefixCommandHandler",
|
|
2619
2504
|
async execute(client, message) {
|
|
2620
|
-
if (message.author.bot) return;
|
|
2505
|
+
if (message.author.bot || !message.guild) return;
|
|
2506
|
+
const config = client.config.prefixCommands;
|
|
2507
|
+
let activePrefix = config.defaultPrefix;
|
|
2508
|
+
if (config.guildPrefixResolver) {
|
|
2509
|
+
try {
|
|
2510
|
+
const customPrefix = await config.guildPrefixResolver(client, message.guild.id);
|
|
2511
|
+
if (customPrefix) activePrefix = customPrefix;
|
|
2512
|
+
} catch (err) {
|
|
2513
|
+
client.logger.error(`Error in guildPrefixResolver for guild ${message.guild.id}:`, err);
|
|
2514
|
+
}
|
|
2515
|
+
}
|
|
2621
2516
|
let prefixUsed;
|
|
2622
|
-
if (
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
}
|
|
2629
|
-
} else {
|
|
2630
|
-
return;
|
|
2517
|
+
if (message.content.startsWith(activePrefix)) {
|
|
2518
|
+
prefixUsed = activePrefix;
|
|
2519
|
+
} else if (config.allowMentionAsPrefix) {
|
|
2520
|
+
const mention = userMention(client.user.id);
|
|
2521
|
+
if (message.content.startsWith(mention)) {
|
|
2522
|
+
prefixUsed = message.content.startsWith(`${mention} `) ? `${mention} ` : mention;
|
|
2631
2523
|
}
|
|
2632
|
-
} else {
|
|
2633
|
-
prefixUsed = client.config.prefixCommands.defaultPrefix;
|
|
2634
2524
|
}
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2525
|
+
if (!prefixUsed) return;
|
|
2526
|
+
const contentWithoutPrefix = message.content.slice(prefixUsed.length).trim();
|
|
2527
|
+
const args = contentWithoutPrefix.split(/\s+/);
|
|
2528
|
+
const trigger = args.shift();
|
|
2529
|
+
if (!trigger) return;
|
|
2530
|
+
const command = client.commands.prefix.resolve(trigger);
|
|
2531
|
+
if (!command) return;
|
|
2532
|
+
message.content = args.join(" ");
|
|
2533
|
+
try {
|
|
2534
|
+
return await command.run(client, client, message);
|
|
2535
|
+
} catch (err) {
|
|
2536
|
+
await sendCommandErrorEmbed(client, err, message.guild, message);
|
|
2537
|
+
throw err;
|
|
2639
2538
|
}
|
|
2640
|
-
|
|
2539
|
+
}
|
|
2540
|
+
});
|
|
2541
|
+
var defaultSlashCommandHandler = new EventBuilder({
|
|
2542
|
+
event: "interactionCreate",
|
|
2543
|
+
name: "SlashCommandHandler",
|
|
2544
|
+
async execute(client, interaction) {
|
|
2545
|
+
if (!interaction.isChatInputCommand()) return;
|
|
2546
|
+
const command = client.commands.slash.get(interaction.commandName);
|
|
2641
2547
|
if (!command) {
|
|
2642
|
-
|
|
2548
|
+
const content = `**/\`${interaction.commandName}\`** is not a registered command.`;
|
|
2549
|
+
if (interaction.replied || interaction.deferred) {
|
|
2550
|
+
return interaction.followUp({ content, flags: "Ephemeral" });
|
|
2551
|
+
}
|
|
2552
|
+
return interaction.reply({ content, flags: "Ephemeral" });
|
|
2643
2553
|
}
|
|
2644
|
-
message.content = message.content.slice(commandName.length + 1);
|
|
2645
2554
|
try {
|
|
2646
|
-
return command.
|
|
2555
|
+
return await command.run(client, client, interaction);
|
|
2647
2556
|
} catch (err) {
|
|
2648
|
-
sendCommandErrorEmbed(client, err,
|
|
2557
|
+
await sendCommandErrorEmbed(client, err, interaction.guild, interaction);
|
|
2649
2558
|
throw err;
|
|
2650
2559
|
}
|
|
2651
2560
|
}
|
|
@@ -2653,9 +2562,22 @@ var defaultPrefixCommandHandler = new EventBuilder({
|
|
|
2653
2562
|
var defaultContextCommandHandler = new EventBuilder({
|
|
2654
2563
|
event: "interactionCreate",
|
|
2655
2564
|
name: "ContextCommandHandler",
|
|
2656
|
-
execute(client, interaction) {
|
|
2565
|
+
async execute(client, interaction) {
|
|
2657
2566
|
if (!interaction.isContextMenuCommand()) return;
|
|
2658
|
-
|
|
2567
|
+
const command = client.commands.context.get(interaction.commandName);
|
|
2568
|
+
if (!command) {
|
|
2569
|
+
const content = `**${interaction.commandName}** is not a registered context command.`;
|
|
2570
|
+
if (interaction.replied || interaction.deferred) {
|
|
2571
|
+
return interaction.followUp({ content, flags: "Ephemeral" });
|
|
2572
|
+
}
|
|
2573
|
+
return interaction.reply({ content, flags: "Ephemeral" });
|
|
2574
|
+
}
|
|
2575
|
+
try {
|
|
2576
|
+
return await command.run(client, client, interaction);
|
|
2577
|
+
} catch (err) {
|
|
2578
|
+
await sendCommandErrorEmbed(client, err, interaction.guild, interaction);
|
|
2579
|
+
throw err;
|
|
2580
|
+
}
|
|
2659
2581
|
}
|
|
2660
2582
|
});
|
|
2661
2583
|
|
|
@@ -2670,8 +2592,8 @@ try {
|
|
|
2670
2592
|
}
|
|
2671
2593
|
var globalInstanceEmitter = new EventEmitter2();
|
|
2672
2594
|
var instances = [];
|
|
2673
|
-
async function useMongoDatabase(
|
|
2674
|
-
const instance = instances.at(
|
|
2595
|
+
async function useMongoDatabase(instanceIndex) {
|
|
2596
|
+
const instance = instances.at(instanceIndex ?? 0);
|
|
2675
2597
|
if (!instance) {
|
|
2676
2598
|
return new Promise((resolve, reject) => {
|
|
2677
2599
|
const timeout = setTimeout(() => reject("useMongoDatabase timed out"), 45e3);
|
|
@@ -2683,6 +2605,15 @@ async function useMongoDatabase(index) {
|
|
|
2683
2605
|
}
|
|
2684
2606
|
return instance;
|
|
2685
2607
|
}
|
|
2608
|
+
async function useReadyMongoDatabase(instanceIndex) {
|
|
2609
|
+
const instance = await useMongoDatabase(instanceIndex);
|
|
2610
|
+
await instance.waitForReady();
|
|
2611
|
+
return instance;
|
|
2612
|
+
}
|
|
2613
|
+
async function createMongoSession(instanceIndex, options) {
|
|
2614
|
+
const instance = await useReadyMongoDatabase(instanceIndex);
|
|
2615
|
+
return instance.mongoose.startSession(options);
|
|
2616
|
+
}
|
|
2686
2617
|
var MongoDatabase = class {
|
|
2687
2618
|
constructor(client, options) {
|
|
2688
2619
|
this.client = client;
|
|
@@ -2839,6 +2770,7 @@ var MongoSchemaBuilder = class {
|
|
|
2839
2770
|
this.eventEmitter.off(event, listener);
|
|
2840
2771
|
return this;
|
|
2841
2772
|
}
|
|
2773
|
+
/** Execute a function while ensuring the connection is ready. On error it will retry using an exponential backoff. */
|
|
2842
2774
|
async execute(fn) {
|
|
2843
2775
|
try {
|
|
2844
2776
|
if (!this.isReady) {
|
|
@@ -2875,9 +2807,9 @@ var MongoSchemaBuilder = class {
|
|
|
2875
2807
|
return id;
|
|
2876
2808
|
});
|
|
2877
2809
|
}
|
|
2878
|
-
async count(filter) {
|
|
2810
|
+
async count(filter, options) {
|
|
2879
2811
|
return await this.execute(async () => {
|
|
2880
|
-
return this.model.countDocuments(filter);
|
|
2812
|
+
return this.model.countDocuments(filter, options);
|
|
2881
2813
|
});
|
|
2882
2814
|
}
|
|
2883
2815
|
async exists(filter) {
|
|
@@ -2885,29 +2817,29 @@ var MongoSchemaBuilder = class {
|
|
|
2885
2817
|
return await this.model.exists(filter) ? true : false;
|
|
2886
2818
|
});
|
|
2887
2819
|
}
|
|
2888
|
-
async create(query) {
|
|
2820
|
+
async create(query, options) {
|
|
2889
2821
|
return await this.execute(async () => {
|
|
2890
|
-
return this.model.create(query);
|
|
2891
|
-
});
|
|
2822
|
+
return this.model.create(query, options);
|
|
2823
|
+
}) ?? [];
|
|
2892
2824
|
}
|
|
2893
2825
|
async upsert(filter, query, options) {
|
|
2894
2826
|
return await this.execute(async () => {
|
|
2895
2827
|
return this.model.findOneAndUpdate(filter, query, { ...options, upsert: true, new: true });
|
|
2896
2828
|
});
|
|
2897
2829
|
}
|
|
2898
|
-
async delete(filter) {
|
|
2830
|
+
async delete(filter, options) {
|
|
2899
2831
|
return await this.execute(async () => {
|
|
2900
|
-
return this.model.deleteOne(filter);
|
|
2832
|
+
return this.model.deleteOne(filter, options);
|
|
2901
2833
|
});
|
|
2902
2834
|
}
|
|
2903
|
-
async deleteAll(filter) {
|
|
2835
|
+
async deleteAll(filter, options) {
|
|
2904
2836
|
return await this.execute(async () => {
|
|
2905
|
-
return this.model.deleteMany(filter);
|
|
2837
|
+
return this.model.deleteMany(filter, options);
|
|
2906
2838
|
});
|
|
2907
2839
|
}
|
|
2908
|
-
async distinct(key, filter) {
|
|
2840
|
+
async distinct(key, filter, options) {
|
|
2909
2841
|
return await this.execute(async () => {
|
|
2910
|
-
return this.model.distinct(key, filter);
|
|
2842
|
+
return this.model.distinct(key, filter, options);
|
|
2911
2843
|
});
|
|
2912
2844
|
}
|
|
2913
2845
|
async fetch(filter, projection, options) {
|
|
@@ -2938,6 +2870,215 @@ var MongoSchemaBuilder = class {
|
|
|
2938
2870
|
}
|
|
2939
2871
|
};
|
|
2940
2872
|
|
|
2873
|
+
// src/tools/BetterCollector.ts
|
|
2874
|
+
var CollectorTimeoutType = /* @__PURE__ */ ((CollectorTimeoutType2) => {
|
|
2875
|
+
CollectorTimeoutType2[CollectorTimeoutType2["DisableComponents"] = 0] = "DisableComponents";
|
|
2876
|
+
CollectorTimeoutType2[CollectorTimeoutType2["DeleteMessage"] = 1] = "DeleteMessage";
|
|
2877
|
+
CollectorTimeoutType2[CollectorTimeoutType2["DoNothing"] = 2] = "DoNothing";
|
|
2878
|
+
return CollectorTimeoutType2;
|
|
2879
|
+
})(CollectorTimeoutType || {});
|
|
2880
|
+
var BetterCollector = class _BetterCollector {
|
|
2881
|
+
message;
|
|
2882
|
+
collector;
|
|
2883
|
+
options;
|
|
2884
|
+
activeUsers = /* @__PURE__ */ new Set();
|
|
2885
|
+
participantWarningCooldowns = /* @__PURE__ */ new Map();
|
|
2886
|
+
config;
|
|
2887
|
+
events = {
|
|
2888
|
+
collectId: /* @__PURE__ */ new Map(),
|
|
2889
|
+
collect: [],
|
|
2890
|
+
end: [],
|
|
2891
|
+
timeout: []
|
|
2892
|
+
};
|
|
2893
|
+
static create(message, options) {
|
|
2894
|
+
return new _BetterCollector(message, options);
|
|
2895
|
+
}
|
|
2896
|
+
async validateParticipant(interaction, participants) {
|
|
2897
|
+
const allowedParticipants = participants || this.options?.participants || [];
|
|
2898
|
+
if (!allowedParticipants.length) return true;
|
|
2899
|
+
const isAllowed = allowedParticipants.some((user) => {
|
|
2900
|
+
if (typeof user === "string") return user === interaction.user.id;
|
|
2901
|
+
if (typeof user === "object" && "id" in user) return user.id === interaction.user.id;
|
|
2902
|
+
return false;
|
|
2903
|
+
});
|
|
2904
|
+
if (!isAllowed) {
|
|
2905
|
+
const now = Date.now();
|
|
2906
|
+
const lastWarned = this.participantWarningCooldowns.get(interaction.user.id) || 0;
|
|
2907
|
+
if (now - lastWarned > this.config.collector.notAParticipantWarningCooldown) {
|
|
2908
|
+
this.participantWarningCooldowns.set(interaction.user.id, now);
|
|
2909
|
+
if (this.config.collector.notAParticipantMessage) {
|
|
2910
|
+
await interaction.reply({
|
|
2911
|
+
content: this.config.collector.notAParticipantMessage,
|
|
2912
|
+
flags: "Ephemeral"
|
|
2913
|
+
}).catch(() => {
|
|
2914
|
+
});
|
|
2915
|
+
} else {
|
|
2916
|
+
await interaction.deferUpdate().catch(() => {
|
|
2917
|
+
});
|
|
2918
|
+
}
|
|
2919
|
+
} else {
|
|
2920
|
+
await interaction.deferUpdate().catch(() => {
|
|
2921
|
+
});
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
return isAllowed;
|
|
2925
|
+
}
|
|
2926
|
+
build() {
|
|
2927
|
+
if (!this.message) return;
|
|
2928
|
+
if (this.collector) return;
|
|
2929
|
+
this.collector = this.message.createMessageComponentCollector({
|
|
2930
|
+
idle: this.options?.idle ?? this.config.timeouts.collectorIdle,
|
|
2931
|
+
time: this.options?.timeout ?? this.config.timeouts.collectorTimeout,
|
|
2932
|
+
componentType: this.options?.type,
|
|
2933
|
+
max: this.options?.max,
|
|
2934
|
+
maxComponents: this.options?.maxComponents,
|
|
2935
|
+
maxUsers: this.options?.maxUsers
|
|
2936
|
+
});
|
|
2937
|
+
this.setupListeners();
|
|
2938
|
+
}
|
|
2939
|
+
setupListeners() {
|
|
2940
|
+
if (!this.collector) return;
|
|
2941
|
+
this.collector.on("collect", async (interaction) => {
|
|
2942
|
+
if (this.options?.userLock && this.activeUsers.has(interaction.user.id)) {
|
|
2943
|
+
return interaction.reply({ content: this.config.collector.userLockMessage, flags: "Ephemeral" }).catch(() => {
|
|
2944
|
+
});
|
|
2945
|
+
}
|
|
2946
|
+
if (this.options?.userLock) {
|
|
2947
|
+
this.activeUsers.add(interaction.user.id);
|
|
2948
|
+
}
|
|
2949
|
+
const globalListeners = this.events.collect;
|
|
2950
|
+
const idListeners = this.events.collectId.get(interaction.customId) || [];
|
|
2951
|
+
const allListeners = [...globalListeners, ...idListeners];
|
|
2952
|
+
const shouldBeDeferred = allListeners.find((l) => l.options?.defer)?.options?.defer;
|
|
2953
|
+
const validListeners = [];
|
|
2954
|
+
for (const listener of allListeners) {
|
|
2955
|
+
const isAllowed = await this.validateParticipant(interaction, listener.options?.participants);
|
|
2956
|
+
if (isAllowed) validListeners.push(listener);
|
|
2957
|
+
}
|
|
2958
|
+
if (validListeners.length === 0) return;
|
|
2959
|
+
try {
|
|
2960
|
+
if (shouldBeDeferred) {
|
|
2961
|
+
if (typeof shouldBeDeferred === "object") {
|
|
2962
|
+
if (shouldBeDeferred.update) {
|
|
2963
|
+
await interaction.deferUpdate().catch(Boolean);
|
|
2964
|
+
} else {
|
|
2965
|
+
await interaction.deferReply({ ephemeral: shouldBeDeferred.ephemeral }).catch(Boolean);
|
|
2966
|
+
}
|
|
2967
|
+
} else {
|
|
2968
|
+
await interaction.deferReply().catch(Boolean);
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
if (this.options?.sequential) {
|
|
2972
|
+
for (const listener of allListeners) {
|
|
2973
|
+
try {
|
|
2974
|
+
const isAllowed = await this.validateParticipant(interaction, listener.options?.participants);
|
|
2975
|
+
if (!isAllowed) return;
|
|
2976
|
+
await listener.fn(interaction);
|
|
2977
|
+
} catch (err) {
|
|
2978
|
+
this.handleListenerError(err);
|
|
2979
|
+
}
|
|
2980
|
+
}
|
|
2981
|
+
} else {
|
|
2982
|
+
Promise.all(
|
|
2983
|
+
allListeners.map((l) => {
|
|
2984
|
+
const isAllowed = this.validateParticipant(interaction, l.options?.participants);
|
|
2985
|
+
if (!isAllowed) return;
|
|
2986
|
+
return l.fn(interaction).catch(this.handleListenerError);
|
|
2987
|
+
})
|
|
2988
|
+
);
|
|
2989
|
+
}
|
|
2990
|
+
} finally {
|
|
2991
|
+
if (this.options?.userLock) {
|
|
2992
|
+
this.activeUsers.delete(interaction.user.id);
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
});
|
|
2996
|
+
this.collector.on("end", async (collected, reason) => {
|
|
2997
|
+
if (this.options?.sequential) {
|
|
2998
|
+
for (const listener of this.events.end) {
|
|
2999
|
+
try {
|
|
3000
|
+
await listener.fn(collected, reason);
|
|
3001
|
+
} catch (err) {
|
|
3002
|
+
this.handleListenerError(err);
|
|
3003
|
+
}
|
|
3004
|
+
}
|
|
3005
|
+
} else {
|
|
3006
|
+
Promise.all(this.events.end.map((l) => l.fn(collected, reason).catch(this.handleListenerError)));
|
|
3007
|
+
}
|
|
3008
|
+
switch (this.options?.onTimeout) {
|
|
3009
|
+
case 0 /* DisableComponents */:
|
|
3010
|
+
if (!this.message?.editable) break;
|
|
3011
|
+
try {
|
|
3012
|
+
const disabledRows = this.message.components.map((row) => {
|
|
3013
|
+
const updatedRow = row.toJSON();
|
|
3014
|
+
if ("components" in updatedRow) {
|
|
3015
|
+
updatedRow.components = updatedRow.components.map((component) => ({
|
|
3016
|
+
...component,
|
|
3017
|
+
disabled: true
|
|
3018
|
+
}));
|
|
3019
|
+
}
|
|
3020
|
+
return updatedRow;
|
|
3021
|
+
});
|
|
3022
|
+
await this.message.edit({ components: disabledRows });
|
|
3023
|
+
} catch (err) {
|
|
3024
|
+
if (!(err instanceof Error && err.message.includes("Unknown Message"))) {
|
|
3025
|
+
this.handleListenerError(err);
|
|
3026
|
+
}
|
|
3027
|
+
}
|
|
3028
|
+
break;
|
|
3029
|
+
case 1 /* DeleteMessage */:
|
|
3030
|
+
if (!this.message?.deletable) break;
|
|
3031
|
+
await this.message.delete().catch(Boolean);
|
|
3032
|
+
break;
|
|
3033
|
+
case 2 /* DoNothing */:
|
|
3034
|
+
default:
|
|
3035
|
+
break;
|
|
3036
|
+
}
|
|
3037
|
+
});
|
|
3038
|
+
}
|
|
3039
|
+
handleListenerError(err) {
|
|
3040
|
+
console.error("[BetterCollector] Listener Error:", err);
|
|
3041
|
+
}
|
|
3042
|
+
constructor(message, options) {
|
|
3043
|
+
this.config = options?.config || globalVimcordToolsConfig;
|
|
3044
|
+
this.message = message || void 0;
|
|
3045
|
+
this.options = options;
|
|
3046
|
+
this.build();
|
|
3047
|
+
}
|
|
3048
|
+
on(idOrFunc, fnOrOptions, options) {
|
|
3049
|
+
let finalFn;
|
|
3050
|
+
let finalOptions;
|
|
3051
|
+
let customId;
|
|
3052
|
+
if (typeof idOrFunc === "function") {
|
|
3053
|
+
finalFn = idOrFunc;
|
|
3054
|
+
finalOptions = fnOrOptions;
|
|
3055
|
+
} else {
|
|
3056
|
+
if (typeof fnOrOptions !== "function") {
|
|
3057
|
+
throw new Error("[BetterCollector] Second argument must be a function when a customId is provided.");
|
|
3058
|
+
}
|
|
3059
|
+
customId = idOrFunc;
|
|
3060
|
+
finalFn = fnOrOptions;
|
|
3061
|
+
finalOptions = options;
|
|
3062
|
+
}
|
|
3063
|
+
if (customId) {
|
|
3064
|
+
const listeners = this.events.collectId.get(customId) || [];
|
|
3065
|
+
listeners.push({ fn: finalFn, options: finalOptions });
|
|
3066
|
+
this.events.collectId.set(customId, listeners);
|
|
3067
|
+
} else {
|
|
3068
|
+
this.events.collect.push({ fn: finalFn, options: finalOptions });
|
|
3069
|
+
}
|
|
3070
|
+
return this;
|
|
3071
|
+
}
|
|
3072
|
+
onEnd(fn, options) {
|
|
3073
|
+
this.events.end.push({ fn, options });
|
|
3074
|
+
return this;
|
|
3075
|
+
}
|
|
3076
|
+
/** Manually stop the collector and trigger cleanup */
|
|
3077
|
+
stop(reason = "manual") {
|
|
3078
|
+
this.collector?.stop(reason);
|
|
3079
|
+
}
|
|
3080
|
+
};
|
|
3081
|
+
|
|
2941
3082
|
// src/tools/BetterContainer.ts
|
|
2942
3083
|
import {
|
|
2943
3084
|
ButtonBuilder as ButtonBuilder2,
|
|
@@ -2982,7 +3123,9 @@ var BetterContainer = class {
|
|
|
2982
3123
|
return this;
|
|
2983
3124
|
}
|
|
2984
3125
|
addText(text) {
|
|
2985
|
-
this.container.addTextDisplayComponents(
|
|
3126
|
+
this.container.addTextDisplayComponents(
|
|
3127
|
+
(tdb) => tdb.setContent(Array.isArray(text) ? text.filter((t) => t !== null && t !== void 0).join("\n") : text)
|
|
3128
|
+
);
|
|
2986
3129
|
return this;
|
|
2987
3130
|
}
|
|
2988
3131
|
addMedia(...media) {
|
|
@@ -3006,7 +3149,9 @@ var BetterContainer = class {
|
|
|
3006
3149
|
this.container.addSectionComponents((sb) => {
|
|
3007
3150
|
if (data.text) {
|
|
3008
3151
|
sb.addTextDisplayComponents(
|
|
3009
|
-
(tdb) => tdb.setContent(
|
|
3152
|
+
(tdb) => tdb.setContent(
|
|
3153
|
+
Array.isArray(data.text) ? data.text.filter((t) => t !== null && t !== void 0).join("\n") : data.text
|
|
3154
|
+
)
|
|
3010
3155
|
);
|
|
3011
3156
|
}
|
|
3012
3157
|
if (data.thumbnail) sb.setThumbnailAccessory(new ThumbnailBuilder(data.thumbnail));
|
|
@@ -3237,6 +3382,7 @@ var BetterModal = class {
|
|
|
3237
3382
|
// src/tools/Paginator.ts
|
|
3238
3383
|
import {
|
|
3239
3384
|
ActionRowBuilder as ActionRowBuilder4,
|
|
3385
|
+
AttachmentBuilder as AttachmentBuilder2,
|
|
3240
3386
|
ButtonBuilder as ButtonBuilder3,
|
|
3241
3387
|
ButtonStyle as ButtonStyle2,
|
|
3242
3388
|
ComponentType as ComponentType2,
|
|
@@ -3256,6 +3402,7 @@ var PaginationTimeoutType = /* @__PURE__ */ ((PaginationTimeoutType2) => {
|
|
|
3256
3402
|
PaginationTimeoutType2[PaginationTimeoutType2["DisableComponents"] = 0] = "DisableComponents";
|
|
3257
3403
|
PaginationTimeoutType2[PaginationTimeoutType2["ClearComponents"] = 1] = "ClearComponents";
|
|
3258
3404
|
PaginationTimeoutType2[PaginationTimeoutType2["DeleteMessage"] = 2] = "DeleteMessage";
|
|
3405
|
+
PaginationTimeoutType2[PaginationTimeoutType2["DoNothing"] = 3] = "DoNothing";
|
|
3259
3406
|
return PaginationTimeoutType2;
|
|
3260
3407
|
})(PaginationTimeoutType || {});
|
|
3261
3408
|
function wrapPositive(num, max) {
|
|
@@ -3336,7 +3483,8 @@ var Paginator = class {
|
|
|
3336
3483
|
last: [],
|
|
3337
3484
|
collect: [],
|
|
3338
3485
|
react: [],
|
|
3339
|
-
|
|
3486
|
+
preTimeout: [],
|
|
3487
|
+
postTimeout: []
|
|
3340
3488
|
};
|
|
3341
3489
|
if (this.options.pages.length) {
|
|
3342
3490
|
this.addChapter(this.options.pages, { label: "Default" });
|
|
@@ -3403,16 +3551,23 @@ var Paginator = class {
|
|
|
3403
3551
|
embeds: [],
|
|
3404
3552
|
components: [],
|
|
3405
3553
|
flags: [],
|
|
3554
|
+
files: [],
|
|
3555
|
+
// Explicitly empty to clear previous files on page switch
|
|
3406
3556
|
...options,
|
|
3407
3557
|
withResponse: true
|
|
3408
3558
|
};
|
|
3409
3559
|
const page = this.data.page.current;
|
|
3560
|
+
const currentChapter = this.chapters[this.data.page.index.chapter];
|
|
3561
|
+
const chapterFile = currentChapter?.files?.[this.data.page.index.nested];
|
|
3562
|
+
if (chapterFile) sendOptions.files.push(chapterFile);
|
|
3410
3563
|
if (Array.isArray(page)) {
|
|
3411
3564
|
sendOptions.embeds.push(...page);
|
|
3412
3565
|
} else if (typeof page === "string") {
|
|
3413
3566
|
sendOptions.content = page;
|
|
3414
3567
|
} else if (isEmbed(page)) {
|
|
3415
3568
|
sendOptions.embeds.push(page);
|
|
3569
|
+
} else if (page instanceof AttachmentBuilder2) {
|
|
3570
|
+
sendOptions.files.push(page);
|
|
3416
3571
|
} else if (page instanceof ContainerBuilder3 || page instanceof BetterContainer) {
|
|
3417
3572
|
sendOptions.components.push(page);
|
|
3418
3573
|
if (!sendOptions.flags.includes("IsComponentsV2")) {
|
|
@@ -3424,7 +3579,7 @@ var Paginator = class {
|
|
|
3424
3579
|
}
|
|
3425
3580
|
async handlePostTimeout() {
|
|
3426
3581
|
if (!this.data.message) return;
|
|
3427
|
-
this.callEventStack("
|
|
3582
|
+
this.callEventStack("preTimeout", this.data.message);
|
|
3428
3583
|
this.data.collectors.component?.stop();
|
|
3429
3584
|
this.data.collectors.reaction?.stop();
|
|
3430
3585
|
switch (this.options.onTimeout) {
|
|
@@ -3468,7 +3623,10 @@ var Paginator = class {
|
|
|
3468
3623
|
case 2 /* DeleteMessage */:
|
|
3469
3624
|
await this.data.message.delete().catch(Boolean);
|
|
3470
3625
|
break;
|
|
3626
|
+
case 3 /* DoNothing */:
|
|
3627
|
+
break;
|
|
3471
3628
|
}
|
|
3629
|
+
this.callEventStack("postTimeout", this.data.message);
|
|
3472
3630
|
}
|
|
3473
3631
|
async nav_removeFromMessage() {
|
|
3474
3632
|
if (!this.data.message?.editable) return;
|
|
@@ -3515,35 +3673,43 @@ var Paginator = class {
|
|
|
3515
3673
|
await i.reply({ content: "Jump not implemented yet.", flags: "Ephemeral" });
|
|
3516
3674
|
return;
|
|
3517
3675
|
}
|
|
3518
|
-
await i.deferUpdate().catch(Boolean);
|
|
3519
3676
|
switch (i.customId) {
|
|
3520
3677
|
case "ssm_chapterSelect":
|
|
3678
|
+
await i.deferUpdate().catch(Boolean);
|
|
3521
3679
|
const chapterIndex = this.chapters.findIndex(
|
|
3522
3680
|
(c) => c.id === i.values[0]
|
|
3523
3681
|
);
|
|
3524
3682
|
await this.setPage(chapterIndex, 0);
|
|
3683
|
+
await this.refresh();
|
|
3525
3684
|
break;
|
|
3526
3685
|
case "btn_first":
|
|
3686
|
+
await i.deferUpdate().catch(Boolean);
|
|
3527
3687
|
this.callEventStack("first", this.data.page.current, this.data.page.index);
|
|
3528
3688
|
await this.setPage(this.data.page.index.chapter, 0);
|
|
3689
|
+
await this.refresh();
|
|
3529
3690
|
break;
|
|
3530
3691
|
case "btn_back":
|
|
3692
|
+
await i.deferUpdate().catch(Boolean);
|
|
3531
3693
|
this.callEventStack("back", this.data.page.current, this.data.page.index);
|
|
3532
3694
|
await this.setPage(this.data.page.index.chapter, this.data.page.index.nested - 1);
|
|
3695
|
+
await this.refresh();
|
|
3533
3696
|
break;
|
|
3534
3697
|
case "btn_next":
|
|
3698
|
+
await i.deferUpdate().catch(Boolean);
|
|
3535
3699
|
this.callEventStack("next", this.data.page.current, this.data.page.index);
|
|
3536
3700
|
await this.setPage(this.data.page.index.chapter, this.data.page.index.nested + 1);
|
|
3701
|
+
await this.refresh();
|
|
3537
3702
|
break;
|
|
3538
3703
|
case "btn_last":
|
|
3704
|
+
await i.deferUpdate().catch(Boolean);
|
|
3539
3705
|
this.callEventStack("last", this.data.page.current, this.data.page.index);
|
|
3540
3706
|
await this.setPage(
|
|
3541
3707
|
this.data.page.index.chapter,
|
|
3542
3708
|
this.chapters[this.data.page.index.chapter].pages.length - 1
|
|
3543
3709
|
);
|
|
3710
|
+
await this.refresh();
|
|
3544
3711
|
break;
|
|
3545
3712
|
}
|
|
3546
|
-
await this.refresh();
|
|
3547
3713
|
} catch (err) {
|
|
3548
3714
|
console.error("[Paginator] Component navigation error", err);
|
|
3549
3715
|
}
|
|
@@ -3583,7 +3749,7 @@ var Paginator = class {
|
|
|
3583
3749
|
data.value = `ssm_c:${this.chapters.length}`;
|
|
3584
3750
|
}
|
|
3585
3751
|
const normalizedPages = resolvePages(pages);
|
|
3586
|
-
this.chapters.push({ id: data.value, pages: normalizedPages });
|
|
3752
|
+
this.chapters.push({ id: data.value, pages: normalizedPages, files: data.files });
|
|
3587
3753
|
this.data.components.chapterSelect.addOptions(data);
|
|
3588
3754
|
return this;
|
|
3589
3755
|
}
|
|
@@ -3965,7 +4131,7 @@ CLI.addCommand("help", "View information about a command, or the available CLI o
|
|
|
3965
4131
|
}
|
|
3966
4132
|
CLI.logger.table("(help)", helpList);
|
|
3967
4133
|
});
|
|
3968
|
-
CLI.addCommand("register", "Register app commands globally, or per guild", async (args, content) => {
|
|
4134
|
+
CLI.addCommand("register", "Register app commands (slash & context) globally, or per guild", async (args, content) => {
|
|
3969
4135
|
const client = CLI.getClientInstance(content);
|
|
3970
4136
|
if (!client) return;
|
|
3971
4137
|
const mode = args[0]?.toLowerCase() || "";
|
|
@@ -3976,10 +4142,14 @@ CLI.addCommand("register", "Register app commands globally, or per guild", async
|
|
|
3976
4142
|
if (!guildIds.length) guildIds = client.guilds.cache.map((g) => g.id);
|
|
3977
4143
|
switch (mode) {
|
|
3978
4144
|
case "guild":
|
|
4145
|
+
CLI.logger.info("Registering guild commands...");
|
|
3979
4146
|
await client.commands.slash.registerGuild({ guilds: guildIds });
|
|
4147
|
+
await client.commands.context.registerGuild({ guilds: guildIds });
|
|
3980
4148
|
break;
|
|
3981
4149
|
case "global":
|
|
4150
|
+
CLI.logger.info("Registering global commands...");
|
|
3982
4151
|
await client.commands.slash.registerGlobal();
|
|
4152
|
+
await client.commands.context.registerGlobal();
|
|
3983
4153
|
break;
|
|
3984
4154
|
}
|
|
3985
4155
|
});
|
|
@@ -3994,10 +4164,14 @@ CLI.addCommand("unregister", "Unregister app commands globally, or per guild", a
|
|
|
3994
4164
|
if (!guildIds.length) guildIds = client.guilds.cache.map((g) => g.id);
|
|
3995
4165
|
switch (mode) {
|
|
3996
4166
|
case "guild":
|
|
4167
|
+
CLI.logger.info("Unregistering guild commands...");
|
|
3997
4168
|
await client.commands.slash.unregisterGuild({ guilds: guildIds });
|
|
4169
|
+
await client.commands.context.unregisterGuild({ guilds: guildIds });
|
|
3998
4170
|
break;
|
|
3999
4171
|
case "global":
|
|
4172
|
+
CLI.logger.info("Unregistering global commands...");
|
|
4000
4173
|
await client.commands.slash.unregisterGlobal();
|
|
4174
|
+
await client.commands.context.unregisterGlobal();
|
|
4001
4175
|
break;
|
|
4002
4176
|
}
|
|
4003
4177
|
});
|
|
@@ -4012,46 +4186,48 @@ CLI.addCommand("stats", "View statistics about a client instance", (args, conten
|
|
|
4012
4186
|
"Memory Usage:": `${(process.memoryUsage().rss / 1024 / 1024).toFixed(2)} MB`
|
|
4013
4187
|
});
|
|
4014
4188
|
});
|
|
4015
|
-
CLI.addCommand("cmds", "List the loaded commands", (args, content) => {
|
|
4189
|
+
CLI.addCommand("cmds", "List the loaded commands", async (args, content) => {
|
|
4016
4190
|
const client = CLI.getClientInstance(content);
|
|
4017
4191
|
if (!client) return;
|
|
4018
|
-
const mode = args[0] || "slash";
|
|
4192
|
+
const mode = (args[0] || "slash").toLowerCase();
|
|
4019
4193
|
switch (mode) {
|
|
4020
|
-
case "slash":
|
|
4021
|
-
const
|
|
4022
|
-
|
|
4023
|
-
const
|
|
4024
|
-
for (const cmd of
|
|
4025
|
-
|
|
4194
|
+
case "slash": {
|
|
4195
|
+
const commands = Array.from(client.commands.slash.commands.values());
|
|
4196
|
+
commands.sort((a, b) => a.builder.name.localeCompare(b.builder.name));
|
|
4197
|
+
const tableData = {};
|
|
4198
|
+
for (const cmd of commands) {
|
|
4199
|
+
tableData[`/${cmd.builder.name}`] = `~ ${cmd.builder.description || "No description"}`;
|
|
4026
4200
|
}
|
|
4027
|
-
return CLI.logger.table(
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
);
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4201
|
+
return CLI.logger.table(`(cmds) ~ slash (${jsTools2.formatThousands(commands.length)})`, tableData);
|
|
4202
|
+
}
|
|
4203
|
+
case "prefix": {
|
|
4204
|
+
const commands = Array.from(client.commands.prefix.commands.values());
|
|
4205
|
+
commands.sort((a, b) => {
|
|
4206
|
+
const nameA = a.toConfig().name;
|
|
4207
|
+
const nameB = b.toConfig().name;
|
|
4208
|
+
return nameA.localeCompare(nameB);
|
|
4209
|
+
});
|
|
4210
|
+
const tableData = {};
|
|
4211
|
+
const defaultPrefix = client.config.prefixCommands.defaultPrefix;
|
|
4212
|
+
for (const cmd of commands) {
|
|
4213
|
+
const config = cmd.toConfig();
|
|
4214
|
+
const aliasIndicator = config.aliases?.length ? ` [${config.aliases.join(", ")}]` : "";
|
|
4215
|
+
tableData[`${defaultPrefix}${config.name}${aliasIndicator}`] = `~ ${config.description || "No description"}`;
|
|
4037
4216
|
}
|
|
4038
|
-
return CLI.logger.table(
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
);
|
|
4042
|
-
|
|
4043
|
-
const
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
contextCommands_f[`${cmd.builder.name}`] = "";
|
|
4217
|
+
return CLI.logger.table(`(cmds) ~ prefix (${jsTools2.formatThousands(commands.length)})`, tableData);
|
|
4218
|
+
}
|
|
4219
|
+
case "ctx": {
|
|
4220
|
+
const commands = Array.from(client.commands.context.commands.values());
|
|
4221
|
+
commands.sort((a, b) => a.builder.name.localeCompare(b.builder.name));
|
|
4222
|
+
const tableData = {};
|
|
4223
|
+
for (const cmd of commands) {
|
|
4224
|
+
const type = cmd.builder.type === 2 ? "User" : "Msg";
|
|
4225
|
+
tableData[`[${type}] ${cmd.builder.name}`] = "";
|
|
4048
4226
|
}
|
|
4049
|
-
return CLI.logger.table(
|
|
4050
|
-
|
|
4051
|
-
contextCommands_f
|
|
4052
|
-
);
|
|
4227
|
+
return CLI.logger.table(`(cmds) ~ ctx (${jsTools2.formatThousands(commands.length)})`, tableData);
|
|
4228
|
+
}
|
|
4053
4229
|
default:
|
|
4054
|
-
return CLI.logger.error(`'${mode}' is not a valid option.
|
|
4230
|
+
return CLI.logger.error(`'${mode}' is not a valid option. Valid options: [slash|prefix|ctx]`);
|
|
4055
4231
|
}
|
|
4056
4232
|
});
|
|
4057
4233
|
function initCLI() {
|
|
@@ -4077,14 +4253,17 @@ function getClientInstances() {
|
|
|
4077
4253
|
}
|
|
4078
4254
|
export {
|
|
4079
4255
|
BaseCommandBuilder,
|
|
4256
|
+
BetterCollector,
|
|
4080
4257
|
BetterContainer,
|
|
4081
4258
|
BetterEmbed,
|
|
4082
4259
|
BetterModal,
|
|
4083
4260
|
CLI,
|
|
4261
|
+
CollectorTimeoutType,
|
|
4084
4262
|
CommandType,
|
|
4085
4263
|
ContextCommandBuilder,
|
|
4086
4264
|
DynaSend,
|
|
4087
4265
|
EventBuilder,
|
|
4266
|
+
LOGGER_COLORS,
|
|
4088
4267
|
LogLevel,
|
|
4089
4268
|
Logger,
|
|
4090
4269
|
MissingPermissionReason,
|
|
@@ -4113,6 +4292,7 @@ export {
|
|
|
4113
4292
|
clientInstances,
|
|
4114
4293
|
createClient,
|
|
4115
4294
|
createMongoSchema,
|
|
4295
|
+
createMongoSession,
|
|
4116
4296
|
createToolsConfig,
|
|
4117
4297
|
createVimcordAppConfig,
|
|
4118
4298
|
createVimcordContextCommandConfig,
|
|
@@ -4146,6 +4326,7 @@ export {
|
|
|
4146
4326
|
useClient,
|
|
4147
4327
|
useMongoDatabase,
|
|
4148
4328
|
useReadyClient,
|
|
4329
|
+
useReadyMongoDatabase,
|
|
4149
4330
|
validateCommandPermissions
|
|
4150
4331
|
};
|
|
4151
4332
|
//# sourceMappingURL=index.js.map
|