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/util/RemoteAuth.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
|
-
const
|
|
2
|
+
|
|
3
|
+
const { Buffer } = require('node:buffer');
|
|
4
|
+
const crypto = require('node:crypto');
|
|
4
5
|
const EventEmitter = require('node:events');
|
|
6
|
+
const { StringDecoder } = require('node:string_decoder');
|
|
5
7
|
const { setTimeout } = require('node:timers');
|
|
6
|
-
const { StringDecoder } = require('string_decoder');
|
|
7
|
-
const chalk = require('chalk');
|
|
8
8
|
const fetch = require('node-fetch');
|
|
9
|
-
const { encode: urlsafe_b64encode } = require('safe-base64');
|
|
10
9
|
const WebSocket = require('ws');
|
|
11
|
-
const {
|
|
10
|
+
const { UserAgent } = require('./Constants');
|
|
12
11
|
const Options = require('./Options');
|
|
13
12
|
|
|
14
13
|
const defaultClientOptions = Options.createDefault();
|
|
@@ -22,9 +21,9 @@ const receiveEvent = {
|
|
|
22
21
|
NONCE_PROOF: 'nonce_proof',
|
|
23
22
|
PENDING_REMOTE_INIT: 'pending_remote_init',
|
|
24
23
|
HEARTBEAT_ACK: 'heartbeat_ack',
|
|
25
|
-
|
|
24
|
+
PENDING_TICKET: 'pending_ticket',
|
|
26
25
|
CANCEL: 'cancel',
|
|
27
|
-
|
|
26
|
+
PENDING_LOGIN: 'pending_login',
|
|
28
27
|
};
|
|
29
28
|
|
|
30
29
|
const sendEvent = {
|
|
@@ -37,266 +36,167 @@ const Event = {
|
|
|
37
36
|
READY: 'ready',
|
|
38
37
|
ERROR: 'error',
|
|
39
38
|
CANCEL: 'cancel',
|
|
40
|
-
|
|
41
|
-
SUCCESS: 'success',
|
|
39
|
+
WAIT_SCAN: 'pending',
|
|
42
40
|
FINISH: 'finish',
|
|
43
41
|
CLOSED: 'closed',
|
|
42
|
+
DEBUG: 'debug',
|
|
44
43
|
};
|
|
45
44
|
|
|
46
45
|
/**
|
|
47
|
-
*
|
|
48
|
-
* @property {?boolean} [debug=false] Log debug info
|
|
49
|
-
* @property {?boolean} [hiddenLog=false] Hide log ?
|
|
50
|
-
* @property {?boolean} [autoLogin=false] Automatically login (DiscordJS.Client Login) ?
|
|
51
|
-
* @property {?boolean} [failIfError=true] Throw error ?
|
|
52
|
-
* @property {?boolean} [generateQR=true] Create QR Code ?
|
|
53
|
-
* @property {?number} [apiVersion=9] API Version
|
|
54
|
-
* @property {?string} [userAgent] User Agent
|
|
55
|
-
* @property {?Object.<string,string>} [wsProperties] Web Socket Properties
|
|
56
|
-
*/
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Discord Auth QR (Discord.RemoteAuth will be removed in the future, v13.9.0 release)
|
|
46
|
+
* Discord Auth QR
|
|
60
47
|
* @extends {EventEmitter}
|
|
61
48
|
* @abstract
|
|
62
49
|
*/
|
|
63
50
|
class DiscordAuthWebsocket extends EventEmitter {
|
|
51
|
+
#ws = null;
|
|
52
|
+
#heartbeatInterval = null;
|
|
53
|
+
#expire = null;
|
|
54
|
+
#publicKey = null;
|
|
55
|
+
#privateKey = null;
|
|
56
|
+
#ticket = null;
|
|
57
|
+
#fingerprint = '';
|
|
58
|
+
#userDecryptString = '';
|
|
59
|
+
|
|
64
60
|
/**
|
|
65
61
|
* Creates a new DiscordAuthWebsocket instance.
|
|
66
|
-
* @param {?DiscordAuthWebsocketOptions} options Options
|
|
67
62
|
*/
|
|
68
|
-
constructor(
|
|
63
|
+
constructor() {
|
|
69
64
|
super();
|
|
70
|
-
|
|
71
|
-
* WebSocket
|
|
72
|
-
* @type {?WebSocket}
|
|
73
|
-
*/
|
|
74
|
-
this.ws = null;
|
|
75
|
-
/**
|
|
76
|
-
* Heartbeat Interval
|
|
77
|
-
* @type {?number}
|
|
78
|
-
*/
|
|
79
|
-
this.heartbeatInterval = NaN;
|
|
80
|
-
this._expire = NaN;
|
|
81
|
-
this.key = null;
|
|
82
|
-
/**
|
|
83
|
-
* User (Scan QR Code)
|
|
84
|
-
* @type {?Object}
|
|
85
|
-
*/
|
|
86
|
-
this.user = null;
|
|
87
|
-
/**
|
|
88
|
-
* Temporary Token (Scan QR Code)
|
|
89
|
-
* @type {?string}
|
|
90
|
-
*/
|
|
91
|
-
this.token = undefined;
|
|
92
|
-
/**
|
|
93
|
-
* Real Token (Login)
|
|
94
|
-
* @type {?string}
|
|
95
|
-
*/
|
|
96
|
-
this.realToken = undefined;
|
|
97
|
-
/**
|
|
98
|
-
* Fingerprint (QR Code)
|
|
99
|
-
* @type {?string}
|
|
100
|
-
*/
|
|
101
|
-
this.fingerprint = null;
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Captcha Handler
|
|
105
|
-
* @type {Function}
|
|
106
|
-
* @param {Captcha} data hcaptcha data
|
|
107
|
-
* @returns {Promise<string>} Captcha token
|
|
108
|
-
*/
|
|
109
|
-
// eslint-disable-next-line no-unused-vars
|
|
110
|
-
this.captchaSolver = data =>
|
|
111
|
-
new Promise((resolve, reject) => {
|
|
112
|
-
reject(
|
|
113
|
-
new Error(`
|
|
114
|
-
Captcha Handler not found - Please set captchaSolver option
|
|
115
|
-
Example captchaSolver function:
|
|
116
|
-
|
|
117
|
-
new DiscordAuthWebsocket({
|
|
118
|
-
captchaSolver: async (data) => {
|
|
119
|
-
const token = await hcaptchaSolver(data.captcha_sitekey, 'discord.com');
|
|
120
|
-
return token;
|
|
65
|
+
this.token = '';
|
|
121
66
|
}
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
`),
|
|
125
|
-
);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Captcha Cache
|
|
130
|
-
* @type {?Captcha}
|
|
131
|
-
*/
|
|
132
|
-
this.captchaCache = null;
|
|
133
|
-
|
|
134
|
-
this._validateOptions(options);
|
|
135
67
|
|
|
136
|
-
|
|
68
|
+
/**
|
|
69
|
+
* @type {string}
|
|
70
|
+
*/
|
|
71
|
+
get AuthURL() {
|
|
72
|
+
return baseURL + this.#fingerprint;
|
|
137
73
|
}
|
|
74
|
+
|
|
138
75
|
/**
|
|
139
|
-
*
|
|
140
|
-
* @type {string} Expire time
|
|
141
|
-
* @readonly
|
|
76
|
+
* @type {Date}
|
|
142
77
|
*/
|
|
143
|
-
get
|
|
144
|
-
return this
|
|
78
|
+
get exprire() {
|
|
79
|
+
return this.#expire;
|
|
145
80
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
this
|
|
152
|
-
debug: false,
|
|
153
|
-
hiddenLog: false,
|
|
154
|
-
autoLogin: false,
|
|
155
|
-
failIfError: true,
|
|
156
|
-
generateQR: true,
|
|
157
|
-
apiVersion: 9,
|
|
158
|
-
userAgent: defaultUA,
|
|
159
|
-
wsProperties: defaultClientOptions.ws.properties,
|
|
160
|
-
captchaSolver: () => new Error('Captcha Handler not found. Please set captchaSolver option.'),
|
|
161
|
-
};
|
|
162
|
-
if (typeof options == 'object') {
|
|
163
|
-
if (typeof options.debug == 'boolean') this.options.debug = options.debug;
|
|
164
|
-
if (typeof options.hiddenLog == 'boolean') this.options.hiddenLog = options.hiddenLog;
|
|
165
|
-
if (typeof options.autoLogin == 'boolean') this.options.autoLogin = options.autoLogin;
|
|
166
|
-
if (typeof options.failIfError == 'boolean') this.options.failIfError = options.failIfError;
|
|
167
|
-
if (typeof options.generateQR == 'boolean') this.options.generateQR = options.generateQR;
|
|
168
|
-
if (typeof options.apiVersion == 'number') this.options.apiVersion = options.apiVersion;
|
|
169
|
-
if (typeof options.userAgent == 'string') this.options.userAgent = options.userAgent;
|
|
170
|
-
if (typeof options.wsProperties == 'object') this.options.wsProperties = options.wsProperties;
|
|
171
|
-
if (typeof options.captchaSolver == 'function') this.captchaSolver = options.captchaSolver;
|
|
172
|
-
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @type {UserRaw}
|
|
84
|
+
*/
|
|
85
|
+
get user() {
|
|
86
|
+
return DiscordAuthWebsocket.decryptUser(this.#userDecryptString);
|
|
173
87
|
}
|
|
174
|
-
|
|
175
|
-
|
|
88
|
+
|
|
89
|
+
#createWebSocket(url) {
|
|
90
|
+
this.#ws = new WebSocket(url, {
|
|
176
91
|
headers: {
|
|
177
92
|
Origin: 'https://discord.com',
|
|
178
|
-
'User-Agent':
|
|
93
|
+
'User-Agent': UserAgent,
|
|
179
94
|
},
|
|
180
95
|
});
|
|
181
|
-
this
|
|
96
|
+
this.#handleWebSocket();
|
|
182
97
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
98
|
+
|
|
99
|
+
#handleWebSocket() {
|
|
100
|
+
this.#ws.on('error', error => {
|
|
101
|
+
/**
|
|
102
|
+
* WS Error
|
|
103
|
+
* @event DiscordAuthWebsocket#error
|
|
104
|
+
* @param {Error} error Error
|
|
105
|
+
*/
|
|
106
|
+
this.emit(Event.ERROR, error);
|
|
189
107
|
});
|
|
190
|
-
this
|
|
191
|
-
|
|
108
|
+
this.#ws.on('open', () => {
|
|
109
|
+
/**
|
|
110
|
+
* Debug Event
|
|
111
|
+
* @event DiscordAuthWebsocket#debug
|
|
112
|
+
* @param {string} msg Debug msg
|
|
113
|
+
*/
|
|
114
|
+
this.emit(Event.DEBUG, '[WS] Client Connected');
|
|
192
115
|
});
|
|
193
|
-
this
|
|
194
|
-
this.
|
|
116
|
+
this.#ws.on('close', () => {
|
|
117
|
+
this.emit(Event.DEBUG, '[WS] Connection closed');
|
|
195
118
|
});
|
|
119
|
+
this.#ws.on('message', this.#handleMessage.bind(this));
|
|
196
120
|
}
|
|
197
|
-
|
|
121
|
+
|
|
122
|
+
#handleMessage(message) {
|
|
123
|
+
message = JSON.parse(message);
|
|
198
124
|
switch (message.op) {
|
|
199
125
|
case receiveEvent.HELLO: {
|
|
200
|
-
this
|
|
126
|
+
this.#ready(message);
|
|
201
127
|
break;
|
|
202
128
|
}
|
|
129
|
+
|
|
203
130
|
case receiveEvent.NONCE_PROOF: {
|
|
204
|
-
this
|
|
131
|
+
this.#receiveNonceProof(message);
|
|
205
132
|
break;
|
|
206
133
|
}
|
|
134
|
+
|
|
207
135
|
case receiveEvent.PENDING_REMOTE_INIT: {
|
|
208
|
-
this.
|
|
136
|
+
this.#fingerprint = message.fingerprint;
|
|
137
|
+
/**
|
|
138
|
+
* Ready Event
|
|
139
|
+
* @event DiscordAuthWebsocket#ready
|
|
140
|
+
* @param {DiscordAuthWebsocket} client WS
|
|
141
|
+
*/
|
|
142
|
+
this.emit(Event.READY, this);
|
|
209
143
|
break;
|
|
210
144
|
}
|
|
145
|
+
|
|
211
146
|
case receiveEvent.HEARTBEAT_ACK: {
|
|
212
|
-
this.
|
|
213
|
-
this
|
|
147
|
+
this.emit(Event.DEBUG, `Heartbeat acknowledged.`);
|
|
148
|
+
this.#heartbeatAck();
|
|
214
149
|
break;
|
|
215
150
|
}
|
|
216
|
-
|
|
217
|
-
|
|
151
|
+
|
|
152
|
+
case receiveEvent.PENDING_TICKET: {
|
|
153
|
+
this.#pendingLogin(message);
|
|
218
154
|
break;
|
|
219
155
|
}
|
|
156
|
+
|
|
220
157
|
case receiveEvent.CANCEL: {
|
|
221
|
-
this._logger('debug', 'Cancel login.');
|
|
222
158
|
/**
|
|
223
|
-
*
|
|
159
|
+
* Cancel
|
|
224
160
|
* @event DiscordAuthWebsocket#cancel
|
|
225
|
-
* @param {
|
|
161
|
+
* @param {DiscordAuthWebsocket} client WS
|
|
226
162
|
*/
|
|
227
|
-
this.emit(Event.CANCEL, this
|
|
163
|
+
this.emit(Event.CANCEL, this);
|
|
228
164
|
this.destroy();
|
|
229
165
|
break;
|
|
230
166
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
* @event DiscordAuthWebsocket#success
|
|
236
|
-
* @param {object} user Discord User
|
|
237
|
-
* @param {string} token Discord Token (Fake)
|
|
238
|
-
*/
|
|
239
|
-
this.emit(Event.SUCCESS, this.user, message.ticket);
|
|
240
|
-
this.token = message.ticket;
|
|
241
|
-
this._findRealToken();
|
|
242
|
-
this._logger('default', 'Get token success.');
|
|
243
|
-
break;
|
|
244
|
-
}
|
|
245
|
-
default: {
|
|
246
|
-
this._logger('debug', `Unknown op: ${message.op}`, message);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
_logger(type = 'default', ...message) {
|
|
251
|
-
if (this.options.hiddenLog) return;
|
|
252
|
-
switch (type.toLowerCase()) {
|
|
253
|
-
case 'error': {
|
|
254
|
-
// eslint-disable-next-line no-unused-expressions
|
|
255
|
-
this.options.failIfError
|
|
256
|
-
? this._throwError(new Error(message[0]))
|
|
257
|
-
: console.error(chalk.red(`[DiscordRemoteAuth] ERROR`), ...message);
|
|
258
|
-
break;
|
|
259
|
-
}
|
|
260
|
-
case 'default': {
|
|
261
|
-
console.log(chalk.green(`[DiscordRemoteAuth]`), ...message);
|
|
262
|
-
break;
|
|
263
|
-
}
|
|
264
|
-
case 'debug': {
|
|
265
|
-
if (this.options.debug) console.log(chalk.yellow(`[DiscordRemoteAuth] DEBUG`), ...message);
|
|
167
|
+
|
|
168
|
+
case receiveEvent.PENDING_LOGIN: {
|
|
169
|
+
this.#ticket = message.ticket;
|
|
170
|
+
this.#findRealToken();
|
|
266
171
|
break;
|
|
267
172
|
}
|
|
268
173
|
}
|
|
269
174
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}
|
|
274
|
-
_send(op, data) {
|
|
275
|
-
if (!this.ws) this._throwError(new Error('WebSocket is not connected.'));
|
|
175
|
+
|
|
176
|
+
#send(op, data) {
|
|
177
|
+
if (!this.#ws) return;
|
|
276
178
|
let payload = { op: op };
|
|
277
179
|
if (data !== null) payload = { ...payload, ...data };
|
|
278
|
-
this.
|
|
279
|
-
this.ws.send(JSON.stringify(payload));
|
|
280
|
-
}
|
|
281
|
-
_heartbeat() {
|
|
282
|
-
this._send(sendEvent.HEARTBEAT);
|
|
180
|
+
this.#ws.send(JSON.stringify(payload));
|
|
283
181
|
}
|
|
284
|
-
|
|
182
|
+
|
|
183
|
+
#heartbeatAck() {
|
|
285
184
|
setTimeout(() => {
|
|
286
|
-
this.
|
|
287
|
-
}, this
|
|
185
|
+
this.#send(sendEvent.HEARTBEAT);
|
|
186
|
+
}, this.#heartbeatInterval).unref();
|
|
288
187
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
this.
|
|
292
|
-
this
|
|
293
|
-
this.
|
|
294
|
-
this
|
|
295
|
-
this
|
|
188
|
+
|
|
189
|
+
#ready(data) {
|
|
190
|
+
this.emit(Event.DEBUG, 'Attempting server handshake...');
|
|
191
|
+
this.#expire = new Date(Date.now() + data.timeout_ms);
|
|
192
|
+
this.#heartbeatInterval = data.heartbeat_interval;
|
|
193
|
+
this.#createKey();
|
|
194
|
+
this.#heartbeatAck();
|
|
195
|
+
this.#init();
|
|
296
196
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
197
|
+
|
|
198
|
+
#createKey() {
|
|
199
|
+
const key = crypto.generateKeyPairSync('rsa', {
|
|
300
200
|
modulusLength: 2048,
|
|
301
201
|
publicKeyEncoding: {
|
|
302
202
|
type: 'spki',
|
|
@@ -307,35 +207,41 @@ new DiscordAuthWebsocket({
|
|
|
307
207
|
format: 'pem',
|
|
308
208
|
},
|
|
309
209
|
});
|
|
210
|
+
this.#privateKey = key.privateKey;
|
|
211
|
+
this.#publicKey = key.publicKey;
|
|
310
212
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
this._logger('debug', 'Generating public key...');
|
|
213
|
+
|
|
214
|
+
#encodePublicKey() {
|
|
314
215
|
const decoder = new StringDecoder('utf-8');
|
|
315
|
-
let pub_key = decoder.write(this
|
|
216
|
+
let pub_key = decoder.write(this.#publicKey);
|
|
316
217
|
pub_key = pub_key.split('\n').slice(1, -2).join('');
|
|
317
|
-
this._logger('debug', 'Public key generated.', pub_key);
|
|
318
218
|
return pub_key;
|
|
319
219
|
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
220
|
+
|
|
221
|
+
#init() {
|
|
222
|
+
const public_key = this.#encodePublicKey();
|
|
223
|
+
this.#send(sendEvent.INIT, { encoded_public_key: public_key });
|
|
323
224
|
}
|
|
324
|
-
|
|
225
|
+
|
|
226
|
+
#receiveNonceProof(data) {
|
|
325
227
|
const nonce = data.encrypted_nonce;
|
|
326
|
-
const decrypted_nonce = this
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
228
|
+
const decrypted_nonce = this.#decryptPayload(nonce);
|
|
229
|
+
const proof = crypto
|
|
230
|
+
.createHash('sha256')
|
|
231
|
+
.update(decrypted_nonce)
|
|
232
|
+
.digest()
|
|
233
|
+
.toString('base64')
|
|
234
|
+
.replace(/\+/g, '-')
|
|
235
|
+
.replace(/\//g, '_')
|
|
236
|
+
.replace(/=+/, '')
|
|
237
|
+
.replace(/\s+$/, '');
|
|
238
|
+
this.#send(sendEvent.NONCE_PROOF, { proof: proof });
|
|
332
239
|
}
|
|
333
|
-
|
|
334
|
-
|
|
240
|
+
|
|
241
|
+
#decryptPayload(encrypted_payload) {
|
|
335
242
|
const payload = Buffer.from(encrypted_payload, 'base64');
|
|
336
|
-
this._logger('debug', `Encrypted Payload (Buffer):`, payload);
|
|
337
243
|
const decoder = new StringDecoder('utf-8');
|
|
338
|
-
const private_key = decoder.write(this
|
|
244
|
+
const private_key = decoder.write(this.#privateKey);
|
|
339
245
|
const data = crypto.privateDecrypt(
|
|
340
246
|
{
|
|
341
247
|
key: private_key,
|
|
@@ -344,170 +250,129 @@ new DiscordAuthWebsocket({
|
|
|
344
250
|
},
|
|
345
251
|
payload,
|
|
346
252
|
);
|
|
347
|
-
this._logger('debug', `Decrypted Payload:`, data.toString());
|
|
348
253
|
return data;
|
|
349
254
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
const
|
|
353
|
-
this
|
|
255
|
+
|
|
256
|
+
#pendingLogin(data) {
|
|
257
|
+
const user_data = this.#decryptPayload(data.encrypted_user_payload);
|
|
258
|
+
this.#userDecryptString = user_data.toString();
|
|
259
|
+
|
|
354
260
|
/**
|
|
355
|
-
*
|
|
356
|
-
* @
|
|
357
|
-
* @
|
|
261
|
+
* @typedef {Object} UserRaw
|
|
262
|
+
* @property {Snowflake} id
|
|
263
|
+
* @property {string} username
|
|
264
|
+
* @property {number} discriminator
|
|
265
|
+
* @property {string} avatar
|
|
358
266
|
*/
|
|
359
|
-
|
|
360
|
-
this._logger('debug', 'Waiting for user to finish login...');
|
|
361
|
-
this.user.prettyPrint(this);
|
|
362
|
-
this._logger('default', 'Please check your phone again to confirm login.');
|
|
363
|
-
}
|
|
364
|
-
_pendingRemoteInit(data) {
|
|
365
|
-
this._logger('debug', `Pending Remote Init:`, data);
|
|
267
|
+
|
|
366
268
|
/**
|
|
367
|
-
* Emitted whenever a
|
|
368
|
-
* @event DiscordAuthWebsocket#
|
|
369
|
-
* @param {
|
|
370
|
-
* @param {string} url DiscordAuthWebsocket
|
|
269
|
+
* Emitted whenever a user is scan QR Code.
|
|
270
|
+
* @event DiscordAuthWebsocket#pending
|
|
271
|
+
* @param {UserRaw} user Discord User Raw
|
|
371
272
|
*/
|
|
372
|
-
this.emit(Event.
|
|
373
|
-
this.fingerprint = data.fingerprint;
|
|
374
|
-
if (this.options.generateQR) this.generateQR();
|
|
273
|
+
this.emit(Event.WAIT_SCAN, this.user);
|
|
375
274
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
275
|
+
|
|
276
|
+
#awaitLogin(client) {
|
|
277
|
+
return new Promise(r => {
|
|
278
|
+
this.once(Event.FINISH, token => {
|
|
279
|
+
r(client.login(token));
|
|
280
|
+
});
|
|
380
281
|
});
|
|
381
282
|
}
|
|
283
|
+
|
|
382
284
|
/**
|
|
383
|
-
* Connect
|
|
384
|
-
* @param {
|
|
385
|
-
* @returns {
|
|
285
|
+
* Connect WS
|
|
286
|
+
* @param {Client} [client] DiscordJS Client
|
|
287
|
+
* @returns {Promise<void>}
|
|
386
288
|
*/
|
|
387
289
|
connect(client) {
|
|
388
|
-
this
|
|
389
|
-
if (client
|
|
290
|
+
this.#createWebSocket(wsURL);
|
|
291
|
+
if (client) {
|
|
292
|
+
return this.#awaitLogin(client);
|
|
293
|
+
} else {
|
|
294
|
+
return Promise.resolve();
|
|
295
|
+
}
|
|
390
296
|
}
|
|
297
|
+
|
|
391
298
|
/**
|
|
392
|
-
*
|
|
393
|
-
* @returns {
|
|
299
|
+
* Destroy client
|
|
300
|
+
* @returns {void}
|
|
394
301
|
*/
|
|
395
302
|
destroy() {
|
|
396
|
-
if (!this.ws)
|
|
303
|
+
if (!this.ws) return;
|
|
397
304
|
this.ws.close();
|
|
305
|
+
this.emit(Event.DEBUG, 'WebSocket closed.');
|
|
398
306
|
/**
|
|
399
307
|
* Emitted whenever a connection is closed.
|
|
400
308
|
* @event DiscordAuthWebsocket#closed
|
|
401
|
-
* @param {boolean} loginState Login state
|
|
402
309
|
*/
|
|
403
|
-
this.emit(Event.CLOSED
|
|
404
|
-
this._logger('debug', 'WebSocket closed.');
|
|
310
|
+
this.emit(Event.CLOSED);
|
|
405
311
|
}
|
|
312
|
+
|
|
406
313
|
/**
|
|
407
314
|
* Generate QR code for user to scan (Terminal)
|
|
408
|
-
* @returns {
|
|
315
|
+
* @returns {void}
|
|
409
316
|
*/
|
|
410
317
|
generateQR() {
|
|
411
|
-
if (!this
|
|
412
|
-
require('@aikochan2k6/qrcode-terminal').generate(
|
|
318
|
+
if (!this.#fingerprint) return;
|
|
319
|
+
require('@aikochan2k6/qrcode-terminal').generate(this.AuthURL, {
|
|
413
320
|
small: true,
|
|
414
321
|
});
|
|
415
|
-
this._logger('default', `Please scan the QR code to continue.\nQR Code will expire in ${this.exprireTime}`);
|
|
416
322
|
}
|
|
417
323
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
}
|
|
455
|
-
: {
|
|
456
|
-
ticket: this.token,
|
|
457
|
-
},
|
|
458
|
-
),
|
|
324
|
+
#findRealToken() {
|
|
325
|
+
return fetch(`https://discord.com/api/v9/users/@me/remote-auth/login`, {
|
|
326
|
+
method: 'POST',
|
|
327
|
+
headers: {
|
|
328
|
+
Accept: '*/*',
|
|
329
|
+
'Accept-Language': 'en-US',
|
|
330
|
+
'Content-Type': 'application/json',
|
|
331
|
+
'Sec-Fetch-Dest': 'empty',
|
|
332
|
+
'Sec-Fetch-Mode': 'cors',
|
|
333
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
334
|
+
'X-Debug-Options': 'bugReporterEnabled',
|
|
335
|
+
'X-Super-Properties': `${Buffer.from(JSON.stringify(defaultClientOptions.ws.properties), 'ascii').toString(
|
|
336
|
+
'base64',
|
|
337
|
+
)}`,
|
|
338
|
+
'X-Discord-Locale': 'en-US',
|
|
339
|
+
'User-Agent': UserAgent,
|
|
340
|
+
Referer: 'https://discord.com/channels/@me',
|
|
341
|
+
Connection: 'keep-alive',
|
|
342
|
+
Origin: 'https://discord.com',
|
|
343
|
+
},
|
|
344
|
+
body: JSON.stringify({
|
|
345
|
+
ticket: this.#ticket,
|
|
346
|
+
}),
|
|
347
|
+
})
|
|
348
|
+
.then(r => r.json())
|
|
349
|
+
.then(res => {
|
|
350
|
+
if (res.encrypted_token) {
|
|
351
|
+
this.token = this.#decryptPayload(res.encrypted_token).toString();
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Emitted whenever a real token is found.
|
|
355
|
+
* @event DiscordAuthWebsocket#finish
|
|
356
|
+
* @param {string} token Discord Token
|
|
357
|
+
*/
|
|
358
|
+
this.emit(Event.FINISH, this.token);
|
|
359
|
+
this.destroy();
|
|
459
360
|
})
|
|
460
|
-
|
|
461
|
-
if (res?.captcha_key) {
|
|
462
|
-
this.captchaCache = res;
|
|
463
|
-
} else if (!res.encrypted_token) {
|
|
464
|
-
this._throwError(new Error('Request failed. Please try again.', res));
|
|
465
|
-
this.captchaCache = null;
|
|
466
|
-
}
|
|
467
|
-
if (!res && this.captchaCache) {
|
|
468
|
-
this._logger('default', 'Captcha is detected. Please solve the captcha to continue.');
|
|
469
|
-
this._logger('debug', 'Try call captchaSolver()', this.captchaCache);
|
|
470
|
-
const token = await this.options.captchaSolver(this.captchaCache);
|
|
471
|
-
return this._findRealToken(token);
|
|
472
|
-
}
|
|
473
|
-
this.realToken = this._decryptPayload(res.encrypted_token).toString();
|
|
474
|
-
/**
|
|
475
|
-
* Emitted whenever a real token is found.
|
|
476
|
-
* @event DiscordAuthWebsocket#finish
|
|
477
|
-
* @param {object} user User
|
|
478
|
-
* @param {string} token Real token
|
|
479
|
-
*/
|
|
480
|
-
this.emit(Event.FINISH, this.user, this.realToken);
|
|
481
|
-
return this;
|
|
361
|
+
.catch(() => false);
|
|
482
362
|
}
|
|
483
|
-
}
|
|
484
363
|
|
|
485
|
-
|
|
486
|
-
constructor(payload) {
|
|
364
|
+
static decryptUser(payload) {
|
|
487
365
|
const values = payload.split(':');
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
return
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
get tag() {
|
|
500
|
-
return `${this.username}#${this.discriminator}`;
|
|
501
|
-
}
|
|
502
|
-
prettyPrint(RemoteAuth) {
|
|
503
|
-
let string = `\n`;
|
|
504
|
-
string += ` ${chalk.bgBlue('User:')} `;
|
|
505
|
-
string += `${this.tag} (${this.id})\n`;
|
|
506
|
-
string += ` ${chalk.bgGreen('Avatar URL:')} `;
|
|
507
|
-
string += chalk.cyan(`${this.avatarURL}\n`);
|
|
508
|
-
string += ` ${chalk.bgMagenta('Token:')} `;
|
|
509
|
-
string += chalk.red(`${this.token ? this.token : 'Unknown'}`);
|
|
510
|
-
RemoteAuth._logger('default', string);
|
|
366
|
+
const id = values[0];
|
|
367
|
+
const username = values[3];
|
|
368
|
+
const discriminator = values[1];
|
|
369
|
+
const avatar = values[2];
|
|
370
|
+
return {
|
|
371
|
+
id,
|
|
372
|
+
username,
|
|
373
|
+
discriminator,
|
|
374
|
+
avatar,
|
|
375
|
+
};
|
|
511
376
|
}
|
|
512
377
|
}
|
|
513
378
|
|