spacecommands 1.0.0
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/LICENSE +21 -0
- package/README.md +519 -0
- package/dist/Command.js +384 -0
- package/dist/CommandHandler.js +339 -0
- package/dist/FeatureHandler.js +89 -0
- package/dist/SlashCommands.js +220 -0
- package/dist/command-checks/channel-specific.js +30 -0
- package/dist/command-checks/guild-only-check.js +24 -0
- package/dist/command-checks/has-entitlement.js +52 -0
- package/dist/command-checks/has-permissions.js +39 -0
- package/dist/command-checks/has-roles.js +69 -0
- package/dist/command-checks/has-valid-arguments.js +54 -0
- package/dist/command-checks/in-cooldown.js +42 -0
- package/dist/command-checks/is-enabled.js +31 -0
- package/dist/command-checks/is-not-test-only.js +8 -0
- package/dist/command-checks/owner-only-check.js +22 -0
- package/dist/commands/channelonly.js +88 -0
- package/dist/commands/command.js +87 -0
- package/dist/commands/help/!ReactionListener.js +217 -0
- package/dist/commands/help/!get-first-embed.js +57 -0
- package/dist/commands/help/help.js +97 -0
- package/dist/commands/language.js +52 -0
- package/dist/commands/prefix.js +42 -0
- package/dist/commands/requiredrole.js +61 -0
- package/dist/commands/slash.js +102 -0
- package/dist/enums/CommandErrors.js +12 -0
- package/dist/enums/Events.js +9 -0
- package/dist/features/message-upsert.js +15 -0
- package/dist/get-all-files.js +25 -0
- package/dist/handlers/AutoModHandler.js +316 -0
- package/dist/handlers/ComponentHandler.js +110 -0
- package/dist/handlers/ContextMenuHandler.js +113 -0
- package/dist/handlers/EntitlementHandler.js +193 -0
- package/dist/handlers/ModalHandler.js +71 -0
- package/dist/handlers/PollHandler.js +230 -0
- package/dist/index.js +339 -0
- package/dist/message-handler.js +118 -0
- package/dist/models/channel-commands.js +49 -0
- package/dist/models/cooldown.js +51 -0
- package/dist/models/disabled-commands.js +45 -0
- package/dist/models/languages.js +46 -0
- package/dist/models/prefixes.js +46 -0
- package/dist/models/required-roles.js +49 -0
- package/dist/mongo.js +25 -0
- package/dist/permissions.js +39 -0
- package/dist/utils/ComponentBuilder.js +144 -0
- package/dist/utils/InteractionCollector.js +80 -0
- package/messages.json +391 -0
- package/package.json +72 -0
- package/typings.d.ts +276 -0
package/dist/Command.js
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
const cooldown_1 = __importDefault(require("./models/cooldown"));
|
|
6
|
+
class Command {
|
|
7
|
+
instance;
|
|
8
|
+
client;
|
|
9
|
+
_names = [];
|
|
10
|
+
_category = '';
|
|
11
|
+
_minArgs = 0;
|
|
12
|
+
_maxArgs = -1;
|
|
13
|
+
_syntaxError;
|
|
14
|
+
_expectedArgs;
|
|
15
|
+
_description;
|
|
16
|
+
_requiredPermissions;
|
|
17
|
+
_requiredRoles = new Map(); // <GuildID, RoleIDs[]>
|
|
18
|
+
_callback = () => { };
|
|
19
|
+
_error = null;
|
|
20
|
+
_disabled = [];
|
|
21
|
+
_cooldownDuration = 0;
|
|
22
|
+
_cooldownChar = '';
|
|
23
|
+
_cooldown;
|
|
24
|
+
_userCooldowns = new Map(); // <GuildID-UserID, Seconds> OR <dm-UserID, Seconds>
|
|
25
|
+
_globalCooldown;
|
|
26
|
+
_guildCooldowns = new Map(); // <GuildID, Seconds>
|
|
27
|
+
_databaseCooldown = false;
|
|
28
|
+
_ownerOnly = false;
|
|
29
|
+
_hidden = false;
|
|
30
|
+
_guildOnly = false;
|
|
31
|
+
_testOnly = false;
|
|
32
|
+
_slash = false;
|
|
33
|
+
_requireRoles = false;
|
|
34
|
+
_requiredChannels = new Map(); // <GuildID-Command, Channel IDs>
|
|
35
|
+
_requiredEntitlements = [];
|
|
36
|
+
_premiumOnly = false;
|
|
37
|
+
constructor(instance, client, names, callback, error, { category, minArgs, maxArgs, syntaxError, expectedArgs, description, requiredPermissions, permissions, cooldown, globalCooldown, ownerOnly = false, hidden = false, guildOnly = false, testOnly = false, slash = false, requireRoles = false, requiredEntitlements, premiumOnly = false, }) {
|
|
38
|
+
this.instance = instance;
|
|
39
|
+
this.client = client;
|
|
40
|
+
this._names = typeof names === 'string' ? [names] : names;
|
|
41
|
+
this._category = category;
|
|
42
|
+
this._minArgs = minArgs || 0;
|
|
43
|
+
this._maxArgs = maxArgs === undefined ? -1 : maxArgs;
|
|
44
|
+
this._syntaxError = syntaxError;
|
|
45
|
+
this._expectedArgs = expectedArgs;
|
|
46
|
+
this._description = description;
|
|
47
|
+
this._requiredPermissions = requiredPermissions || permissions;
|
|
48
|
+
this._cooldown = cooldown || '';
|
|
49
|
+
this._globalCooldown = globalCooldown || '';
|
|
50
|
+
this._ownerOnly = ownerOnly;
|
|
51
|
+
this._hidden = hidden;
|
|
52
|
+
this._guildOnly = guildOnly;
|
|
53
|
+
this._testOnly = testOnly;
|
|
54
|
+
this._callback = callback;
|
|
55
|
+
this._error = error;
|
|
56
|
+
this._slash = slash;
|
|
57
|
+
this._requireRoles = requireRoles;
|
|
58
|
+
this._requiredEntitlements =
|
|
59
|
+
typeof requiredEntitlements === 'string'
|
|
60
|
+
? [requiredEntitlements]
|
|
61
|
+
: requiredEntitlements || [];
|
|
62
|
+
this._premiumOnly = premiumOnly;
|
|
63
|
+
if (this.cooldown && this.globalCooldown) {
|
|
64
|
+
throw new Error(`Command "${names[0]}" has both a global and per-user cooldown. Commands can only have up to one of these properties.`);
|
|
65
|
+
}
|
|
66
|
+
if (requiredPermissions && permissions) {
|
|
67
|
+
throw new Error(`Command "${names[0]}" has both requiredPermissions and permissions fields. These are interchangeable but only one should be provided.`);
|
|
68
|
+
}
|
|
69
|
+
if (this.cooldown) {
|
|
70
|
+
this.verifyCooldown(this._cooldown, 'cooldown');
|
|
71
|
+
}
|
|
72
|
+
if (this.globalCooldown) {
|
|
73
|
+
this.verifyCooldown(this._globalCooldown, 'global cooldown');
|
|
74
|
+
}
|
|
75
|
+
if (this._minArgs < 0) {
|
|
76
|
+
throw new Error(`Command "${names[0]}" has a minimum argument count less than 0!`);
|
|
77
|
+
}
|
|
78
|
+
if (this._maxArgs < -1) {
|
|
79
|
+
throw new Error(`Command "${names[0]}" has a maximum argument count less than -1!`);
|
|
80
|
+
}
|
|
81
|
+
if (this._maxArgs !== -1 && this._maxArgs < this._minArgs) {
|
|
82
|
+
throw new Error(`Command "${names[0]}" has a maximum argument count less than it's minimum argument count!`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async execute(message, args) {
|
|
86
|
+
const reply = await this._callback({
|
|
87
|
+
message,
|
|
88
|
+
channel: message.channel,
|
|
89
|
+
args,
|
|
90
|
+
text: args.join(' '),
|
|
91
|
+
client: this.client,
|
|
92
|
+
prefix: this.instance.getPrefix(message.guild),
|
|
93
|
+
instance: this.instance,
|
|
94
|
+
user: message.author,
|
|
95
|
+
member: message.member,
|
|
96
|
+
guild: message.guild,
|
|
97
|
+
cancelCoolDown: () => {
|
|
98
|
+
this.decrementCooldowns(message.guild?.id, message.author.id);
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
if (!reply) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (typeof reply === 'string') {
|
|
105
|
+
message.reply({
|
|
106
|
+
content: reply,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
else if (typeof reply === 'object') {
|
|
110
|
+
if (reply.custom) {
|
|
111
|
+
message.reply(reply);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
let embeds = [];
|
|
115
|
+
if (Array.isArray(reply)) {
|
|
116
|
+
embeds = reply;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
embeds.push(reply);
|
|
120
|
+
}
|
|
121
|
+
message.reply({
|
|
122
|
+
embeds,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
get names() {
|
|
128
|
+
return this._names;
|
|
129
|
+
}
|
|
130
|
+
get category() {
|
|
131
|
+
return this._category;
|
|
132
|
+
}
|
|
133
|
+
get description() {
|
|
134
|
+
return this._description;
|
|
135
|
+
}
|
|
136
|
+
get minArgs() {
|
|
137
|
+
return this._minArgs;
|
|
138
|
+
}
|
|
139
|
+
get maxArgs() {
|
|
140
|
+
return this._maxArgs;
|
|
141
|
+
}
|
|
142
|
+
get syntaxError() {
|
|
143
|
+
return this._syntaxError || {};
|
|
144
|
+
}
|
|
145
|
+
get expectedArgs() {
|
|
146
|
+
return this._expectedArgs;
|
|
147
|
+
}
|
|
148
|
+
get requiredPermissions() {
|
|
149
|
+
return this._requiredPermissions;
|
|
150
|
+
}
|
|
151
|
+
get cooldownDuration() {
|
|
152
|
+
return this._cooldownDuration;
|
|
153
|
+
}
|
|
154
|
+
get cooldownChar() {
|
|
155
|
+
return this._cooldownChar;
|
|
156
|
+
}
|
|
157
|
+
get cooldown() {
|
|
158
|
+
return this._cooldown;
|
|
159
|
+
}
|
|
160
|
+
get globalCooldown() {
|
|
161
|
+
return this._globalCooldown;
|
|
162
|
+
}
|
|
163
|
+
get testOnly() {
|
|
164
|
+
return this._testOnly;
|
|
165
|
+
}
|
|
166
|
+
verifyCooldown(cooldown, type) {
|
|
167
|
+
if (typeof cooldown !== 'string') {
|
|
168
|
+
throw new Error(`Invalid ${type} format! Must be a string, examples: "10s" "5m" etc.`);
|
|
169
|
+
}
|
|
170
|
+
const results = cooldown.match(/[a-z]+|[^a-z]+/gi) || [];
|
|
171
|
+
if (results.length !== 2) {
|
|
172
|
+
throw new Error(`Invalid ${type} format! Please provide "<Duration><Type>", examples: "10s" "5m" etc.`);
|
|
173
|
+
}
|
|
174
|
+
this._cooldownDuration = +results[0];
|
|
175
|
+
if (isNaN(this._cooldownDuration)) {
|
|
176
|
+
throw new Error(`Invalid ${type} format! Number is invalid.`);
|
|
177
|
+
}
|
|
178
|
+
this._cooldownChar = results[1];
|
|
179
|
+
if (this._cooldownChar !== 's' &&
|
|
180
|
+
this._cooldownChar !== 'm' &&
|
|
181
|
+
this._cooldownChar !== 'h' &&
|
|
182
|
+
this._cooldownChar !== 'd') {
|
|
183
|
+
throw new Error(`Invalid ${type} format! Unknown type. Please provide 's', 'm', 'h', or 'd' for seconds, minutes, hours, or days respectively.`);
|
|
184
|
+
}
|
|
185
|
+
if (type === 'global cooldown' &&
|
|
186
|
+
this._cooldownChar === 's' &&
|
|
187
|
+
this._cooldownDuration < 60) {
|
|
188
|
+
throw new Error(`Invalid ${type} format! The minimum duration for a global cooldown is 1m.`);
|
|
189
|
+
}
|
|
190
|
+
if (this._cooldownDuration < 1) {
|
|
191
|
+
throw new Error(`Invalid ${type} format! Durations must be at least 1.`);
|
|
192
|
+
}
|
|
193
|
+
if ((this._cooldownChar === 's' || this._cooldownChar === 'm') &&
|
|
194
|
+
this._cooldownDuration > 60) {
|
|
195
|
+
throw new Error(`Invalid ${type} format! Second or minute durations cannot exceed 60.`);
|
|
196
|
+
}
|
|
197
|
+
if (this._cooldownChar === 'h' && this._cooldownDuration > 24) {
|
|
198
|
+
throw new Error(`Invalid ${type} format! Hour durations cannot exceed 24.`);
|
|
199
|
+
}
|
|
200
|
+
if (this._cooldownChar === 'd' && this._cooldownDuration > 365) {
|
|
201
|
+
throw new Error(`Invalid ${type} format! Day durations cannot exceed 365.`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
get hidden() {
|
|
205
|
+
return this._hidden;
|
|
206
|
+
}
|
|
207
|
+
get guildOnly() {
|
|
208
|
+
return this._guildOnly;
|
|
209
|
+
}
|
|
210
|
+
get ownerOnly() {
|
|
211
|
+
return this._ownerOnly;
|
|
212
|
+
}
|
|
213
|
+
verifyDatabaseCooldowns() {
|
|
214
|
+
if (this._cooldownChar === 'd' ||
|
|
215
|
+
this._cooldownChar === 'h' ||
|
|
216
|
+
(this._cooldownChar === 'm' && this._cooldownDuration >= 5)) {
|
|
217
|
+
this._databaseCooldown = true;
|
|
218
|
+
if (!this.instance.isDBConnected()) {
|
|
219
|
+
console.warn(`SpaceCommands > A database connection is STRONGLY RECOMMENDED for cooldowns of 5 minutes or more.`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Decrements per-user and global cooldowns
|
|
225
|
+
* Deletes expired cooldowns
|
|
226
|
+
*/
|
|
227
|
+
decrementCooldowns(guildId, userId) {
|
|
228
|
+
for (const map of [this._userCooldowns, this._guildCooldowns]) {
|
|
229
|
+
if (typeof map !== 'string') {
|
|
230
|
+
map.forEach((value, key) => {
|
|
231
|
+
if (key === `${guildId}-${userId}`) {
|
|
232
|
+
value = 0;
|
|
233
|
+
}
|
|
234
|
+
if (--value <= 0) {
|
|
235
|
+
map.delete(key);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
map.set(key, value);
|
|
239
|
+
}
|
|
240
|
+
if (this._databaseCooldown && this.instance.isDBConnected()) {
|
|
241
|
+
this.updateDatabaseCooldowns(`${this.names[0]}-${key}`, value);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
async updateDatabaseCooldowns(_id, cooldown) {
|
|
248
|
+
// Only update every 20s
|
|
249
|
+
if (cooldown % 20 === 0 && this.instance.isDBConnected()) {
|
|
250
|
+
const type = this.globalCooldown ? 'global' : 'per-user';
|
|
251
|
+
if (cooldown <= 0) {
|
|
252
|
+
await cooldown_1.default.deleteOne({ _id, name: this.names[0], type });
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
await cooldown_1.default.findOneAndUpdate({
|
|
256
|
+
_id,
|
|
257
|
+
name: this.names[0],
|
|
258
|
+
type,
|
|
259
|
+
}, {
|
|
260
|
+
_id,
|
|
261
|
+
name: this.names[0],
|
|
262
|
+
type,
|
|
263
|
+
cooldown,
|
|
264
|
+
}, { upsert: true });
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
setCooldown(guildId, userId, customCooldown) {
|
|
269
|
+
const target = this.globalCooldown || this.cooldown;
|
|
270
|
+
if (target) {
|
|
271
|
+
let seconds = customCooldown || this._cooldownDuration;
|
|
272
|
+
const durationType = customCooldown ? 's' : this._cooldownChar;
|
|
273
|
+
switch (durationType) {
|
|
274
|
+
case 'm':
|
|
275
|
+
seconds *= 60;
|
|
276
|
+
break;
|
|
277
|
+
case 'h':
|
|
278
|
+
seconds *= 60 * 60;
|
|
279
|
+
break;
|
|
280
|
+
case 'd':
|
|
281
|
+
seconds *= 60 * 60 * 24;
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
// Increment to ensure we save it to the database when it is divisible by 20
|
|
285
|
+
++seconds;
|
|
286
|
+
if (this.globalCooldown) {
|
|
287
|
+
this._guildCooldowns.set(guildId, seconds);
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
this._userCooldowns.set(`${guildId}-${userId}`, seconds);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
getCooldownSeconds(guildId, userId) {
|
|
295
|
+
let seconds = this.globalCooldown
|
|
296
|
+
? this._guildCooldowns.get(guildId)
|
|
297
|
+
: this._userCooldowns.get(`${guildId}-${userId}`);
|
|
298
|
+
if (!seconds) {
|
|
299
|
+
return '';
|
|
300
|
+
}
|
|
301
|
+
const days = Math.floor(seconds / (3600 * 24));
|
|
302
|
+
const hours = Math.floor((seconds % (3600 * 24)) / 3600);
|
|
303
|
+
const minutes = Math.floor((seconds % 3600) / 60);
|
|
304
|
+
seconds = Math.floor(seconds % 60);
|
|
305
|
+
let result = '';
|
|
306
|
+
if (days) {
|
|
307
|
+
result += `${days}d `;
|
|
308
|
+
}
|
|
309
|
+
if (hours) {
|
|
310
|
+
result += `${hours}h `;
|
|
311
|
+
}
|
|
312
|
+
if (minutes) {
|
|
313
|
+
result += `${minutes}m `;
|
|
314
|
+
}
|
|
315
|
+
if (seconds) {
|
|
316
|
+
result += `${seconds}s `;
|
|
317
|
+
}
|
|
318
|
+
return result.substring(0, result.length - 1);
|
|
319
|
+
}
|
|
320
|
+
addRequiredRole(guildId, roleId) {
|
|
321
|
+
const array = this._requiredRoles?.get(guildId) || [];
|
|
322
|
+
if (!array.includes(roleId)) {
|
|
323
|
+
array.push(roleId);
|
|
324
|
+
this._requiredRoles?.set(guildId, array);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
removeRequiredRole(guildId, roleId) {
|
|
328
|
+
if (roleId === 'none') {
|
|
329
|
+
this._requiredRoles?.delete(guildId);
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
const array = this._requiredRoles?.get(guildId) || [];
|
|
333
|
+
const index = array ? array.indexOf(roleId) : -1;
|
|
334
|
+
if (array && index >= 0) {
|
|
335
|
+
array.splice(index, 1);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
getRequiredRoles(guildId) {
|
|
339
|
+
const map = this._requiredRoles || new Map();
|
|
340
|
+
return map.get(guildId) || [];
|
|
341
|
+
}
|
|
342
|
+
get callback() {
|
|
343
|
+
return this._callback;
|
|
344
|
+
}
|
|
345
|
+
disable(guildId) {
|
|
346
|
+
if (!this._disabled.includes(guildId)) {
|
|
347
|
+
this._disabled.push(guildId);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
enable(guildId) {
|
|
351
|
+
const index = this._disabled.indexOf(guildId);
|
|
352
|
+
if (index >= 0) {
|
|
353
|
+
this._disabled.splice(index, 1);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
isDisabled(guildId) {
|
|
357
|
+
return this._disabled.includes(guildId);
|
|
358
|
+
}
|
|
359
|
+
get error() {
|
|
360
|
+
return this._error;
|
|
361
|
+
}
|
|
362
|
+
get slash() {
|
|
363
|
+
return this._slash;
|
|
364
|
+
}
|
|
365
|
+
get doesRequireRoles() {
|
|
366
|
+
return this._requireRoles;
|
|
367
|
+
}
|
|
368
|
+
get requiredChannels() {
|
|
369
|
+
return this._requiredChannels;
|
|
370
|
+
}
|
|
371
|
+
setRequiredChannels(guild, command, channels) {
|
|
372
|
+
if (!guild) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
this.requiredChannels.set(`${guild.id}-${command}`, channels);
|
|
376
|
+
}
|
|
377
|
+
get requiredEntitlements() {
|
|
378
|
+
return this._requiredEntitlements;
|
|
379
|
+
}
|
|
380
|
+
get premiumOnly() {
|
|
381
|
+
return this._premiumOnly;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
module.exports = Command;
|