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.
Files changed (148) hide show
  1. package/README.md +31 -16
  2. package/package.json +15 -8
  3. package/src/client/BaseClient.js +3 -2
  4. package/src/client/Client.js +539 -187
  5. package/src/client/actions/Action.js +13 -18
  6. package/src/client/actions/ActionsManager.js +1 -7
  7. package/src/client/actions/AutoModerationActionExecution.js +0 -1
  8. package/src/client/actions/AutoModerationRuleCreate.js +0 -1
  9. package/src/client/actions/AutoModerationRuleDelete.js +0 -1
  10. package/src/client/actions/AutoModerationRuleUpdate.js +0 -1
  11. package/src/client/actions/InteractionCreate.js +115 -0
  12. package/src/client/actions/MessageCreate.js +4 -0
  13. package/src/client/actions/PresenceUpdate.js +16 -17
  14. package/src/client/websocket/WebSocketManager.js +31 -11
  15. package/src/client/websocket/WebSocketShard.js +38 -39
  16. package/src/client/websocket/handlers/APPLICATION_COMMAND_AUTOCOMPLETE_RESPONSE.js +23 -0
  17. package/src/client/websocket/handlers/CALL_CREATE.js +3 -3
  18. package/src/client/websocket/handlers/CALL_DELETE.js +2 -2
  19. package/src/client/websocket/handlers/CALL_UPDATE.js +2 -2
  20. package/src/client/websocket/handlers/CHANNEL_RECIPIENT_ADD.js +13 -16
  21. package/src/client/websocket/handlers/CHANNEL_RECIPIENT_REMOVE.js +11 -11
  22. package/src/client/websocket/handlers/GUILD_APPLICATION_COMMANDS_UPDATE.js +11 -0
  23. package/src/client/websocket/handlers/GUILD_CREATE.js +0 -7
  24. package/src/client/websocket/handlers/GUILD_MEMBER_LIST_UPDATE.js +55 -0
  25. package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUNDS_UPDATE.js +0 -0
  26. package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_CREATE.js +0 -0
  27. package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_DELETE.js +0 -0
  28. package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_UPDATE.js +0 -0
  29. package/src/client/websocket/handlers/INTERACTION_CREATE.js +16 -0
  30. package/src/client/websocket/handlers/INTERACTION_FAILURE.js +18 -0
  31. package/src/client/websocket/handlers/INTERACTION_MODAL_CREATE.js +0 -1
  32. package/src/client/websocket/handlers/INTERACTION_SUCCESS.js +30 -0
  33. package/src/client/websocket/handlers/MESSAGE_ACK.js +16 -0
  34. package/src/client/websocket/handlers/READY.js +137 -47
  35. package/src/client/websocket/handlers/RELATIONSHIP_ADD.js +5 -7
  36. package/src/client/websocket/handlers/RELATIONSHIP_REMOVE.js +4 -6
  37. package/src/client/websocket/handlers/RELATIONSHIP_UPDATE.js +9 -32
  38. package/src/client/websocket/handlers/SOUNDBOARD_SOUNDS.js +0 -0
  39. package/src/client/websocket/handlers/USER_GUILD_SETTINGS_UPDATE.js +8 -2
  40. package/src/client/websocket/handlers/USER_NOTE_UPDATE.js +1 -1
  41. package/src/client/websocket/handlers/USER_SETTINGS_UPDATE.js +5 -1
  42. package/src/client/websocket/handlers/VOICE_CHANNEL_EFFECT_SEND.js +0 -0
  43. package/src/client/websocket/handlers/index.js +20 -15
  44. package/src/errors/Messages.js +69 -24
  45. package/src/index.js +43 -12
  46. package/src/managers/ApplicationCommandManager.js +12 -9
  47. package/src/managers/ApplicationCommandPermissionsManager.js +11 -3
  48. package/src/managers/ChannelManager.js +4 -2
  49. package/src/managers/ClientUserSettingManager.js +279 -161
  50. package/src/managers/DeveloperPortalManager.js +104 -0
  51. package/src/managers/GuildApplicationCommandManager.js +28 -0
  52. package/src/managers/GuildBanManager.js +1 -1
  53. package/src/managers/GuildChannelManager.js +0 -2
  54. package/src/managers/GuildFolderManager.js +24 -0
  55. package/src/managers/GuildForumThreadManager.js +28 -22
  56. package/src/managers/GuildMemberManager.js +216 -40
  57. package/src/managers/GuildSettingManager.js +15 -22
  58. package/src/managers/MessageManager.js +44 -42
  59. package/src/managers/PermissionOverwriteManager.js +1 -1
  60. package/src/managers/ReactionUserManager.js +5 -5
  61. package/src/managers/RelationshipManager.js +74 -81
  62. package/src/managers/SessionManager.js +57 -0
  63. package/src/managers/ThreadManager.js +45 -12
  64. package/src/managers/ThreadMemberManager.js +1 -1
  65. package/src/managers/UserManager.js +10 -6
  66. package/src/rest/APIRequest.js +20 -42
  67. package/src/rest/CaptchaSolver.js +132 -0
  68. package/src/rest/DiscordAPIError.js +16 -17
  69. package/src/rest/RESTManager.js +21 -1
  70. package/src/rest/RequestHandler.js +21 -35
  71. package/src/structures/ApplicationCommand.js +456 -19
  72. package/src/structures/ApplicationRoleConnectionMetadata.js +0 -3
  73. package/src/structures/AutoModerationRule.js +5 -5
  74. package/src/structures/AutocompleteInteraction.js +0 -1
  75. package/src/structures/BaseGuildTextChannel.js +12 -10
  76. package/src/structures/BaseGuildVoiceChannel.js +18 -16
  77. package/src/structures/{CallState.js → Call.js} +12 -17
  78. package/src/structures/CategoryChannel.js +0 -2
  79. package/src/structures/Channel.js +3 -2
  80. package/src/structures/ClientApplication.js +204 -0
  81. package/src/structures/ClientPresence.js +8 -12
  82. package/src/structures/ClientUser.js +336 -117
  83. package/src/structures/ContextMenuInteraction.js +1 -1
  84. package/src/structures/DMChannel.js +92 -29
  85. package/src/structures/DeveloperPortalApplication.js +520 -0
  86. package/src/structures/ForumChannel.js +10 -0
  87. package/src/structures/Guild.js +271 -135
  88. package/src/structures/GuildAuditLogs.js +5 -0
  89. package/src/structures/GuildChannel.js +2 -16
  90. package/src/structures/GuildFolder.js +75 -0
  91. package/src/structures/GuildMember.js +145 -27
  92. package/src/structures/Interaction.js +62 -1
  93. package/src/structures/InteractionResponse.js +114 -0
  94. package/src/structures/Invite.js +52 -35
  95. package/src/structures/Message.js +202 -222
  96. package/src/structures/MessageAttachment.js +0 -11
  97. package/src/structures/MessageButton.js +67 -1
  98. package/src/structures/MessageEmbed.js +1 -1
  99. package/src/structures/MessageMentions.js +2 -3
  100. package/src/structures/MessagePayload.js +46 -4
  101. package/src/structures/MessageReaction.js +1 -1
  102. package/src/structures/MessageSelectMenu.js +252 -1
  103. package/src/structures/Modal.js +180 -75
  104. package/src/structures/PartialGroupDMChannel.js +433 -0
  105. package/src/structures/Presence.js +2 -2
  106. package/src/structures/RichPresence.js +34 -14
  107. package/src/structures/Role.js +2 -18
  108. package/src/structures/SelectMenuInteraction.js +151 -2
  109. package/src/structures/Session.js +81 -0
  110. package/src/structures/Team.js +49 -0
  111. package/src/structures/TextInputComponent.js +70 -0
  112. package/src/structures/ThreadChannel.js +19 -0
  113. package/src/structures/User.js +345 -117
  114. package/src/structures/UserContextMenuInteraction.js +2 -2
  115. package/src/structures/VoiceState.js +39 -74
  116. package/src/structures/WebEmbed.js +52 -38
  117. package/src/structures/Webhook.js +11 -17
  118. package/src/structures/interfaces/Application.js +23 -146
  119. package/src/structures/interfaces/TextBasedChannel.js +256 -411
  120. package/src/util/ApplicationFlags.js +1 -1
  121. package/src/util/Constants.js +284 -106
  122. package/src/util/Formatters.js +2 -16
  123. package/src/util/LimitedCollection.js +1 -1
  124. package/src/util/Options.js +68 -48
  125. package/src/util/Permissions.js +0 -5
  126. package/src/util/PurchasedFlags.js +0 -2
  127. package/src/util/RemoteAuth.js +356 -221
  128. package/src/util/Sweepers.js +1 -1
  129. package/src/util/Util.js +36 -76
  130. package/src/util/Voice.js +1456 -0
  131. package/src/util/arRPC/index.js +229 -0
  132. package/src/util/arRPC/process/detectable.json +1 -0
  133. package/src/util/arRPC/process/index.js +102 -0
  134. package/src/util/arRPC/process/native/index.js +5 -0
  135. package/src/util/arRPC/process/native/linux.js +37 -0
  136. package/src/util/arRPC/process/native/win32.js +25 -0
  137. package/src/util/arRPC/transports/ipc.js +281 -0
  138. package/src/util/arRPC/transports/websocket.js +128 -0
  139. package/typings/enums.d.ts +73 -18
  140. package/typings/index.d.ts +1249 -897
  141. package/typings/rawDataTypes.d.ts +9 -68
  142. package/src/client/websocket/handlers/USER_REQUIRED_ACTION_UPDATE.js +0 -78
  143. package/src/client/websocket/handlers/VOICE_CHANNEL_STATUS_UPDATE.js +0 -12
  144. package/src/managers/UserNoteManager.js +0 -53
  145. package/src/structures/GroupDMChannel.js +0 -387
  146. package/src/util/AttachmentFlags.js +0 -38
  147. package/src/util/InviteFlags.js +0 -29
  148. package/src/util/RoleFlags.js +0 -37
