djs-selfbot-v13 3.1.7 → 3.1.8
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 +1 -1
- package/README.md +18 -45
- package/package.json +8 -37
- package/src/client/BaseClient.js +2 -3
- package/src/client/Client.js +187 -539
- package/src/client/actions/Action.js +18 -13
- package/src/client/actions/ActionsManager.js +7 -1
- package/src/client/actions/AutoModerationActionExecution.js +1 -0
- package/src/client/actions/AutoModerationRuleCreate.js +1 -0
- package/src/client/actions/AutoModerationRuleDelete.js +1 -0
- package/src/client/actions/AutoModerationRuleUpdate.js +1 -0
- package/src/client/actions/MessageCreate.js +0 -4
- package/src/client/actions/PresenceUpdate.js +17 -16
- package/src/client/websocket/WebSocketManager.js +11 -31
- package/src/client/websocket/WebSocketShard.js +39 -38
- package/src/client/websocket/handlers/CALL_CREATE.js +3 -3
- package/src/client/websocket/handlers/CALL_DELETE.js +2 -2
- package/src/client/websocket/handlers/CALL_UPDATE.js +2 -2
- package/src/client/websocket/handlers/CHANNEL_RECIPIENT_ADD.js +16 -13
- package/src/client/websocket/handlers/CHANNEL_RECIPIENT_REMOVE.js +11 -11
- package/src/client/websocket/handlers/GUILD_CREATE.js +7 -0
- package/src/client/websocket/handlers/INTERACTION_MODAL_CREATE.js +1 -0
- package/src/client/websocket/handlers/READY.js +47 -137
- package/src/client/websocket/handlers/RELATIONSHIP_ADD.js +7 -5
- package/src/client/websocket/handlers/RELATIONSHIP_REMOVE.js +6 -4
- package/src/client/websocket/handlers/RELATIONSHIP_UPDATE.js +32 -9
- package/src/client/websocket/handlers/USER_GUILD_SETTINGS_UPDATE.js +2 -8
- package/src/client/websocket/handlers/USER_NOTE_UPDATE.js +1 -1
- package/src/client/websocket/handlers/USER_REQUIRED_ACTION_UPDATE.js +78 -0
- package/src/client/websocket/handlers/USER_SETTINGS_UPDATE.js +1 -5
- package/src/client/websocket/handlers/VOICE_CHANNEL_STATUS_UPDATE.js +12 -0
- package/src/client/websocket/handlers/index.js +15 -20
- package/src/errors/Messages.js +24 -69
- package/src/index.js +12 -43
- package/src/managers/ApplicationCommandManager.js +9 -12
- package/src/managers/ApplicationCommandPermissionsManager.js +3 -11
- package/src/managers/ChannelManager.js +3 -4
- package/src/managers/ClientUserSettingManager.js +161 -279
- package/src/managers/GuildBanManager.js +1 -1
- package/src/managers/GuildChannelManager.js +2 -0
- package/src/managers/GuildForumThreadManager.js +22 -28
- package/src/managers/GuildMemberManager.js +40 -216
- package/src/managers/GuildSettingManager.js +22 -15
- package/src/managers/MessageManager.js +42 -44
- package/src/managers/PermissionOverwriteManager.js +1 -1
- package/src/managers/ReactionUserManager.js +5 -5
- package/src/managers/RelationshipManager.js +81 -74
- package/src/managers/ThreadManager.js +12 -45
- package/src/managers/ThreadMemberManager.js +1 -1
- package/src/managers/UserManager.js +6 -10
- package/src/managers/UserNoteManager.js +53 -0
- package/src/rest/APIRequest.js +42 -20
- package/src/rest/DiscordAPIError.js +17 -16
- package/src/rest/RESTManager.js +1 -21
- package/src/rest/RequestHandler.js +35 -21
- package/src/structures/ApplicationCommand.js +19 -456
- package/src/structures/ApplicationRoleConnectionMetadata.js +3 -0
- package/src/structures/AutoModerationRule.js +5 -5
- package/src/structures/AutocompleteInteraction.js +1 -0
- package/src/structures/BaseGuildTextChannel.js +10 -12
- package/src/structures/BaseGuildVoiceChannel.js +16 -18
- package/src/structures/{Call.js → CallState.js} +17 -12
- package/src/structures/CategoryChannel.js +2 -0
- package/src/structures/Channel.js +2 -3
- package/src/structures/ClientPresence.js +12 -8
- package/src/structures/ClientUser.js +117 -336
- package/src/structures/ContextMenuInteraction.js +1 -1
- package/src/structures/DMChannel.js +29 -92
- package/src/structures/ForumChannel.js +0 -10
- package/src/structures/GroupDMChannel.js +387 -0
- package/src/structures/Guild.js +135 -271
- package/src/structures/GuildAuditLogs.js +0 -5
- package/src/structures/GuildChannel.js +16 -2
- package/src/structures/GuildMember.js +27 -145
- package/src/structures/Interaction.js +1 -62
- package/src/structures/Invite.js +35 -52
- package/src/structures/Message.js +228 -202
- package/src/structures/MessageAttachment.js +11 -0
- package/src/structures/MessageButton.js +1 -67
- package/src/structures/MessageEmbed.js +1 -1
- package/src/structures/MessageMentions.js +3 -2
- package/src/structures/MessagePayload.js +4 -46
- package/src/structures/MessageReaction.js +1 -1
- package/src/structures/MessageSelectMenu.js +1 -252
- package/src/structures/Modal.js +75 -180
- package/src/structures/Presence.js +2 -2
- package/src/structures/RichPresence.js +14 -34
- package/src/structures/Role.js +18 -2
- package/src/structures/SelectMenuInteraction.js +2 -151
- package/src/structures/Team.js +0 -49
- package/src/structures/TextInputComponent.js +0 -70
- package/src/structures/ThreadChannel.js +0 -19
- package/src/structures/User.js +117 -345
- package/src/structures/UserContextMenuInteraction.js +2 -2
- package/src/structures/VoiceState.js +74 -39
- package/src/structures/WebEmbed.js +38 -52
- package/src/structures/Webhook.js +17 -11
- package/src/structures/interfaces/Application.js +146 -23
- package/src/structures/interfaces/TextBasedChannel.js +411 -256
- package/src/util/ApplicationFlags.js +1 -1
- package/src/util/AttachmentFlags.js +38 -0
- package/src/util/Constants.js +106 -284
- package/src/util/Formatters.js +16 -2
- package/src/util/InviteFlags.js +29 -0
- package/src/util/LimitedCollection.js +1 -1
- package/src/util/Options.js +48 -68
- package/src/util/Permissions.js +5 -0
- package/src/util/PurchasedFlags.js +2 -0
- package/src/util/RemoteAuth.js +221 -356
- package/src/util/RoleFlags.js +37 -0
- package/src/util/Sweepers.js +1 -1
- package/src/util/Util.js +76 -36
- package/typings/enums.d.ts +18 -73
- package/typings/index.d.ts +873 -1225
- package/typings/rawDataTypes.d.ts +68 -9
- package/src/client/actions/InteractionCreate.js +0 -115
- package/src/client/websocket/handlers/APPLICATION_COMMAND_AUTOCOMPLETE_RESPONSE.js +0 -23
- package/src/client/websocket/handlers/GUILD_APPLICATION_COMMANDS_UPDATE.js +0 -11
- package/src/client/websocket/handlers/GUILD_MEMBER_LIST_UPDATE.js +0 -55
- package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUNDS_UPDATE.js +0 -0
- package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_CREATE.js +0 -0
- package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_DELETE.js +0 -0
- package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_UPDATE.js +0 -0
- package/src/client/websocket/handlers/INTERACTION_CREATE.js +0 -16
- package/src/client/websocket/handlers/INTERACTION_FAILURE.js +0 -18
- package/src/client/websocket/handlers/INTERACTION_SUCCESS.js +0 -30
- package/src/client/websocket/handlers/MESSAGE_ACK.js +0 -16
- package/src/client/websocket/handlers/SOUNDBOARD_SOUNDS.js +0 -0
- package/src/client/websocket/handlers/VOICE_CHANNEL_EFFECT_SEND.js +0 -0
- package/src/managers/DeveloperPortalManager.js +0 -104
- package/src/managers/GuildApplicationCommandManager.js +0 -28
- package/src/managers/GuildFolderManager.js +0 -24
- package/src/managers/SessionManager.js +0 -57
- package/src/rest/CaptchaSolver.js +0 -132
- package/src/structures/ClientApplication.js +0 -204
- package/src/structures/DeveloperPortalApplication.js +0 -520
- package/src/structures/GuildFolder.js +0 -75
- package/src/structures/InteractionResponse.js +0 -114
- package/src/structures/PartialGroupDMChannel.js +0 -433
- package/src/structures/Session.js +0 -81
- package/src/util/Voice.js +0 -1456
- package/src/util/arRPC/index.js +0 -229
- package/src/util/arRPC/process/detectable.json +0 -1
- package/src/util/arRPC/process/index.js +0 -102
- package/src/util/arRPC/process/native/index.js +0 -5
- package/src/util/arRPC/process/native/linux.js +0 -37
- package/src/util/arRPC/process/native/win32.js +0 -25
- package/src/util/arRPC/transports/ipc.js +0 -281
- package/src/util/arRPC/transports/websocket.js +0 -128
package/src/rest/RESTManager.js
CHANGED
|
@@ -4,7 +4,6 @@ const { setInterval } = require('node:timers');
|
|
|
4
4
|
const { Collection } = require('@discordjs/collection');
|
|
5
5
|
const APIRequest = require('./APIRequest');
|
|
6
6
|
const routeBuilder = require('./APIRouter');
|
|
7
|
-
const CaptchaSolver = require('./CaptchaSolver');
|
|
8
7
|
const RequestHandler = require('./RequestHandler');
|
|
9
8
|
const { Error } = require('../errors');
|
|
10
9
|
const { Endpoints } = require('../util/Constants');
|
|
@@ -23,17 +22,6 @@ class RESTManager {
|
|
|
23
22
|
this.handlers.sweep(handler => handler._inactive);
|
|
24
23
|
}, client.options.restSweepInterval * 1_000).unref();
|
|
25
24
|
}
|
|
26
|
-
this.captchaService = null;
|
|
27
|
-
this.setup();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
setup() {
|
|
31
|
-
this.captchaService = new CaptchaSolver(
|
|
32
|
-
this.client.options.captchaService,
|
|
33
|
-
this.client.options.captchaKey,
|
|
34
|
-
this.client.options.captchaSolver,
|
|
35
|
-
this.client.options.captchaWithProxy ? this.client.options.proxy : '',
|
|
36
|
-
);
|
|
37
25
|
}
|
|
38
26
|
|
|
39
27
|
get api() {
|
|
@@ -41,16 +29,8 @@ class RESTManager {
|
|
|
41
29
|
}
|
|
42
30
|
|
|
43
31
|
getAuth() {
|
|
44
|
-
if ((this.client.token && this.client.user && this.client.user.bot) || this.client.accessToken) {
|
|
45
|
-
return `Bot ${this.client.token}`;
|
|
46
|
-
} else if (this.client.token) {
|
|
47
|
-
return this.client.token;
|
|
48
|
-
}
|
|
49
|
-
/*
|
|
50
|
-
// v13.7
|
|
51
32
|
const token = this.client.token ?? this.client.accessToken;
|
|
52
|
-
if (token) return
|
|
53
|
-
*/
|
|
33
|
+
if (token) return token?.replace(/Bot /g, '');
|
|
54
34
|
throw new Error('TOKEN_MISSING');
|
|
55
35
|
}
|
|
56
36
|
|
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
const { setTimeout } = require('node:timers');
|
|
4
4
|
const { setTimeout: sleep } = require('node:timers/promises');
|
|
5
|
-
const { inspect } = require('util');
|
|
6
5
|
const { AsyncQueue } = require('@sapphire/async-queue');
|
|
7
6
|
const DiscordAPIError = require('./DiscordAPIError');
|
|
8
7
|
const HTTPError = require('./HTTPError');
|
|
9
8
|
const RateLimitError = require('./RateLimitError');
|
|
10
9
|
const {
|
|
11
|
-
Events: { DEBUG, RATE_LIMIT, INVALID_REQUEST_WARNING, API_RESPONSE, API_REQUEST
|
|
10
|
+
Events: { DEBUG, RATE_LIMIT, INVALID_REQUEST_WARNING, API_RESPONSE, API_REQUEST },
|
|
12
11
|
} = require('../util/Constants');
|
|
13
12
|
|
|
14
13
|
const captchaMessage = [
|
|
@@ -19,11 +18,13 @@ const captchaMessage = [
|
|
|
19
18
|
'invalid-response',
|
|
20
19
|
'You need to update your app',
|
|
21
20
|
'response-already-used-error',
|
|
21
|
+
'rqkey-mismatch',
|
|
22
|
+
'sitekey-secret-mismatch',
|
|
22
23
|
];
|
|
23
24
|
|
|
24
25
|
function parseResponse(res) {
|
|
25
26
|
if (res.headers.get('content-type')?.startsWith('application/json')) return res.json();
|
|
26
|
-
return res.arrayBuffer();
|
|
27
|
+
return res.arrayBuffer();
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
function getAPIOffset(serverDate) {
|
|
@@ -354,50 +355,63 @@ class RequestHandler {
|
|
|
354
355
|
let data;
|
|
355
356
|
try {
|
|
356
357
|
data = await parseResponse(res);
|
|
357
|
-
|
|
358
|
-
/**
|
|
359
|
-
* Emitted when a request is blocked by a captcha
|
|
360
|
-
* @event Client#captchaRequired
|
|
361
|
-
* @param {Request} request The request that was blocked
|
|
362
|
-
* @param {Captcha} data The data returned by Discord
|
|
363
|
-
*/
|
|
364
|
-
this.manager.client.emit(CAPTCHA_REQUIRED, request, data);
|
|
365
|
-
}
|
|
358
|
+
// Captcha
|
|
366
359
|
if (
|
|
367
360
|
data?.captcha_service &&
|
|
368
|
-
this.manager.client.options.
|
|
361
|
+
typeof this.manager.client.options.captchaSolver == 'function' &&
|
|
369
362
|
request.retries < this.manager.client.options.captchaRetryLimit &&
|
|
370
363
|
captchaMessage.some(s => data.captcha_key[0].includes(s))
|
|
371
364
|
) {
|
|
372
365
|
// Retry the request after a captcha is solved
|
|
373
366
|
this.manager.client.emit(
|
|
374
367
|
DEBUG,
|
|
375
|
-
`Hit a captcha while executing a request.
|
|
368
|
+
`Hit a captcha while executing a request (${data.captcha_key.join(', ')})
|
|
376
369
|
Method : ${request.method}
|
|
377
370
|
Path : ${request.path}
|
|
378
371
|
Route : ${request.route}
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
const captcha = await this.manager.captchaService.solve(
|
|
382
|
-
data,
|
|
383
|
-
this.manager.client.options.http.headers['User-Agent'],
|
|
372
|
+
Sitekey : ${data.captcha_sitekey}
|
|
373
|
+
rqToken : ${data.captcha_rqtoken}`,
|
|
384
374
|
);
|
|
385
|
-
|
|
375
|
+
const captcha = await this.manager.client.options.captchaSolver(data, request.fullUserAgent);
|
|
386
376
|
this.manager.client.emit(
|
|
387
377
|
DEBUG,
|
|
388
378
|
`Captcha details:
|
|
389
379
|
Method : ${request.method}
|
|
390
380
|
Path : ${request.path}
|
|
391
381
|
Route : ${request.route}
|
|
392
|
-
Key : ${captcha ? `${captcha.slice(0,
|
|
382
|
+
Key : ${captcha ? `${captcha.slice(0, 120)}...` : '[Captcha not solved]'}
|
|
393
383
|
rqToken : ${data.captcha_rqtoken}`,
|
|
394
384
|
);
|
|
395
385
|
request.retries++;
|
|
396
386
|
return this.execute(request, captcha, data.captcha_rqtoken);
|
|
397
387
|
}
|
|
388
|
+
// Two factor
|
|
389
|
+
if (data?.code && data.code == 60003 && request.options.mfaCode && request.retries < 1) {
|
|
390
|
+
this.manager.client.emit(
|
|
391
|
+
DEBUG,
|
|
392
|
+
`${data.message}
|
|
393
|
+
Method : ${request.method}
|
|
394
|
+
Path : ${request.path}
|
|
395
|
+
Route : ${request.route}
|
|
396
|
+
mfaCode : ${request.options.mfaCode}`,
|
|
397
|
+
);
|
|
398
|
+
// Get ticket
|
|
399
|
+
const mfaData = data.mfa;
|
|
400
|
+
const mfaPost = await this.manager.client.api.mfa.finish.post({
|
|
401
|
+
data: {
|
|
402
|
+
ticket: mfaData.ticket,
|
|
403
|
+
data: request.options.mfaCode,
|
|
404
|
+
mfa_type: 'totp',
|
|
405
|
+
},
|
|
406
|
+
});
|
|
407
|
+
request.options.mfaToken = mfaPost.token;
|
|
408
|
+
request.retries++;
|
|
409
|
+
return this.execute(request);
|
|
410
|
+
}
|
|
398
411
|
} catch (err) {
|
|
399
412
|
throw new HTTPError(err.message, err.constructor.name, err.status, request);
|
|
400
413
|
}
|
|
414
|
+
|
|
401
415
|
throw new DiscordAPIError(data, res.status, request);
|
|
402
416
|
}
|
|
403
417
|
|
|
@@ -1,28 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { setTimeout } = require('node:timers');
|
|
4
|
-
const { findBestMatch } = require('string-similarity');
|
|
5
3
|
const Base = require('./Base');
|
|
6
|
-
const MessagePayload = require('./MessagePayload');
|
|
7
4
|
const ApplicationCommandPermissionsManager = require('../managers/ApplicationCommandPermissionsManager');
|
|
8
|
-
const {
|
|
9
|
-
ApplicationCommandOptionTypes,
|
|
10
|
-
ApplicationCommandTypes,
|
|
11
|
-
ChannelTypes,
|
|
12
|
-
Events,
|
|
13
|
-
InteractionTypes,
|
|
14
|
-
} = require('../util/Constants');
|
|
5
|
+
const { ApplicationCommandOptionTypes, ApplicationCommandTypes, ChannelTypes } = require('../util/Constants');
|
|
15
6
|
const Permissions = require('../util/Permissions');
|
|
16
7
|
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
|
17
|
-
const { lazy, getAttachments, uploadFile } = require('../util/Util');
|
|
18
|
-
const Message = lazy(() => require('../structures/Message').Message);
|
|
19
8
|
|
|
20
9
|
/**
|
|
21
10
|
* Represents an application command.
|
|
22
11
|
* @extends {Base}
|
|
23
12
|
*/
|
|
24
13
|
class ApplicationCommand extends Base {
|
|
25
|
-
constructor(client, data) {
|
|
14
|
+
constructor(client, data, guild, guildId) {
|
|
26
15
|
super(client);
|
|
27
16
|
|
|
28
17
|
/**
|
|
@@ -37,11 +26,24 @@ class ApplicationCommand extends Base {
|
|
|
37
26
|
*/
|
|
38
27
|
this.applicationId = data.application_id;
|
|
39
28
|
|
|
29
|
+
/**
|
|
30
|
+
* The guild this command is part of
|
|
31
|
+
* @type {?Guild}
|
|
32
|
+
*/
|
|
33
|
+
this.guild = guild ?? null;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The guild's id this command is part of, this may be non-null when `guild` is `null` if the command
|
|
37
|
+
* was fetched from the `ApplicationCommandManager`
|
|
38
|
+
* @type {?Snowflake}
|
|
39
|
+
*/
|
|
40
|
+
this.guildId = guild?.id ?? guildId ?? null;
|
|
41
|
+
|
|
40
42
|
/**
|
|
41
43
|
* The manager for permissions of this command on its guild or arbitrary guilds when the command is global
|
|
42
44
|
* @type {ApplicationCommandPermissionsManager}
|
|
43
45
|
*/
|
|
44
|
-
this.permissions = new ApplicationCommandPermissionsManager(this
|
|
46
|
+
this.permissions = new ApplicationCommandPermissionsManager(this);
|
|
45
47
|
|
|
46
48
|
/**
|
|
47
49
|
* The type of this application command
|
|
@@ -49,30 +51,10 @@ class ApplicationCommand extends Base {
|
|
|
49
51
|
*/
|
|
50
52
|
this.type = ApplicationCommandTypes[data.type];
|
|
51
53
|
|
|
52
|
-
this.user = client.users.cache.get(this.applicationId);
|
|
53
|
-
|
|
54
54
|
this._patch(data);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
/**
|
|
58
|
-
* The guild this command is part of
|
|
59
|
-
* @type {?Guild}
|
|
60
|
-
* @readonly
|
|
61
|
-
*/
|
|
62
|
-
get guild() {
|
|
63
|
-
return this.client.guilds.resolve(this.guildId);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
57
|
_patch(data) {
|
|
67
|
-
if ('guild_id' in data) {
|
|
68
|
-
/**
|
|
69
|
-
* The guild's id this command is part of, this may be non-null when `guild` is `null` if the command
|
|
70
|
-
* was fetched from the `ApplicationCommandManager`
|
|
71
|
-
* @type {?Snowflake}
|
|
72
|
-
*/
|
|
73
|
-
this.guildId = data.guild_id ?? null;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
58
|
if ('name' in data) {
|
|
77
59
|
/**
|
|
78
60
|
* The name of this command
|
|
@@ -148,7 +130,6 @@ class ApplicationCommand extends Base {
|
|
|
148
130
|
*/
|
|
149
131
|
this.defaultPermission = data.default_permission;
|
|
150
132
|
}
|
|
151
|
-
|
|
152
133
|
/* eslint-disable max-len */
|
|
153
134
|
|
|
154
135
|
if ('default_member_permissions' in data) {
|
|
@@ -336,7 +317,6 @@ class ApplicationCommand extends Base {
|
|
|
336
317
|
setDefaultPermission(defaultPermission = true) {
|
|
337
318
|
return this.edit({ defaultPermission });
|
|
338
319
|
}
|
|
339
|
-
|
|
340
320
|
/* eslint-enable max-len */
|
|
341
321
|
|
|
342
322
|
/**
|
|
@@ -391,6 +371,7 @@ class ApplicationCommand extends Base {
|
|
|
391
371
|
equals(command, enforceOptionOrder = false) {
|
|
392
372
|
// If given an id, check if the id matches
|
|
393
373
|
if (command.id && this.id !== command.id) return false;
|
|
374
|
+
|
|
394
375
|
let defaultMemberPermissions = null;
|
|
395
376
|
let dmPermission = command.dmPermission ?? command.dm_permission;
|
|
396
377
|
|
|
@@ -404,6 +385,7 @@ class ApplicationCommand extends Base {
|
|
|
404
385
|
defaultMemberPermissions =
|
|
405
386
|
command.defaultMemberPermissions !== null ? new Permissions(command.defaultMemberPermissions).bitfield : null;
|
|
406
387
|
}
|
|
388
|
+
|
|
407
389
|
// Check top level parameters
|
|
408
390
|
const commandType = typeof command.type === 'string' ? command.type : ApplicationCommandTypes[command.type];
|
|
409
391
|
if (
|
|
@@ -446,9 +428,7 @@ class ApplicationCommand extends Base {
|
|
|
446
428
|
const newOptions = new Map(options.map(option => [option.name, option]));
|
|
447
429
|
for (const option of existing) {
|
|
448
430
|
const foundOption = newOptions.get(option.name);
|
|
449
|
-
if (!foundOption || !this._optionEquals(option, foundOption))
|
|
450
|
-
return false;
|
|
451
|
-
}
|
|
431
|
+
if (!foundOption || !this._optionEquals(option, foundOption)) return false;
|
|
452
432
|
}
|
|
453
433
|
return true;
|
|
454
434
|
}
|
|
@@ -597,423 +577,6 @@ class ApplicationCommand extends Base {
|
|
|
597
577
|
[maxLengthKey]: option.maxLength ?? option.max_length,
|
|
598
578
|
};
|
|
599
579
|
}
|
|
600
|
-
/**
|
|
601
|
-
* Send Slash command to channel
|
|
602
|
-
* @param {Message} message Discord Message
|
|
603
|
-
* @param {Array<string>} subCommandArray SubCommand Array
|
|
604
|
-
* @param {Array<any>} options The options to Slash Command
|
|
605
|
-
* @returns {Promise<InteractionResponse>}
|
|
606
|
-
*/
|
|
607
|
-
// eslint-disable-next-line consistent-return
|
|
608
|
-
async sendSlashCommand(message, subCommandArray = [], options = []) {
|
|
609
|
-
// Todo: Refactor [Done]
|
|
610
|
-
const buildError = (type, value, array, msg) =>
|
|
611
|
-
new Error(`Invalid ${type}: ${value} ${msg}\nList of ${type}:\n${array}`);
|
|
612
|
-
// Check Options
|
|
613
|
-
if (!(message instanceof Message())) {
|
|
614
|
-
throw new TypeError('The message must be a Discord.Message');
|
|
615
|
-
}
|
|
616
|
-
if (!Array.isArray(options)) {
|
|
617
|
-
throw new TypeError('The options must be an array of strings');
|
|
618
|
-
}
|
|
619
|
-
if (this.type !== 'CHAT_INPUT') throw new Error('This command is not a chat input [/]');
|
|
620
|
-
const optionFormat = [];
|
|
621
|
-
const attachments = [];
|
|
622
|
-
const attachmentsBuffer = [];
|
|
623
|
-
const parseChoices = (list_choices, value) => {
|
|
624
|
-
if (value !== undefined) {
|
|
625
|
-
if (Array.isArray(list_choices) && list_choices.length) {
|
|
626
|
-
const choice = list_choices.find(c => c.name === value) || list_choices.find(c => c.value === value);
|
|
627
|
-
if (choice) {
|
|
628
|
-
return choice.value;
|
|
629
|
-
}
|
|
630
|
-
throw buildError(
|
|
631
|
-
'choice',
|
|
632
|
-
value,
|
|
633
|
-
list_choices.map((c, i) => ` #${i + 1} Name: ${c.name} Value: ${c.value}`).join('\n'),
|
|
634
|
-
'is not a valid choice for this option',
|
|
635
|
-
);
|
|
636
|
-
} else {
|
|
637
|
-
return value;
|
|
638
|
-
}
|
|
639
|
-
} else {
|
|
640
|
-
return undefined;
|
|
641
|
-
}
|
|
642
|
-
};
|
|
643
|
-
const parseOption = async (optionCommand, value) => {
|
|
644
|
-
const data = {
|
|
645
|
-
type: ApplicationCommandOptionTypes[optionCommand.type],
|
|
646
|
-
name: optionCommand.name,
|
|
647
|
-
};
|
|
648
|
-
if (value !== undefined) {
|
|
649
|
-
value = parseChoices(optionCommand.choices, value);
|
|
650
|
-
switch (optionCommand.type) {
|
|
651
|
-
case 'BOOLEAN': {
|
|
652
|
-
data.value = Boolean(value);
|
|
653
|
-
break;
|
|
654
|
-
}
|
|
655
|
-
case 'INTEGER': {
|
|
656
|
-
data.value = Number(value);
|
|
657
|
-
break;
|
|
658
|
-
}
|
|
659
|
-
case 'ATTACHMENT': {
|
|
660
|
-
data.value = await addDataFromAttachment(value, this.client);
|
|
661
|
-
break;
|
|
662
|
-
}
|
|
663
|
-
case 'SUB_COMMAND_GROUP': {
|
|
664
|
-
break;
|
|
665
|
-
}
|
|
666
|
-
default: {
|
|
667
|
-
if (optionCommand.autocomplete) {
|
|
668
|
-
let optionsBuild;
|
|
669
|
-
switch (subCommandArray.length) {
|
|
670
|
-
case 0: {
|
|
671
|
-
optionsBuild = [
|
|
672
|
-
...optionFormat,
|
|
673
|
-
{
|
|
674
|
-
type: ApplicationCommandOptionTypes[optionCommand.type],
|
|
675
|
-
name: optionCommand.name,
|
|
676
|
-
value,
|
|
677
|
-
focused: true,
|
|
678
|
-
},
|
|
679
|
-
];
|
|
680
|
-
break;
|
|
681
|
-
}
|
|
682
|
-
case 1: {
|
|
683
|
-
const subCommand = this.options.find(o => o.name == subCommandArray[0] && o.type == 'SUB_COMMAND');
|
|
684
|
-
optionsBuild = [
|
|
685
|
-
{
|
|
686
|
-
type: ApplicationCommandOptionTypes[subCommand.type],
|
|
687
|
-
name: subCommand.name,
|
|
688
|
-
options: [
|
|
689
|
-
...optionFormat,
|
|
690
|
-
{
|
|
691
|
-
type: ApplicationCommandOptionTypes[optionCommand.type],
|
|
692
|
-
name: optionCommand.name,
|
|
693
|
-
value,
|
|
694
|
-
focused: true,
|
|
695
|
-
},
|
|
696
|
-
],
|
|
697
|
-
},
|
|
698
|
-
];
|
|
699
|
-
break;
|
|
700
|
-
}
|
|
701
|
-
case 2: {
|
|
702
|
-
const subGroup = this.options.find(
|
|
703
|
-
o => o.name == subCommandArray[0] && o.type == 'SUB_COMMAND_GROUP',
|
|
704
|
-
);
|
|
705
|
-
const subCommand = subGroup.options.find(
|
|
706
|
-
o => o.name == subCommandArray[1] && o.type == 'SUB_COMMAND',
|
|
707
|
-
);
|
|
708
|
-
optionsBuild = [
|
|
709
|
-
{
|
|
710
|
-
type: ApplicationCommandOptionTypes[subGroup.type],
|
|
711
|
-
name: subGroup.name,
|
|
712
|
-
options: [
|
|
713
|
-
{
|
|
714
|
-
type: ApplicationCommandOptionTypes[subCommand.type],
|
|
715
|
-
name: subCommand.name,
|
|
716
|
-
options: [
|
|
717
|
-
...optionFormat,
|
|
718
|
-
{
|
|
719
|
-
type: ApplicationCommandOptionTypes[optionCommand.type],
|
|
720
|
-
name: optionCommand.name,
|
|
721
|
-
value,
|
|
722
|
-
focused: true,
|
|
723
|
-
},
|
|
724
|
-
],
|
|
725
|
-
},
|
|
726
|
-
],
|
|
727
|
-
},
|
|
728
|
-
];
|
|
729
|
-
break;
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
const autoValue = await getAutoResponse(optionsBuild, value);
|
|
733
|
-
data.value = autoValue;
|
|
734
|
-
} else {
|
|
735
|
-
data.value = value;
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
optionFormat.push(data);
|
|
740
|
-
}
|
|
741
|
-
return optionFormat;
|
|
742
|
-
};
|
|
743
|
-
const parseSubCommand = async (subCommandName, options, subGroup) => {
|
|
744
|
-
const options_sub = subGroup ? subGroup.options : this.options;
|
|
745
|
-
const subCommand = options_sub.find(
|
|
746
|
-
o => (o.name == subCommandName || o.nameLocalized == subCommandName) && o.type == 'SUB_COMMAND',
|
|
747
|
-
);
|
|
748
|
-
if (!subCommand) {
|
|
749
|
-
throw buildError(
|
|
750
|
-
'SubCommand',
|
|
751
|
-
subCommandName,
|
|
752
|
-
options_sub.map((o, i) => ` #${i + 1} Name: ${o.name}`).join('\n'),
|
|
753
|
-
'is not a valid sub command',
|
|
754
|
-
);
|
|
755
|
-
}
|
|
756
|
-
const valueRequired = subCommand.options?.filter(o => o.required).length || 0;
|
|
757
|
-
for (let i = 0; i < options.length; i++) {
|
|
758
|
-
const optionInput = subCommand.options[i];
|
|
759
|
-
const value = options[i];
|
|
760
|
-
await parseOption(optionInput, value);
|
|
761
|
-
}
|
|
762
|
-
if (valueRequired > options.length) {
|
|
763
|
-
throw new Error(`Value required missing\nDebug:
|
|
764
|
-
Required: ${valueRequired} - Options: ${optionFormat.length}`);
|
|
765
|
-
}
|
|
766
|
-
return {
|
|
767
|
-
type: ApplicationCommandOptionTypes[subCommand.type],
|
|
768
|
-
name: subCommand.name,
|
|
769
|
-
options: optionFormat,
|
|
770
|
-
};
|
|
771
|
-
};
|
|
772
|
-
const parseSubGroupCommand = async (subGroupName, subName) => {
|
|
773
|
-
const subGroup = this.options.find(
|
|
774
|
-
o => (o.name == subGroupName || o.nameLocalized == subGroupName) && o.type == 'SUB_COMMAND_GROUP',
|
|
775
|
-
);
|
|
776
|
-
if (!subGroup) {
|
|
777
|
-
throw buildError(
|
|
778
|
-
'SubGroupCommand',
|
|
779
|
-
subGroupName,
|
|
780
|
-
this.options.map((o, i) => ` #${i + 1} Name: ${o.name}`).join('\n'),
|
|
781
|
-
'is not a valid sub group command',
|
|
782
|
-
);
|
|
783
|
-
}
|
|
784
|
-
const data = await parseSubCommand(subName, options, subGroup);
|
|
785
|
-
return {
|
|
786
|
-
type: ApplicationCommandOptionTypes[subGroup.type],
|
|
787
|
-
name: subGroup.name,
|
|
788
|
-
options: [data],
|
|
789
|
-
};
|
|
790
|
-
};
|
|
791
|
-
async function addDataFromAttachment(data, client) {
|
|
792
|
-
const data_ = await MessagePayload.resolveFile(data);
|
|
793
|
-
if (!data_.file) {
|
|
794
|
-
throw new TypeError(
|
|
795
|
-
'The attachment data must be a BufferResolvable or Stream or FileOptions of MessageAttachment',
|
|
796
|
-
);
|
|
797
|
-
}
|
|
798
|
-
if (client.options.usingNewAttachmentAPI === true) {
|
|
799
|
-
const attachments_ = await getAttachments(client, message.channelId, data_);
|
|
800
|
-
await uploadFile(data_.file, attachments_[0].upload_url);
|
|
801
|
-
const id = attachments.length;
|
|
802
|
-
attachments.push({
|
|
803
|
-
id: id,
|
|
804
|
-
filename: data_.name,
|
|
805
|
-
uploaded_filename: attachments_[0].upload_filename,
|
|
806
|
-
});
|
|
807
|
-
return id;
|
|
808
|
-
} else {
|
|
809
|
-
const id = attachments.length;
|
|
810
|
-
attachments.push({
|
|
811
|
-
id: id,
|
|
812
|
-
filename: data_.name,
|
|
813
|
-
});
|
|
814
|
-
attachmentsBuffer.push(data_);
|
|
815
|
-
return id;
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
const getDataPost = (dataAdd = [], nonce, autocomplete = false) => {
|
|
819
|
-
if (!Array.isArray(dataAdd) && typeof dataAdd == 'object') {
|
|
820
|
-
dataAdd = [dataAdd];
|
|
821
|
-
}
|
|
822
|
-
const data = {
|
|
823
|
-
type: autocomplete ? InteractionTypes.APPLICATION_COMMAND_AUTOCOMPLETE : InteractionTypes.APPLICATION_COMMAND,
|
|
824
|
-
application_id: this.applicationId,
|
|
825
|
-
guild_id: message.guildId,
|
|
826
|
-
channel_id: message.channelId,
|
|
827
|
-
session_id: this.client.session_id,
|
|
828
|
-
data: {
|
|
829
|
-
version: this.version,
|
|
830
|
-
id: this.id,
|
|
831
|
-
name: this.name,
|
|
832
|
-
type: ApplicationCommandTypes[this.type],
|
|
833
|
-
options: dataAdd,
|
|
834
|
-
attachments: attachments,
|
|
835
|
-
},
|
|
836
|
-
nonce,
|
|
837
|
-
};
|
|
838
|
-
if (this.guildId) {
|
|
839
|
-
data.data.guild_id = message.guildId;
|
|
840
|
-
}
|
|
841
|
-
return data;
|
|
842
|
-
};
|
|
843
|
-
const getAutoResponse = async (sendData, value) => {
|
|
844
|
-
let nonce = SnowflakeUtil.generate();
|
|
845
|
-
const data = getDataPost(sendData, nonce, true);
|
|
846
|
-
await this.client.api.interactions.post({
|
|
847
|
-
data,
|
|
848
|
-
files: attachmentsBuffer,
|
|
849
|
-
});
|
|
850
|
-
return new Promise(resolve => {
|
|
851
|
-
const handler = data => {
|
|
852
|
-
timeout.refresh();
|
|
853
|
-
if (data.nonce !== nonce) return;
|
|
854
|
-
clearTimeout(timeout);
|
|
855
|
-
this.client.removeListener(Events.APPLICATION_COMMAND_AUTOCOMPLETE_RESPONSE, handler);
|
|
856
|
-
this.client.decrementMaxListeners();
|
|
857
|
-
if (data.choices.length > 1) {
|
|
858
|
-
// Find best match name
|
|
859
|
-
const bestMatch = findBestMatch(
|
|
860
|
-
value,
|
|
861
|
-
data.choices.map(c => c.name),
|
|
862
|
-
);
|
|
863
|
-
const result = data.choices.find(c => c.name == bestMatch.bestMatch.target);
|
|
864
|
-
resolve(result.value);
|
|
865
|
-
} else {
|
|
866
|
-
resolve(value);
|
|
867
|
-
}
|
|
868
|
-
};
|
|
869
|
-
const timeout = setTimeout(() => {
|
|
870
|
-
this.client.removeListener(Events.APPLICATION_COMMAND_AUTOCOMPLETE_RESPONSE, handler);
|
|
871
|
-
this.client.decrementMaxListeners();
|
|
872
|
-
resolve(value);
|
|
873
|
-
}, this.client.options.interactionTimeout).unref();
|
|
874
|
-
this.client.incrementMaxListeners();
|
|
875
|
-
this.client.on(Events.APPLICATION_COMMAND_AUTOCOMPLETE_RESPONSE, handler);
|
|
876
|
-
});
|
|
877
|
-
};
|
|
878
|
-
const sendData = async (optionsData = []) => {
|
|
879
|
-
let nonce = SnowflakeUtil.generate();
|
|
880
|
-
const data = getDataPost(optionsData, nonce);
|
|
881
|
-
await this.client.api.interactions.post({
|
|
882
|
-
data,
|
|
883
|
-
useFormDataPayloadJSON: true,
|
|
884
|
-
files: attachmentsBuffer,
|
|
885
|
-
});
|
|
886
|
-
this.client._interactionCache.set(nonce, {
|
|
887
|
-
channelId: message.channelId,
|
|
888
|
-
guildId: message.guildId,
|
|
889
|
-
metadata: data,
|
|
890
|
-
});
|
|
891
|
-
return new Promise((resolve, reject) => {
|
|
892
|
-
const handler = data => {
|
|
893
|
-
timeout.refresh();
|
|
894
|
-
if (data.metadata?.nonce !== nonce) return;
|
|
895
|
-
clearTimeout(timeout);
|
|
896
|
-
this.client.removeListener('interactionResponse', handler);
|
|
897
|
-
this.client.decrementMaxListeners();
|
|
898
|
-
if (data.status) {
|
|
899
|
-
resolve(data.metadata);
|
|
900
|
-
} else {
|
|
901
|
-
reject(
|
|
902
|
-
new Error('INTERACTION_ERROR', {
|
|
903
|
-
cause: data,
|
|
904
|
-
}),
|
|
905
|
-
);
|
|
906
|
-
}
|
|
907
|
-
};
|
|
908
|
-
const timeout = setTimeout(() => {
|
|
909
|
-
this.client.removeListener('interactionResponse', handler);
|
|
910
|
-
this.client.decrementMaxListeners();
|
|
911
|
-
reject(
|
|
912
|
-
new Error('INTERACTION_TIMEOUT', {
|
|
913
|
-
cause: data,
|
|
914
|
-
}),
|
|
915
|
-
);
|
|
916
|
-
}, this.client.options.interactionTimeout).unref();
|
|
917
|
-
this.client.incrementMaxListeners();
|
|
918
|
-
this.client.on('interactionResponse', handler);
|
|
919
|
-
});
|
|
920
|
-
};
|
|
921
|
-
// SubCommandArray length max 2
|
|
922
|
-
// length = 0 => no sub command
|
|
923
|
-
// length = 1 => sub command
|
|
924
|
-
// length = 2 => sub command group + sub command
|
|
925
|
-
switch (subCommandArray.length) {
|
|
926
|
-
case 0: {
|
|
927
|
-
const valueRequired = this.options?.filter(o => o.required).length || 0;
|
|
928
|
-
for (let i = 0; i < options.length; i++) {
|
|
929
|
-
const optionInput = this.options[i];
|
|
930
|
-
const value = options[i];
|
|
931
|
-
await parseOption(optionInput, value);
|
|
932
|
-
}
|
|
933
|
-
if (valueRequired > options.length) {
|
|
934
|
-
throw new Error(`Value required missing\nDebug:
|
|
935
|
-
Required: ${valueRequired} - Options: ${optionFormat.length}`);
|
|
936
|
-
}
|
|
937
|
-
return sendData(optionFormat);
|
|
938
|
-
}
|
|
939
|
-
case 1: {
|
|
940
|
-
const optionsData = await parseSubCommand(subCommandArray[0], options);
|
|
941
|
-
return sendData(optionsData);
|
|
942
|
-
}
|
|
943
|
-
case 2: {
|
|
944
|
-
const optionsData = await parseSubGroupCommand(subCommandArray[0], subCommandArray[1], options);
|
|
945
|
-
return sendData(optionsData);
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
/**
|
|
950
|
-
* Message Context Menu
|
|
951
|
-
* @param {Message} message Discord Message
|
|
952
|
-
* @returns {Promise<InteractionResponse>}
|
|
953
|
-
*/
|
|
954
|
-
async sendContextMenu(message) {
|
|
955
|
-
if (!(message instanceof Message())) {
|
|
956
|
-
throw new TypeError('The message must be a Discord.Message');
|
|
957
|
-
}
|
|
958
|
-
if (this.type == 'CHAT_INPUT') return false;
|
|
959
|
-
const nonce = SnowflakeUtil.generate();
|
|
960
|
-
const data = {
|
|
961
|
-
type: InteractionTypes.APPLICATION_COMMAND,
|
|
962
|
-
application_id: this.applicationId,
|
|
963
|
-
guild_id: message.guildId,
|
|
964
|
-
channel_id: message.channelId,
|
|
965
|
-
session_id: this.client.session_id,
|
|
966
|
-
data: {
|
|
967
|
-
version: this.version,
|
|
968
|
-
id: this.id,
|
|
969
|
-
name: this.name,
|
|
970
|
-
type: ApplicationCommandTypes[this.type],
|
|
971
|
-
target_id: ApplicationCommandTypes[this.type] == 1 ? message.author.id : message.id,
|
|
972
|
-
},
|
|
973
|
-
nonce,
|
|
974
|
-
};
|
|
975
|
-
if (this.guildId) {
|
|
976
|
-
data.data.guild_id = message.guildId;
|
|
977
|
-
}
|
|
978
|
-
await this.client.api.interactions.post({
|
|
979
|
-
data,
|
|
980
|
-
useFormDataPayloadJSON: true,
|
|
981
|
-
});
|
|
982
|
-
this.client._interactionCache.set(nonce, {
|
|
983
|
-
channelId: message.channelId,
|
|
984
|
-
guildId: message.guildId,
|
|
985
|
-
metadata: data,
|
|
986
|
-
});
|
|
987
|
-
return new Promise((resolve, reject) => {
|
|
988
|
-
const handler = data => {
|
|
989
|
-
timeout.refresh();
|
|
990
|
-
if (data.metadata?.nonce !== nonce) return;
|
|
991
|
-
clearTimeout(timeout);
|
|
992
|
-
this.client.removeListener('interactionResponse', handler);
|
|
993
|
-
this.client.decrementMaxListeners();
|
|
994
|
-
if (data.status) {
|
|
995
|
-
resolve(data.metadata);
|
|
996
|
-
} else {
|
|
997
|
-
reject(
|
|
998
|
-
new Error('INTERACTION_ERROR', {
|
|
999
|
-
cause: data,
|
|
1000
|
-
}),
|
|
1001
|
-
);
|
|
1002
|
-
}
|
|
1003
|
-
};
|
|
1004
|
-
const timeout = setTimeout(() => {
|
|
1005
|
-
this.client.removeListener('interactionResponse', handler);
|
|
1006
|
-
this.client.decrementMaxListeners();
|
|
1007
|
-
reject(
|
|
1008
|
-
new Error('INTERACTION_TIMEOUT', {
|
|
1009
|
-
cause: data,
|
|
1010
|
-
}),
|
|
1011
|
-
);
|
|
1012
|
-
}, this.client.options.interactionTimeout).unref();
|
|
1013
|
-
this.client.incrementMaxListeners();
|
|
1014
|
-
this.client.on('interactionResponse', handler);
|
|
1015
|
-
});
|
|
1016
|
-
}
|
|
1017
580
|
}
|
|
1018
581
|
|
|
1019
582
|
module.exports = ApplicationCommand;
|