djs-selfbot-v13 3.1.6 → 3.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -16
- package/package.json +15 -8
- package/src/client/BaseClient.js +3 -2
- package/src/client/Client.js +539 -187
- package/src/client/actions/Action.js +13 -18
- package/src/client/actions/ActionsManager.js +1 -7
- package/src/client/actions/AutoModerationActionExecution.js +0 -1
- package/src/client/actions/AutoModerationRuleCreate.js +0 -1
- package/src/client/actions/AutoModerationRuleDelete.js +0 -1
- package/src/client/actions/AutoModerationRuleUpdate.js +0 -1
- package/src/client/actions/InteractionCreate.js +115 -0
- package/src/client/actions/MessageCreate.js +4 -0
- package/src/client/actions/PresenceUpdate.js +16 -17
- package/src/client/websocket/WebSocketManager.js +31 -11
- package/src/client/websocket/WebSocketShard.js +38 -39
- package/src/client/websocket/handlers/APPLICATION_COMMAND_AUTOCOMPLETE_RESPONSE.js +23 -0
- 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 +13 -16
- package/src/client/websocket/handlers/CHANNEL_RECIPIENT_REMOVE.js +11 -11
- package/src/client/websocket/handlers/GUILD_APPLICATION_COMMANDS_UPDATE.js +11 -0
- package/src/client/websocket/handlers/GUILD_CREATE.js +0 -7
- package/src/client/websocket/handlers/GUILD_MEMBER_LIST_UPDATE.js +55 -0
- 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 +16 -0
- package/src/client/websocket/handlers/INTERACTION_FAILURE.js +18 -0
- package/src/client/websocket/handlers/INTERACTION_MODAL_CREATE.js +0 -1
- package/src/client/websocket/handlers/INTERACTION_SUCCESS.js +30 -0
- package/src/client/websocket/handlers/MESSAGE_ACK.js +16 -0
- package/src/client/websocket/handlers/READY.js +137 -47
- package/src/client/websocket/handlers/RELATIONSHIP_ADD.js +5 -7
- package/src/client/websocket/handlers/RELATIONSHIP_REMOVE.js +4 -6
- package/src/client/websocket/handlers/RELATIONSHIP_UPDATE.js +9 -32
- package/src/client/websocket/handlers/SOUNDBOARD_SOUNDS.js +0 -0
- package/src/client/websocket/handlers/USER_GUILD_SETTINGS_UPDATE.js +8 -2
- package/src/client/websocket/handlers/USER_NOTE_UPDATE.js +1 -1
- package/src/client/websocket/handlers/USER_SETTINGS_UPDATE.js +5 -1
- package/src/client/websocket/handlers/VOICE_CHANNEL_EFFECT_SEND.js +0 -0
- package/src/client/websocket/handlers/index.js +20 -15
- package/src/errors/Messages.js +69 -24
- package/src/index.js +43 -12
- package/src/managers/ApplicationCommandManager.js +12 -9
- package/src/managers/ApplicationCommandPermissionsManager.js +11 -3
- package/src/managers/ChannelManager.js +4 -2
- package/src/managers/ClientUserSettingManager.js +279 -161
- package/src/managers/DeveloperPortalManager.js +104 -0
- package/src/managers/GuildApplicationCommandManager.js +28 -0
- package/src/managers/GuildBanManager.js +1 -1
- package/src/managers/GuildChannelManager.js +0 -2
- package/src/managers/GuildFolderManager.js +24 -0
- package/src/managers/GuildForumThreadManager.js +28 -22
- package/src/managers/GuildMemberManager.js +216 -40
- package/src/managers/GuildSettingManager.js +15 -22
- package/src/managers/MessageManager.js +44 -42
- package/src/managers/PermissionOverwriteManager.js +1 -1
- package/src/managers/ReactionUserManager.js +5 -5
- package/src/managers/RelationshipManager.js +74 -81
- package/src/managers/SessionManager.js +57 -0
- package/src/managers/ThreadManager.js +45 -12
- package/src/managers/ThreadMemberManager.js +1 -1
- package/src/managers/UserManager.js +10 -6
- package/src/rest/APIRequest.js +20 -42
- package/src/rest/CaptchaSolver.js +132 -0
- package/src/rest/DiscordAPIError.js +16 -17
- package/src/rest/RESTManager.js +21 -1
- package/src/rest/RequestHandler.js +21 -35
- package/src/structures/ApplicationCommand.js +456 -19
- package/src/structures/ApplicationRoleConnectionMetadata.js +0 -3
- package/src/structures/AutoModerationRule.js +5 -5
- package/src/structures/AutocompleteInteraction.js +0 -1
- package/src/structures/BaseGuildTextChannel.js +12 -10
- package/src/structures/BaseGuildVoiceChannel.js +18 -16
- package/src/structures/{CallState.js → Call.js} +12 -17
- package/src/structures/CategoryChannel.js +0 -2
- package/src/structures/Channel.js +3 -2
- package/src/structures/ClientApplication.js +204 -0
- package/src/structures/ClientPresence.js +8 -12
- package/src/structures/ClientUser.js +336 -117
- package/src/structures/ContextMenuInteraction.js +1 -1
- package/src/structures/DMChannel.js +92 -29
- package/src/structures/DeveloperPortalApplication.js +520 -0
- package/src/structures/ForumChannel.js +10 -0
- package/src/structures/Guild.js +271 -135
- package/src/structures/GuildAuditLogs.js +5 -0
- package/src/structures/GuildChannel.js +2 -16
- package/src/structures/GuildFolder.js +75 -0
- package/src/structures/GuildMember.js +145 -27
- package/src/structures/Interaction.js +62 -1
- package/src/structures/InteractionResponse.js +114 -0
- package/src/structures/Invite.js +52 -35
- package/src/structures/Message.js +202 -222
- package/src/structures/MessageAttachment.js +0 -11
- package/src/structures/MessageButton.js +67 -1
- package/src/structures/MessageEmbed.js +1 -1
- package/src/structures/MessageMentions.js +2 -3
- package/src/structures/MessagePayload.js +46 -4
- package/src/structures/MessageReaction.js +1 -1
- package/src/structures/MessageSelectMenu.js +252 -1
- package/src/structures/Modal.js +180 -75
- package/src/structures/PartialGroupDMChannel.js +433 -0
- package/src/structures/Presence.js +2 -2
- package/src/structures/RichPresence.js +34 -14
- package/src/structures/Role.js +2 -18
- package/src/structures/SelectMenuInteraction.js +151 -2
- package/src/structures/Session.js +81 -0
- package/src/structures/Team.js +49 -0
- package/src/structures/TextInputComponent.js +70 -0
- package/src/structures/ThreadChannel.js +19 -0
- package/src/structures/User.js +345 -117
- package/src/structures/UserContextMenuInteraction.js +2 -2
- package/src/structures/VoiceState.js +39 -74
- package/src/structures/WebEmbed.js +52 -38
- package/src/structures/Webhook.js +11 -17
- package/src/structures/interfaces/Application.js +23 -146
- package/src/structures/interfaces/TextBasedChannel.js +256 -411
- package/src/util/ApplicationFlags.js +1 -1
- package/src/util/Constants.js +284 -106
- package/src/util/Formatters.js +2 -16
- package/src/util/LimitedCollection.js +1 -1
- package/src/util/Options.js +68 -48
- package/src/util/Permissions.js +0 -5
- package/src/util/PurchasedFlags.js +0 -2
- package/src/util/RemoteAuth.js +356 -221
- package/src/util/Sweepers.js +1 -1
- package/src/util/Util.js +36 -76
- package/src/util/Voice.js +1456 -0
- package/src/util/arRPC/index.js +229 -0
- package/src/util/arRPC/process/detectable.json +1 -0
- package/src/util/arRPC/process/index.js +102 -0
- package/src/util/arRPC/process/native/index.js +5 -0
- package/src/util/arRPC/process/native/linux.js +37 -0
- package/src/util/arRPC/process/native/win32.js +25 -0
- package/src/util/arRPC/transports/ipc.js +281 -0
- package/src/util/arRPC/transports/websocket.js +128 -0
- package/typings/enums.d.ts +73 -18
- package/typings/index.d.ts +1249 -897
- package/typings/rawDataTypes.d.ts +9 -68
- package/src/client/websocket/handlers/USER_REQUIRED_ACTION_UPDATE.js +0 -78
- package/src/client/websocket/handlers/VOICE_CHANNEL_STATUS_UPDATE.js +0 -12
- package/src/managers/UserNoteManager.js +0 -53
- package/src/structures/GroupDMChannel.js +0 -387
- package/src/util/AttachmentFlags.js +0 -38
- package/src/util/InviteFlags.js +0 -29
- package/src/util/RoleFlags.js +0 -37
package/src/client/Client.js
CHANGED
|
@@ -1,40 +1,47 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const process = require('node:process');
|
|
4
|
-
const { setInterval } = require('node:timers');
|
|
5
|
-
const { setTimeout } = require('node:timers');
|
|
4
|
+
const { setInterval, setTimeout } = require('node:timers');
|
|
6
5
|
const { Collection } = require('@discordjs/collection');
|
|
6
|
+
const { getVoiceConnection } = require('@discordjs/voice');
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
const fetch = require('node-fetch');
|
|
7
9
|
const BaseClient = require('./BaseClient');
|
|
8
10
|
const ActionsManager = require('./actions/ActionsManager');
|
|
9
11
|
const ClientVoiceManager = require('./voice/ClientVoiceManager');
|
|
10
12
|
const WebSocketManager = require('./websocket/WebSocketManager');
|
|
11
|
-
const { Error, TypeError } = require('../errors');
|
|
13
|
+
const { Error, TypeError, RangeError } = require('../errors');
|
|
14
|
+
const Discord = require('../index');
|
|
12
15
|
const BaseGuildEmojiManager = require('../managers/BaseGuildEmojiManager');
|
|
13
16
|
const BillingManager = require('../managers/BillingManager');
|
|
14
17
|
const ChannelManager = require('../managers/ChannelManager');
|
|
15
18
|
const ClientUserSettingManager = require('../managers/ClientUserSettingManager');
|
|
19
|
+
const DeveloperPortalManager = require('../managers/DeveloperPortalManager');
|
|
16
20
|
const GuildManager = require('../managers/GuildManager');
|
|
17
|
-
const PresenceManager = require('../managers/PresenceManager');
|
|
18
21
|
const RelationshipManager = require('../managers/RelationshipManager');
|
|
22
|
+
const SessionManager = require('../managers/SessionManager');
|
|
19
23
|
const UserManager = require('../managers/UserManager');
|
|
20
|
-
const UserNoteManager = require('../managers/UserNoteManager');
|
|
21
24
|
const VoiceStateManager = require('../managers/VoiceStateManager');
|
|
22
25
|
const ShardClientUtil = require('../sharding/ShardClientUtil');
|
|
23
26
|
const ClientPresence = require('../structures/ClientPresence');
|
|
24
27
|
const GuildPreview = require('../structures/GuildPreview');
|
|
25
28
|
const GuildTemplate = require('../structures/GuildTemplate');
|
|
26
29
|
const Invite = require('../structures/Invite');
|
|
30
|
+
const { CustomStatus } = require('../structures/RichPresence');
|
|
27
31
|
const { Sticker } = require('../structures/Sticker');
|
|
28
32
|
const StickerPack = require('../structures/StickerPack');
|
|
29
33
|
const VoiceRegion = require('../structures/VoiceRegion');
|
|
30
34
|
const Webhook = require('../structures/Webhook');
|
|
31
35
|
const Widget = require('../structures/Widget');
|
|
32
|
-
const { Events, Status } = require('../util/Constants');
|
|
36
|
+
const { Events, InviteScopes, Status, captchaServices } = require('../util/Constants');
|
|
33
37
|
const DataResolver = require('../util/DataResolver');
|
|
34
38
|
const Intents = require('../util/Intents');
|
|
39
|
+
const Options = require('../util/Options');
|
|
35
40
|
const Permissions = require('../util/Permissions');
|
|
36
41
|
const DiscordAuthWebsocket = require('../util/RemoteAuth');
|
|
37
42
|
const Sweepers = require('../util/Sweepers');
|
|
43
|
+
const { lazy, testImportModule } = require('../util/Util');
|
|
44
|
+
const Message = lazy(() => require('../structures/Message').Message);
|
|
38
45
|
|
|
39
46
|
/**
|
|
40
47
|
* The main hub for interacting with the Discord API, and the starting point for any bot.
|
|
@@ -42,11 +49,44 @@ const Sweepers = require('../util/Sweepers');
|
|
|
42
49
|
*/
|
|
43
50
|
class Client extends BaseClient {
|
|
44
51
|
/**
|
|
45
|
-
* @param {ClientOptions}
|
|
52
|
+
* @param {ClientOptions} options Options for the client
|
|
46
53
|
*/
|
|
47
|
-
constructor(options) {
|
|
54
|
+
constructor(options = {}) {
|
|
48
55
|
super(options);
|
|
49
56
|
|
|
57
|
+
const data = require('node:worker_threads').workerData ?? process.env;
|
|
58
|
+
const defaults = Options.createDefault();
|
|
59
|
+
|
|
60
|
+
if (this.options.shards === defaults.shards) {
|
|
61
|
+
if ('SHARDS' in data) {
|
|
62
|
+
this.options.shards = JSON.parse(data.SHARDS);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (this.options.shardCount === defaults.shardCount) {
|
|
67
|
+
if ('SHARD_COUNT' in data) {
|
|
68
|
+
this.options.shardCount = Number(data.SHARD_COUNT);
|
|
69
|
+
} else if (Array.isArray(this.options.shards)) {
|
|
70
|
+
this.options.shardCount = this.options.shards.length;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const typeofShards = typeof this.options.shards;
|
|
75
|
+
|
|
76
|
+
if (typeofShards === 'undefined' && typeof this.options.shardCount === 'number') {
|
|
77
|
+
this.options.shards = Array.from({ length: this.options.shardCount }, (_, i) => i);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (typeofShards === 'number') this.options.shards = [this.options.shards];
|
|
81
|
+
|
|
82
|
+
if (Array.isArray(this.options.shards)) {
|
|
83
|
+
this.options.shards = [
|
|
84
|
+
...new Set(
|
|
85
|
+
this.options.shards.filter(item => !isNaN(item) && item >= 0 && item < Infinity && item === (item | 0)),
|
|
86
|
+
),
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
|
|
50
90
|
this._validateOptions();
|
|
51
91
|
|
|
52
92
|
/**
|
|
@@ -102,6 +142,17 @@ class Client extends BaseClient {
|
|
|
102
142
|
*/
|
|
103
143
|
this.users = new UserManager(this);
|
|
104
144
|
|
|
145
|
+
// Patch
|
|
146
|
+
/**
|
|
147
|
+
* All of the relationships {@link User}
|
|
148
|
+
* @type {RelationshipManager}
|
|
149
|
+
*/
|
|
150
|
+
this.relationships = new RelationshipManager(this);
|
|
151
|
+
/**
|
|
152
|
+
* All of the settings {@link Object}
|
|
153
|
+
* @type {ClientUserSettingManager}
|
|
154
|
+
*/
|
|
155
|
+
this.settings = new ClientUserSettingManager(this);
|
|
105
156
|
/**
|
|
106
157
|
* All of the guilds the client is currently handling, mapped by their ids -
|
|
107
158
|
* as long as sharding isn't being used, this will be *every* guild the bot is a member of
|
|
@@ -109,6 +160,18 @@ class Client extends BaseClient {
|
|
|
109
160
|
*/
|
|
110
161
|
this.guilds = new GuildManager(this);
|
|
111
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Manages the API methods
|
|
165
|
+
* @type {BillingManager}
|
|
166
|
+
*/
|
|
167
|
+
this.billing = new BillingManager(this);
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* All of the sessions of the client
|
|
171
|
+
* @type {SessionManager}
|
|
172
|
+
*/
|
|
173
|
+
this.sessions = new SessionManager(this);
|
|
174
|
+
|
|
112
175
|
/**
|
|
113
176
|
* All of the {@link Channel}s that the client is currently handling, mapped by their ids -
|
|
114
177
|
* as long as sharding isn't being used, this will be *every* channel in *every* guild the bot
|
|
@@ -124,6 +187,12 @@ class Client extends BaseClient {
|
|
|
124
187
|
*/
|
|
125
188
|
this.sweepers = new Sweepers(this, this.options.sweepers);
|
|
126
189
|
|
|
190
|
+
/**
|
|
191
|
+
* The developer portal manager of the client
|
|
192
|
+
* @type {DeveloperPortalManager}
|
|
193
|
+
*/
|
|
194
|
+
this.developerPortal = new DeveloperPortalManager(this);
|
|
195
|
+
|
|
127
196
|
/**
|
|
128
197
|
* The presence of the Client
|
|
129
198
|
* @private
|
|
@@ -131,36 +200,6 @@ class Client extends BaseClient {
|
|
|
131
200
|
*/
|
|
132
201
|
this.presence = new ClientPresence(this, this.options.presence);
|
|
133
202
|
|
|
134
|
-
/**
|
|
135
|
-
* A manager of the presences belonging to this client
|
|
136
|
-
* @type {PresenceManager}
|
|
137
|
-
*/
|
|
138
|
-
this.presences = new PresenceManager(this);
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* All of the note that have been cached at any point, mapped by their ids
|
|
142
|
-
* @type {UserManager}
|
|
143
|
-
*/
|
|
144
|
-
this.notes = new UserNoteManager(this);
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* All of the relationships {@link User}
|
|
148
|
-
* @type {RelationshipManager}
|
|
149
|
-
*/
|
|
150
|
-
this.relationships = new RelationshipManager(this);
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Manages the API methods
|
|
154
|
-
* @type {BillingManager}
|
|
155
|
-
*/
|
|
156
|
-
this.billing = new BillingManager(this);
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* All of the settings {@link Object}
|
|
160
|
-
* @type {ClientUserSettingManager}
|
|
161
|
-
*/
|
|
162
|
-
this.settings = new ClientUserSettingManager(this);
|
|
163
|
-
|
|
164
203
|
Object.defineProperty(this, 'token', { writable: true });
|
|
165
204
|
if (!this.token && 'DISCORD_TOKEN' in process.env) {
|
|
166
205
|
/**
|
|
@@ -174,12 +213,20 @@ class Client extends BaseClient {
|
|
|
174
213
|
this.token = null;
|
|
175
214
|
}
|
|
176
215
|
|
|
216
|
+
this._interactionCache = new Collection();
|
|
217
|
+
|
|
177
218
|
/**
|
|
178
219
|
* User that the client is logged in as
|
|
179
220
|
* @type {?ClientUser}
|
|
180
221
|
*/
|
|
181
222
|
this.user = null;
|
|
182
223
|
|
|
224
|
+
/**
|
|
225
|
+
* The application of this bot
|
|
226
|
+
* @type {?ClientApplication}
|
|
227
|
+
*/
|
|
228
|
+
this.application = null;
|
|
229
|
+
|
|
183
230
|
/**
|
|
184
231
|
* Time at which the client was last regarded as being in the `READY` state
|
|
185
232
|
* (each time the client disconnects and successfully reconnects, this will be overwritten)
|
|
@@ -187,6 +234,14 @@ class Client extends BaseClient {
|
|
|
187
234
|
*/
|
|
188
235
|
this.readyAt = null;
|
|
189
236
|
|
|
237
|
+
/**
|
|
238
|
+
* Password cache
|
|
239
|
+
* @type {?string}
|
|
240
|
+
*/
|
|
241
|
+
this.password = this.options.password;
|
|
242
|
+
|
|
243
|
+
this.session_id = null;
|
|
244
|
+
|
|
190
245
|
if (this.options.messageSweepInterval > 0) {
|
|
191
246
|
process.emitWarning(
|
|
192
247
|
'The message sweeping client options are deprecated, use the global sweepers instead.',
|
|
@@ -199,6 +254,15 @@ class Client extends BaseClient {
|
|
|
199
254
|
}
|
|
200
255
|
}
|
|
201
256
|
|
|
257
|
+
/**
|
|
258
|
+
* Session ID
|
|
259
|
+
* @type {?string}
|
|
260
|
+
* @readonly
|
|
261
|
+
*/
|
|
262
|
+
get sessionId() {
|
|
263
|
+
return this.session_id;
|
|
264
|
+
}
|
|
265
|
+
|
|
202
266
|
/**
|
|
203
267
|
* All custom emojis that the client has access to, mapped by their ids
|
|
204
268
|
* @type {BaseGuildEmojiManager}
|
|
@@ -230,6 +294,19 @@ class Client extends BaseClient {
|
|
|
230
294
|
return this.readyAt ? Date.now() - this.readyAt : null;
|
|
231
295
|
}
|
|
232
296
|
|
|
297
|
+
/**
|
|
298
|
+
* @external VoiceConnection
|
|
299
|
+
* @see {@link https://discord.js.org/#/docs/voice/main/class/VoiceConnection}
|
|
300
|
+
*/
|
|
301
|
+
/**
|
|
302
|
+
* Get connection to current call
|
|
303
|
+
* @type {?VoiceConnection}
|
|
304
|
+
* @readonly
|
|
305
|
+
*/
|
|
306
|
+
get callVoice() {
|
|
307
|
+
return getVoiceConnection(null);
|
|
308
|
+
}
|
|
309
|
+
|
|
233
310
|
/**
|
|
234
311
|
* Logs the client in, establishing a WebSocket connection to Discord.
|
|
235
312
|
* @param {string} [token=this.token] Token of the account to log in with
|
|
@@ -246,7 +323,8 @@ class Client extends BaseClient {
|
|
|
246
323
|
Logging on with a user token is unfortunately against the Discord
|
|
247
324
|
\`Terms of Service\` <https://support.discord.com/hc/en-us/articles/115002192352>
|
|
248
325
|
and doing so might potentially get your account banned.
|
|
249
|
-
Use this at your own risk
|
|
326
|
+
Use this at your own risk.
|
|
327
|
+
`,
|
|
250
328
|
);
|
|
251
329
|
this.emit(
|
|
252
330
|
Events.DEBUG,
|
|
@@ -271,10 +349,174 @@ class Client extends BaseClient {
|
|
|
271
349
|
}
|
|
272
350
|
}
|
|
273
351
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
352
|
+
/**
|
|
353
|
+
* Login Discord with Username and Password
|
|
354
|
+
* @param {string} username Email or Phone Number
|
|
355
|
+
* @param {?string} password Password
|
|
356
|
+
* @param {?string} mfaCode 2FA Code / Backup Code
|
|
357
|
+
* @returns {Promise<string>}
|
|
358
|
+
*/
|
|
359
|
+
async normalLogin(username, password = this.password, mfaCode) {
|
|
360
|
+
if (!username || !password || typeof username !== 'string' || typeof password !== 'string') {
|
|
361
|
+
throw new Error('NORMAL_LOGIN');
|
|
362
|
+
}
|
|
363
|
+
this.emit(
|
|
364
|
+
Events.DEBUG,
|
|
365
|
+
`Connecting to Discord with:
|
|
366
|
+
username: ${username}
|
|
367
|
+
password: ${password.replace(/./g, '*')}`,
|
|
368
|
+
);
|
|
369
|
+
const data = await this.api.auth.login.post({
|
|
370
|
+
data: {
|
|
371
|
+
login: username,
|
|
372
|
+
password: password,
|
|
373
|
+
undelete: false,
|
|
374
|
+
captcha_key: null,
|
|
375
|
+
login_source: null,
|
|
376
|
+
gift_code_sku_id: null,
|
|
377
|
+
},
|
|
378
|
+
auth: false,
|
|
379
|
+
});
|
|
380
|
+
this.password = password;
|
|
381
|
+
if (!data.token && data.ticket && data.mfa) {
|
|
382
|
+
this.emit(Events.DEBUG, `Using 2FA Code: ${mfaCode}`);
|
|
383
|
+
const normal2fa = /(\d{6})/g;
|
|
384
|
+
const backupCode = /([a-z0-9]{4})-([a-z0-9]{4})/g;
|
|
385
|
+
if (!mfaCode || typeof mfaCode !== 'string') {
|
|
386
|
+
throw new Error('LOGIN_FAILED_2FA');
|
|
387
|
+
}
|
|
388
|
+
if (normal2fa.test(mfaCode) || backupCode.test(mfaCode)) {
|
|
389
|
+
const data2 = await this.api.auth.mfa.totp.post({
|
|
390
|
+
data: {
|
|
391
|
+
code: mfaCode,
|
|
392
|
+
ticket: data.ticket,
|
|
393
|
+
login_source: null,
|
|
394
|
+
gift_code_sku_id: null,
|
|
395
|
+
},
|
|
396
|
+
auth: false,
|
|
397
|
+
});
|
|
398
|
+
return this.login(data2.token);
|
|
399
|
+
} else {
|
|
400
|
+
throw new Error('LOGIN_FAILED_2FA');
|
|
401
|
+
}
|
|
402
|
+
} else if (data.token) {
|
|
403
|
+
return this.login(data.token);
|
|
404
|
+
} else {
|
|
405
|
+
throw new Error('LOGIN_FAILED_UNKNOWN');
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Switch the user
|
|
411
|
+
* @param {string} token User Token
|
|
412
|
+
* @returns {Promise<string>}
|
|
413
|
+
*/
|
|
414
|
+
switchUser(token) {
|
|
415
|
+
this._clearCache(this.emojis.cache);
|
|
416
|
+
this._clearCache(this.guilds.cache);
|
|
417
|
+
this._clearCache(this.channels.cache);
|
|
418
|
+
this._clearCache(this.users.cache);
|
|
419
|
+
this._clearCache(this.relationships.cache);
|
|
420
|
+
this._clearCache(this.sessions.cache);
|
|
421
|
+
this._clearCache(this.voiceStates.cache);
|
|
422
|
+
this.ws.status = Status.IDLE;
|
|
423
|
+
return this.login(token);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Sign in with the QR code on your phone.
|
|
428
|
+
* @param {DiscordAuthWebsocketOptions} options Options
|
|
429
|
+
* @returns {DiscordAuthWebsocket}
|
|
430
|
+
* @example
|
|
431
|
+
* client.QRLogin();
|
|
432
|
+
*/
|
|
433
|
+
QRLogin(options = {}) {
|
|
434
|
+
const QR = new DiscordAuthWebsocket({ ...options, autoLogin: true });
|
|
435
|
+
this.emit(Events.DEBUG, `Preparing to connect to the gateway (QR Login)`, QR);
|
|
436
|
+
return QR.connect(this);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Implement `remoteAuth`, like using your phone to scan a QR code
|
|
441
|
+
* @param {string} url URL from QR code
|
|
442
|
+
* @returns {Promise<void>}
|
|
443
|
+
*/
|
|
444
|
+
async remoteAuth(url) {
|
|
445
|
+
if (!this.isReady()) throw new Error('CLIENT_NOT_READY', 'Remote Auth');
|
|
446
|
+
// Step 1: Parse URL
|
|
447
|
+
url = new URL(url);
|
|
448
|
+
if (
|
|
449
|
+
!['discordapp.com', 'discord.com'].includes(url.hostname) ||
|
|
450
|
+
!url.pathname.startsWith('/ra/') ||
|
|
451
|
+
url.pathname.length <= 4
|
|
452
|
+
) {
|
|
453
|
+
throw new Error('INVALID_REMOTE_AUTH_URL');
|
|
454
|
+
}
|
|
455
|
+
const hash = url.pathname.replace('/ra/', '');
|
|
456
|
+
// Step 2: Post > Get handshake_token
|
|
457
|
+
const res = await this.api.users['@me']['remote-auth'].post({
|
|
458
|
+
data: {
|
|
459
|
+
fingerprint: hash,
|
|
460
|
+
},
|
|
461
|
+
});
|
|
462
|
+
const handshake_token = res.handshake_token;
|
|
463
|
+
// Step 3: Post
|
|
464
|
+
return this.api.users['@me']['remote-auth'].finish.post({ data: { handshake_token, temporary_token: false } });
|
|
465
|
+
// Cancel
|
|
466
|
+
// this.api.users['@me']['remote-auth'].cancel.post({ data: { handshake_token } });
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Create a new token based on the current token
|
|
471
|
+
* @returns {Promise<string>} New Discord Token
|
|
472
|
+
*/
|
|
473
|
+
createToken() {
|
|
474
|
+
return new Promise(resolve => {
|
|
475
|
+
// Step 1: Create DiscordAuthWebsocket
|
|
476
|
+
const QR = new DiscordAuthWebsocket({
|
|
477
|
+
hiddenLog: true,
|
|
478
|
+
generateQR: false,
|
|
479
|
+
autoLogin: false,
|
|
480
|
+
debug: false,
|
|
481
|
+
failIfError: false,
|
|
482
|
+
userAgent: this.options.http.headers['User-Agent'],
|
|
483
|
+
wsProperties: this.options.ws.properties,
|
|
484
|
+
});
|
|
485
|
+
// Step 2: Add event
|
|
486
|
+
QR.once('ready', async (_, url) => {
|
|
487
|
+
await this.remoteAuth(url, true);
|
|
488
|
+
}).once('finish', (user, token) => {
|
|
489
|
+
resolve(token);
|
|
490
|
+
});
|
|
491
|
+
// Step 3: Connect
|
|
492
|
+
QR.connect();
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Emitted whenever clientOptions.checkUpdate = false
|
|
498
|
+
* @event Client#update
|
|
499
|
+
* @param {string} oldVersion Current version
|
|
500
|
+
* @param {string} newVersion Latest version
|
|
501
|
+
*/
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Check for updates
|
|
505
|
+
* @returns {Promise<Client>}
|
|
506
|
+
*/
|
|
507
|
+
async checkUpdate() {
|
|
508
|
+
const res_ = await (
|
|
509
|
+
await fetch(`https://registry.npmjs.com/${encodeURIComponent('djs-selfbot-v13')}`)
|
|
510
|
+
).json();
|
|
511
|
+
try {
|
|
512
|
+
const latest_tag = res_['dist-tags'].latest;
|
|
513
|
+
this.emit('update', Discord.version, latest_tag);
|
|
514
|
+
this.emit('debug', `${chalk.greenBright('[OK]')} Check Update success`);
|
|
515
|
+
} catch {
|
|
516
|
+
this.emit('debug', `${chalk.redBright('[Fail]')} Check Update error`);
|
|
517
|
+
this.emit('update', Discord.version, false);
|
|
518
|
+
}
|
|
519
|
+
return this;
|
|
278
520
|
}
|
|
279
521
|
|
|
280
522
|
/**
|
|
@@ -301,6 +543,7 @@ class Client extends BaseClient {
|
|
|
301
543
|
this.sweepers.destroy();
|
|
302
544
|
this.ws.destroy();
|
|
303
545
|
this.token = null;
|
|
546
|
+
this.password = null;
|
|
304
547
|
}
|
|
305
548
|
|
|
306
549
|
/**
|
|
@@ -314,7 +557,7 @@ class Client extends BaseClient {
|
|
|
314
557
|
voip_provider: null,
|
|
315
558
|
},
|
|
316
559
|
});
|
|
317
|
-
|
|
560
|
+
await this.destroy();
|
|
318
561
|
}
|
|
319
562
|
|
|
320
563
|
/**
|
|
@@ -342,6 +585,68 @@ class Client extends BaseClient {
|
|
|
342
585
|
return new Invite(this, data);
|
|
343
586
|
}
|
|
344
587
|
|
|
588
|
+
/**
|
|
589
|
+
* Join this Guild using this invite (fast)
|
|
590
|
+
* @param {InviteResolvable} invite Invite code or URL
|
|
591
|
+
* @returns {Promise<void>}
|
|
592
|
+
* @example
|
|
593
|
+
* await client.acceptInvite('https://discord.gg/genshinimpact')
|
|
594
|
+
*/
|
|
595
|
+
async acceptInvite(invite) {
|
|
596
|
+
const code = DataResolver.resolveInviteCode(invite);
|
|
597
|
+
if (!code) throw new Error('INVITE_RESOLVE_CODE');
|
|
598
|
+
if (invite instanceof Invite) {
|
|
599
|
+
await invite.acceptInvite();
|
|
600
|
+
} else {
|
|
601
|
+
await this.api.invites(code).post({
|
|
602
|
+
headers: {
|
|
603
|
+
'X-Context-Properties': 'eyJsb2NhdGlvbiI6Ik1hcmtkb3duIExpbmsifQ==', // Markdown Link
|
|
604
|
+
},
|
|
605
|
+
data: {
|
|
606
|
+
session_id: this.session_id,
|
|
607
|
+
},
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Automatically Redeem Nitro from raw message.
|
|
614
|
+
* @param {Message} message Discord Message
|
|
615
|
+
* @private
|
|
616
|
+
*/
|
|
617
|
+
async autoRedeemNitro(message) {
|
|
618
|
+
if (!(message instanceof Message())) return;
|
|
619
|
+
if (!message.content) return;
|
|
620
|
+
const allLinks =
|
|
621
|
+
message.content.match(/(discord.gift|discord.com|discordapp.com\/gifts)\/(\w{16,25})/gm) ||
|
|
622
|
+
message.content.match(/(discord\.gift\/|discord\.com\/gifts\/|discordapp\.com\/gifts\/)(\w+)/gm);
|
|
623
|
+
if (!allLinks) return;
|
|
624
|
+
for (const link of allLinks) {
|
|
625
|
+
await this.redeemNitro(link, message.channel);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
/**
|
|
630
|
+
* Redeem nitro from code or url.
|
|
631
|
+
* @param {string} nitro Nitro url or code
|
|
632
|
+
* @param {TextChannelResolvable} channel Channel that the code was sent in
|
|
633
|
+
* @param {Snowflake} [paymentSourceId] Payment source id
|
|
634
|
+
* @returns {Promise<any>}
|
|
635
|
+
*/
|
|
636
|
+
redeemNitro(nitro, channel, paymentSourceId) {
|
|
637
|
+
if (typeof nitro !== 'string') throw new Error('INVALID_NITRO');
|
|
638
|
+
const nitroCode =
|
|
639
|
+
nitro.match(/(discord.gift|discord.com|discordapp.com\/gifts)\/(\w{16,25})/) ||
|
|
640
|
+
nitro.match(/(discord\.gift\/|discord\.com\/gifts\/|discordapp\.com\/gifts\/)(\w+)/);
|
|
641
|
+
if (!nitroCode) return false;
|
|
642
|
+
const code = nitroCode[2];
|
|
643
|
+
channel = this.channels.resolveId(channel);
|
|
644
|
+
return this.api.entitlements['gift-codes'](code).redeem.post({
|
|
645
|
+
auth: true,
|
|
646
|
+
data: { channel_id: channel || null, payment_source_id: paymentSourceId || null },
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
|
|
345
650
|
/**
|
|
346
651
|
* Obtains a template from Discord.
|
|
347
652
|
* @param {GuildTemplateResolvable} template Template code or URL
|
|
@@ -432,6 +737,16 @@ class Client extends BaseClient {
|
|
|
432
737
|
}
|
|
433
738
|
}
|
|
434
739
|
|
|
740
|
+
/**
|
|
741
|
+
* Clear a cache
|
|
742
|
+
* @param {Collection} cache The cache to clear
|
|
743
|
+
* @returns {number} The number of removed entries
|
|
744
|
+
* @private
|
|
745
|
+
*/
|
|
746
|
+
_clearCache(cache) {
|
|
747
|
+
return cache.sweep(() => true);
|
|
748
|
+
}
|
|
749
|
+
|
|
435
750
|
/**
|
|
436
751
|
* Sweeps all text-based channels' messages and removes the ones older than the max message lifetime.
|
|
437
752
|
* If the message has been edited, the time of the edit is used rather than the time of the original message.
|
|
@@ -492,13 +807,65 @@ class Client extends BaseClient {
|
|
|
492
807
|
*/
|
|
493
808
|
|
|
494
809
|
/**
|
|
495
|
-
*
|
|
496
|
-
* @param {
|
|
497
|
-
*
|
|
498
|
-
* @
|
|
810
|
+
* Generates a link that can be used to invite the bot to a guild.
|
|
811
|
+
* @param {InviteGenerationOptions} [options={}] Options for the invite
|
|
812
|
+
* @returns {string}
|
|
813
|
+
* @example
|
|
814
|
+
* const link = client.generateInvite({
|
|
815
|
+
* scopes: ['applications.commands'],
|
|
816
|
+
* });
|
|
817
|
+
* console.log(`Generated application invite link: ${link}`);
|
|
818
|
+
* @example
|
|
819
|
+
* const link = client.generateInvite({
|
|
820
|
+
* permissions: [
|
|
821
|
+
* Permissions.FLAGS.SEND_MESSAGES,
|
|
822
|
+
* Permissions.FLAGS.MANAGE_GUILD,
|
|
823
|
+
* Permissions.FLAGS.MENTION_EVERYONE,
|
|
824
|
+
* ],
|
|
825
|
+
* scopes: ['bot'],
|
|
826
|
+
* });
|
|
827
|
+
* console.log(`Generated bot invite link: ${link}`);
|
|
499
828
|
*/
|
|
500
|
-
|
|
501
|
-
|
|
829
|
+
generateInvite(options = {}) {
|
|
830
|
+
if (typeof options !== 'object') throw new TypeError('INVALID_TYPE', 'options', 'object', true);
|
|
831
|
+
if (!this.application) throw new Error('CLIENT_NOT_READY', 'generate an invite link');
|
|
832
|
+
|
|
833
|
+
const query = new URLSearchParams({
|
|
834
|
+
client_id: this.application.id,
|
|
835
|
+
});
|
|
836
|
+
|
|
837
|
+
const { scopes } = options;
|
|
838
|
+
if (typeof scopes === 'undefined') {
|
|
839
|
+
throw new TypeError('INVITE_MISSING_SCOPES');
|
|
840
|
+
}
|
|
841
|
+
if (!Array.isArray(scopes)) {
|
|
842
|
+
throw new TypeError('INVALID_TYPE', 'scopes', 'Array of Invite Scopes', true);
|
|
843
|
+
}
|
|
844
|
+
if (!scopes.some(scope => ['bot', 'applications.commands'].includes(scope))) {
|
|
845
|
+
throw new TypeError('INVITE_MISSING_SCOPES');
|
|
846
|
+
}
|
|
847
|
+
const invalidScope = scopes.find(scope => !InviteScopes.includes(scope));
|
|
848
|
+
if (invalidScope) {
|
|
849
|
+
throw new TypeError('INVALID_ELEMENT', 'Array', 'scopes', invalidScope);
|
|
850
|
+
}
|
|
851
|
+
query.set('scope', scopes.join(' '));
|
|
852
|
+
|
|
853
|
+
if (options.permissions) {
|
|
854
|
+
const permissions = Permissions.resolve(options.permissions);
|
|
855
|
+
if (permissions) query.set('permissions', permissions);
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
if (options.disableGuildSelect) {
|
|
859
|
+
query.set('disable_guild_select', true);
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
if (options.guild) {
|
|
863
|
+
const guildId = this.guilds.resolveId(options.guild);
|
|
864
|
+
if (!guildId) throw new TypeError('INVALID_TYPE', 'options.guild', 'GuildResolvable');
|
|
865
|
+
query.set('guild_id', guildId);
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
return `${this.options.http.api}${this.api.oauth2.authorize}?${query}`;
|
|
502
869
|
}
|
|
503
870
|
|
|
504
871
|
toJSON() {
|
|
@@ -508,137 +875,43 @@ class Client extends BaseClient {
|
|
|
508
875
|
}
|
|
509
876
|
|
|
510
877
|
/**
|
|
511
|
-
*
|
|
512
|
-
*
|
|
878
|
+
* Calls {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval} on a script
|
|
879
|
+
* with the client as `this`.
|
|
880
|
+
* @param {string} script Script to eval
|
|
881
|
+
* @returns {*}
|
|
882
|
+
* @private
|
|
513
883
|
*/
|
|
514
|
-
|
|
515
|
-
return
|
|
884
|
+
_eval(script) {
|
|
885
|
+
return eval(script);
|
|
516
886
|
}
|
|
517
887
|
|
|
518
888
|
/**
|
|
519
|
-
*
|
|
520
|
-
* @
|
|
521
|
-
* @
|
|
522
|
-
* @property {boolean} [bypassVerify=true] Whether to bypass rule screening
|
|
523
|
-
*/
|
|
524
|
-
|
|
525
|
-
/**
|
|
526
|
-
* Join this Guild / GroupDMChannel using this invite
|
|
527
|
-
* @param {InviteResolvable} invite Invite code or URL
|
|
528
|
-
* @param {AcceptInviteOptions} [options={ bypassOnboarding: true, bypassVerify: true }] Options
|
|
529
|
-
* @returns {Promise<Guild|DMChannel|GroupDMChannel>}
|
|
530
|
-
* @example
|
|
531
|
-
* await client.acceptInvite('https://discord.gg/genshinimpact', { bypassOnboarding: true, bypassVerify: true })
|
|
889
|
+
* Sets the client's presence. (Sync Setting).
|
|
890
|
+
* @param {Client} client Discord Client
|
|
891
|
+
* @private
|
|
532
892
|
*/
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
if (!
|
|
536
|
-
const
|
|
537
|
-
if (
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
location_guild_id: i.guild?.id,
|
|
543
|
-
location_channel_id: i.channelId,
|
|
544
|
-
location_channel_type: typeof i.channel.type == 'number' ? i.channel.type : ChannelTypes[i.channel.type],
|
|
545
|
-
}
|
|
546
|
-
*/
|
|
547
|
-
const data = await this.api.invites(code).post({
|
|
548
|
-
DiscordContext: { location: 'Markdown Link' },
|
|
549
|
-
data: {
|
|
550
|
-
session_id: this.sessionId,
|
|
551
|
-
},
|
|
552
|
-
});
|
|
553
|
-
this.emit(Events.DEBUG, `[Invite > Guild ${i.guild?.id}] Joined`);
|
|
554
|
-
// Guild
|
|
555
|
-
if (i.guild?.id) {
|
|
556
|
-
const guild = this.guilds.cache.get(i.guild?.id);
|
|
557
|
-
if (i.flags.has('GUEST')) {
|
|
558
|
-
this.emit(Events.DEBUG, `[Invite > Guild ${i.guild?.id}] Guest invite`);
|
|
559
|
-
return guild;
|
|
560
|
-
}
|
|
561
|
-
if (options.bypassOnboarding) {
|
|
562
|
-
const onboardingData = await this.api.guilds[i.guild?.id].onboarding.get();
|
|
563
|
-
// Onboarding
|
|
564
|
-
if (onboardingData.enabled) {
|
|
565
|
-
const prompts = onboardingData.prompts.filter(o => o.in_onboarding);
|
|
566
|
-
if (prompts.length) {
|
|
567
|
-
const onboarding_prompts_seen = {};
|
|
568
|
-
const onboarding_responses = [];
|
|
569
|
-
const onboarding_responses_seen = {};
|
|
570
|
-
|
|
571
|
-
const currentDate = Date.now();
|
|
572
|
-
|
|
573
|
-
prompts.forEach(prompt => {
|
|
574
|
-
onboarding_prompts_seen[prompt.id] = currentDate;
|
|
575
|
-
if (prompt.required) onboarding_responses.push(prompt.options[0].id);
|
|
576
|
-
prompt.options.forEach(option => {
|
|
577
|
-
onboarding_responses_seen[option.id] = currentDate;
|
|
578
|
-
});
|
|
579
|
-
});
|
|
580
|
-
|
|
581
|
-
await this.api.guilds[i.guild?.id]['onboarding-responses'].post({
|
|
582
|
-
data: {
|
|
583
|
-
onboarding_prompts_seen,
|
|
584
|
-
onboarding_responses,
|
|
585
|
-
onboarding_responses_seen,
|
|
586
|
-
},
|
|
587
|
-
});
|
|
588
|
-
this.emit(Events.DEBUG, `[Invite > Guild ${i.guild?.id}] Bypassed onboarding`);
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
// Read rule
|
|
593
|
-
if (data.show_verification_form && options.bypassVerify) {
|
|
594
|
-
// Check Guild
|
|
595
|
-
if (i.guild.verificationLevel == 'VERY_HIGH' && !this.user.phone) {
|
|
596
|
-
this.emit(Events.DEBUG, `[Invite > Guild ${i.guild?.id}] Cannot bypass verify (Phone required)`);
|
|
597
|
-
return this.guilds.cache.get(i.guild?.id);
|
|
598
|
-
}
|
|
599
|
-
if (i.guild.verificationLevel !== 'NONE' && !this.user.email) {
|
|
600
|
-
this.emit(Events.DEBUG, `[Invite > Guild ${i.guild?.id}] Cannot bypass verify (Email required)`);
|
|
601
|
-
return this.guilds.cache.get(i.guild?.id);
|
|
602
|
-
}
|
|
603
|
-
const getForm = await this.api
|
|
604
|
-
.guilds(i.guild?.id)
|
|
605
|
-
['member-verification'].get({ query: { with_guild: false, invite_code: this.code } })
|
|
606
|
-
.catch(() => {});
|
|
607
|
-
if (getForm) {
|
|
608
|
-
const form = Object.assign(getForm.form_fields[0], { response: true });
|
|
609
|
-
await this.api
|
|
610
|
-
.guilds(i.guild?.id)
|
|
611
|
-
.requests['@me'].put({ data: { form_fields: [form], version: getForm.version } });
|
|
612
|
-
this.emit(Events.DEBUG, `[Invite > Guild ${i.guild?.id}] Bypassed verify`);
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
return guild;
|
|
893
|
+
customStatusAuto(client) {
|
|
894
|
+
client = client ?? this;
|
|
895
|
+
if (!client.user) return;
|
|
896
|
+
const custom_status = new CustomStatus();
|
|
897
|
+
if (!client.settings.rawSetting.custom_status?.text && !client.settings.rawSetting.custom_status?.emoji_name) {
|
|
898
|
+
client.user.setPresence({
|
|
899
|
+
activities: this.presence.activities.filter(a => a.type !== 'CUSTOM'),
|
|
900
|
+
status: client.settings.rawSetting.status ?? 'invisible',
|
|
901
|
+
});
|
|
616
902
|
} else {
|
|
617
|
-
|
|
903
|
+
custom_status.setEmoji({
|
|
904
|
+
name: client.settings.rawSetting.custom_status?.emoji_name,
|
|
905
|
+
id: client.settings.rawSetting.custom_status?.emoji_id,
|
|
906
|
+
});
|
|
907
|
+
custom_status.setState(client.settings.rawSetting.custom_status?.text);
|
|
908
|
+
client.user.setPresence({
|
|
909
|
+
activities: [custom_status.toJSON(), ...this.presence.activities.filter(a => a.type !== 'CUSTOM')],
|
|
910
|
+
status: client.settings.rawSetting.status ?? 'invisible',
|
|
911
|
+
});
|
|
618
912
|
}
|
|
619
913
|
}
|
|
620
914
|
|
|
621
|
-
/**
|
|
622
|
-
* Redeem nitro from code or url.
|
|
623
|
-
* @param {string} nitro Nitro url or code
|
|
624
|
-
* @param {TextChannelResolvable} [channel] Channel that the code was sent in
|
|
625
|
-
* @param {Snowflake} [paymentSourceId] Payment source id
|
|
626
|
-
* @returns {Promise<any>}
|
|
627
|
-
*/
|
|
628
|
-
redeemNitro(nitro, channel, paymentSourceId) {
|
|
629
|
-
if (typeof nitro !== 'string') throw new Error('INVALID_NITRO');
|
|
630
|
-
const nitroCode =
|
|
631
|
-
nitro.match(/(discord.gift|discord.com|discordapp.com\/gifts)\/(\w{16,25})/) ||
|
|
632
|
-
nitro.match(/(discord\.gift\/|discord\.com\/gifts\/|discordapp\.com\/gifts\/)(\w+)/);
|
|
633
|
-
if (!nitroCode) return false;
|
|
634
|
-
const code = nitroCode[2];
|
|
635
|
-
channel = this.channels.resolveId(channel);
|
|
636
|
-
return this.api.entitlements['gift-codes'](code).redeem.post({
|
|
637
|
-
auth: true,
|
|
638
|
-
data: { channel_id: channel || null, payment_source_id: paymentSourceId || null },
|
|
639
|
-
});
|
|
640
|
-
}
|
|
641
|
-
|
|
642
915
|
/**
|
|
643
916
|
* @typedef {Object} OAuth2AuthorizeOptions
|
|
644
917
|
* @property {string} [guild_id] Guild ID
|
|
@@ -652,7 +925,7 @@ class Client extends BaseClient {
|
|
|
652
925
|
* Authorize an application.
|
|
653
926
|
* @param {string} url Discord Auth URL
|
|
654
927
|
* @param {OAuth2AuthorizeOptions} options Oauth2 options
|
|
655
|
-
* @returns {Promise<
|
|
928
|
+
* @returns {Promise<Object>}
|
|
656
929
|
* @example
|
|
657
930
|
* client.authorizeURL(`https://discord.com/api/oauth2/authorize?client_id=botID&permissions=8&scope=applications.commands%20bot`, {
|
|
658
931
|
guild_id: "guildID",
|
|
@@ -680,14 +953,12 @@ class Client extends BaseClient {
|
|
|
680
953
|
}
|
|
681
954
|
|
|
682
955
|
/**
|
|
683
|
-
*
|
|
684
|
-
*
|
|
685
|
-
* @
|
|
686
|
-
* @returns {*}
|
|
687
|
-
* @private
|
|
956
|
+
* Makes waiting time for Client.
|
|
957
|
+
* @param {number} miliseconds Sleeping time as milliseconds.
|
|
958
|
+
* @returns {Promise<void> | null}
|
|
688
959
|
*/
|
|
689
|
-
|
|
690
|
-
return
|
|
960
|
+
sleep(miliseconds) {
|
|
961
|
+
return typeof miliseconds === 'number' ? new Promise(r => setTimeout(r, miliseconds).unref()) : null;
|
|
691
962
|
}
|
|
692
963
|
|
|
693
964
|
/**
|
|
@@ -696,6 +967,88 @@ class Client extends BaseClient {
|
|
|
696
967
|
* @private
|
|
697
968
|
*/
|
|
698
969
|
_validateOptions(options = this.options) {
|
|
970
|
+
if (typeof options.intents === 'undefined') {
|
|
971
|
+
throw new TypeError('CLIENT_MISSING_INTENTS');
|
|
972
|
+
} else {
|
|
973
|
+
options.intents = Intents.resolve(options.intents);
|
|
974
|
+
}
|
|
975
|
+
if (options && typeof options.checkUpdate !== 'boolean') {
|
|
976
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'checkUpdate', 'a boolean');
|
|
977
|
+
}
|
|
978
|
+
if (options && typeof options.syncStatus !== 'boolean') {
|
|
979
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'syncStatus', 'a boolean');
|
|
980
|
+
}
|
|
981
|
+
if (options && typeof options.autoRedeemNitro !== 'boolean') {
|
|
982
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'autoRedeemNitro', 'a boolean');
|
|
983
|
+
}
|
|
984
|
+
if (options && options.captchaService && !captchaServices.includes(options.captchaService)) {
|
|
985
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'captchaService', captchaServices.join(', '));
|
|
986
|
+
}
|
|
987
|
+
// Parse captcha key
|
|
988
|
+
if (options && captchaServices.includes(options.captchaService) && options.captchaService !== 'custom') {
|
|
989
|
+
if (typeof options.captchaKey !== 'string') {
|
|
990
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'captchaKey', 'a string');
|
|
991
|
+
}
|
|
992
|
+
switch (options.captchaService) {
|
|
993
|
+
case '2captcha':
|
|
994
|
+
if (options.captchaKey.length !== 32) {
|
|
995
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'captchaKey', 'a 32 character string');
|
|
996
|
+
}
|
|
997
|
+
break;
|
|
998
|
+
case 'capmonster':
|
|
999
|
+
if (options.captchaKey.length !== 32) {
|
|
1000
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'captchaKey', 'a 32 character string');
|
|
1001
|
+
}
|
|
1002
|
+
break;
|
|
1003
|
+
case 'nopecha': {
|
|
1004
|
+
if (options.captchaKey.length !== 16) {
|
|
1005
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'captchaKey', 'a 16 character string');
|
|
1006
|
+
}
|
|
1007
|
+
break;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
if (typeof options.captchaRetryLimit !== 'number' || isNaN(options.captchaRetryLimit)) {
|
|
1012
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'captchaRetryLimit', 'a number');
|
|
1013
|
+
}
|
|
1014
|
+
if (options && typeof options.captchaSolver !== 'function') {
|
|
1015
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'captchaSolver', 'a function');
|
|
1016
|
+
}
|
|
1017
|
+
if (options && typeof options.captchaWithProxy !== 'boolean') {
|
|
1018
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'captchaWithProxy', 'a boolean');
|
|
1019
|
+
}
|
|
1020
|
+
if (options && typeof options.DMSync !== 'boolean') {
|
|
1021
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'DMSync', 'a boolean');
|
|
1022
|
+
}
|
|
1023
|
+
if (options && typeof options.patchVoice !== 'boolean') {
|
|
1024
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'patchVoice', 'a boolean');
|
|
1025
|
+
}
|
|
1026
|
+
if (options && options.password && typeof options.password !== 'string') {
|
|
1027
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'password', 'a string');
|
|
1028
|
+
}
|
|
1029
|
+
if (options && options.usingNewAttachmentAPI && typeof options.usingNewAttachmentAPI !== 'boolean') {
|
|
1030
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'usingNewAttachmentAPI', 'a boolean');
|
|
1031
|
+
}
|
|
1032
|
+
if (options && options.interactionTimeout && typeof options.interactionTimeout !== 'number') {
|
|
1033
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'interactionTimeout', 'a number');
|
|
1034
|
+
}
|
|
1035
|
+
if (options && typeof options.proxy !== 'string') {
|
|
1036
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'proxy', 'a string');
|
|
1037
|
+
} else if (
|
|
1038
|
+
options &&
|
|
1039
|
+
options.proxy &&
|
|
1040
|
+
typeof options.proxy === 'string' &&
|
|
1041
|
+
testImportModule('proxy-agent') === false
|
|
1042
|
+
) {
|
|
1043
|
+
throw new Error('MISSING_MODULE', 'proxy-agent', 'npm install proxy-agent');
|
|
1044
|
+
}
|
|
1045
|
+
if (typeof options.shardCount !== 'number' || isNaN(options.shardCount) || options.shardCount < 1) {
|
|
1046
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'shardCount', 'a number greater than or equal to 1');
|
|
1047
|
+
}
|
|
1048
|
+
if (options.shards && !(options.shards === 'auto' || Array.isArray(options.shards))) {
|
|
1049
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'shards', "'auto', a number or array of numbers");
|
|
1050
|
+
}
|
|
1051
|
+
if (options.shards && !options.shards.length) throw new RangeError('CLIENT_INVALID_PROVIDED_SHARDS');
|
|
699
1052
|
if (typeof options.makeCache !== 'function') {
|
|
700
1053
|
throw new TypeError('CLIENT_INVALID_OPTION', 'makeCache', 'a function');
|
|
701
1054
|
}
|
|
@@ -714,12 +1067,12 @@ class Client extends BaseClient {
|
|
|
714
1067
|
if (!Array.isArray(options.partials)) {
|
|
715
1068
|
throw new TypeError('CLIENT_INVALID_OPTION', 'partials', 'an Array');
|
|
716
1069
|
}
|
|
717
|
-
if (typeof options.DMChannelVoiceStatusSync !== 'number' || isNaN(options.DMChannelVoiceStatusSync)) {
|
|
718
|
-
throw new TypeError('CLIENT_INVALID_OPTION', 'DMChannelVoiceStatusSync', 'a number');
|
|
719
|
-
}
|
|
720
1070
|
if (typeof options.waitGuildTimeout !== 'number' || isNaN(options.waitGuildTimeout)) {
|
|
721
1071
|
throw new TypeError('CLIENT_INVALID_OPTION', 'waitGuildTimeout', 'a number');
|
|
722
1072
|
}
|
|
1073
|
+
if (typeof options.messageCreateEventGuildTimeout !== 'number' || isNaN(options.messageCreateEventGuildTimeout)) {
|
|
1074
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'messageCreateEventGuildTimeout', 'a number');
|
|
1075
|
+
}
|
|
723
1076
|
if (typeof options.restWsBridgeTimeout !== 'number' || isNaN(options.restWsBridgeTimeout)) {
|
|
724
1077
|
throw new TypeError('CLIENT_INVALID_OPTION', 'restWsBridgeTimeout', 'a number');
|
|
725
1078
|
}
|
|
@@ -738,16 +1091,15 @@ class Client extends BaseClient {
|
|
|
738
1091
|
if (typeof options.failIfNotExists !== 'boolean') {
|
|
739
1092
|
throw new TypeError('CLIENT_INVALID_OPTION', 'failIfNotExists', 'a boolean');
|
|
740
1093
|
}
|
|
1094
|
+
if (!Array.isArray(options.userAgentSuffix)) {
|
|
1095
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'userAgentSuffix', 'an array of strings');
|
|
1096
|
+
}
|
|
741
1097
|
if (
|
|
742
1098
|
typeof options.rejectOnRateLimit !== 'undefined' &&
|
|
743
1099
|
!(typeof options.rejectOnRateLimit === 'function' || Array.isArray(options.rejectOnRateLimit))
|
|
744
1100
|
) {
|
|
745
1101
|
throw new TypeError('CLIENT_INVALID_OPTION', 'rejectOnRateLimit', 'an array or a function');
|
|
746
1102
|
}
|
|
747
|
-
// Hardcode
|
|
748
|
-
this.options.shardCount = 1;
|
|
749
|
-
this.options.shards = [0];
|
|
750
|
-
this.options.intents = Intents.ALL;
|
|
751
1103
|
}
|
|
752
1104
|
}
|
|
753
1105
|
|