@@ -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} [options] Options for the client
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
- QRLogin() {
275
- const ws = new DiscordAuthWebsocket();
276
- ws.once('ready', () => ws.generateQR());
277
- return ws.connect(this);
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
- return this.destroy();
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
- * The sleep function in JavaScript returns a promise that resolves after a specified timeout.
496
- * @param {number} timeout - The timeout parameter is the amount of time, in milliseconds, that the sleep
497
- * function will wait before resolving the promise and continuing execution.
498
- * @returns {void} The `sleep` function is returning a Promise.
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
- sleep(timeout) {
501
- return new Promise(r => setTimeout(r, timeout));
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
- * The current session id of the shard
512
- * @type {?string}
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
- get sessionId() {
515
- return this.ws.shards.first()?.sessionId;
884
+ _eval(script) {
885
+ return eval(script);
516
886
  }
517
887
 
518
888
  /**
519
- * Options for {@link Client#acceptInvite}.
520
- * @typedef {Object} AcceptInviteOptions
521
- * @property {boolean} [bypassOnboarding=true] Whether to bypass onboarding
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
- async acceptInvite(invite, options = { bypassOnboarding: true, bypassVerify: true }) {
534
- const code = DataResolver.resolveInviteCode(invite);
535
- if (!code) throw new Error('INVITE_RESOLVE_CODE');
536
- const i = await this.fetchInvite(code);
537
- if (i.guild?.id && this.guilds.cache.has(i.guild?.id)) return this.guilds.cache.get(i.guild?.id);
538
- if (this.channels.cache.has(i.channelId)) return this.channels.cache.get(i.channelId);
539
- /*
540
- {
541
- location: 'Desktop Invite Modal',
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
- return this.channels.cache.has(i.channelId || data.channel?.id);
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<any>}
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
- * Calls {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval} on a script
684
- * with the client as `this`.
685
- * @param {string} script Script to eval
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
- _eval(script) {
690
- return eval(script);
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