djs-selfbot-v13 3.1.5 → 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 (152) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +42 -15
  3. package/package.json +24 -9
  4. package/src/client/BaseClient.js +3 -2
  5. package/src/client/Client.js +539 -187
  6. package/src/client/actions/Action.js +13 -18
  7. package/src/client/actions/ActionsManager.js +1 -7
  8. package/src/client/actions/AutoModerationActionExecution.js +0 -1
  9. package/src/client/actions/AutoModerationRuleCreate.js +0 -1
  10. package/src/client/actions/AutoModerationRuleDelete.js +0 -1
  11. package/src/client/actions/AutoModerationRuleUpdate.js +0 -1
  12. package/src/client/actions/GuildMemberRemove.js +1 -1
  13. package/src/client/actions/GuildMemberUpdate.js +1 -1
  14. package/src/client/actions/InteractionCreate.js +115 -0
  15. package/src/client/actions/MessageCreate.js +4 -0
  16. package/src/client/actions/PresenceUpdate.js +16 -17
  17. package/src/client/websocket/WebSocketManager.js +31 -11
  18. package/src/client/websocket/WebSocketShard.js +38 -39
  19. package/src/client/websocket/handlers/APPLICATION_COMMAND_AUTOCOMPLETE_RESPONSE.js +23 -0
  20. package/src/client/websocket/handlers/CALL_CREATE.js +3 -3
  21. package/src/client/websocket/handlers/CALL_DELETE.js +2 -2
  22. package/src/client/websocket/handlers/CALL_UPDATE.js +2 -2
  23. package/src/client/websocket/handlers/CHANNEL_RECIPIENT_ADD.js +13 -16
  24. package/src/client/websocket/handlers/CHANNEL_RECIPIENT_REMOVE.js +11 -11
  25. package/src/client/websocket/handlers/GUILD_APPLICATION_COMMANDS_UPDATE.js +11 -0
  26. package/src/client/websocket/handlers/GUILD_CREATE.js +0 -7
  27. package/src/client/websocket/handlers/GUILD_MEMBER_ADD.js +1 -1
  28. package/src/client/websocket/handlers/GUILD_MEMBER_LIST_UPDATE.js +55 -0
  29. package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUNDS_UPDATE.js +0 -0
  30. package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_CREATE.js +0 -0
  31. package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_DELETE.js +0 -0
  32. package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_UPDATE.js +0 -0
  33. package/src/client/websocket/handlers/INTERACTION_CREATE.js +16 -0
  34. package/src/client/websocket/handlers/INTERACTION_FAILURE.js +18 -0
  35. package/src/client/websocket/handlers/INTERACTION_MODAL_CREATE.js +0 -1
  36. package/src/client/websocket/handlers/INTERACTION_SUCCESS.js +30 -0
  37. package/src/client/websocket/handlers/MESSAGE_ACK.js +16 -0
  38. package/src/client/websocket/handlers/READY.js +137 -47
  39. package/src/client/websocket/handlers/RELATIONSHIP_ADD.js +5 -7
  40. package/src/client/websocket/handlers/RELATIONSHIP_REMOVE.js +4 -6
  41. package/src/client/websocket/handlers/RELATIONSHIP_UPDATE.js +9 -32
  42. package/src/client/websocket/handlers/SOUNDBOARD_SOUNDS.js +0 -0
  43. package/src/client/websocket/handlers/USER_GUILD_SETTINGS_UPDATE.js +8 -2
  44. package/src/client/websocket/handlers/USER_NOTE_UPDATE.js +1 -1
  45. package/src/client/websocket/handlers/USER_SETTINGS_UPDATE.js +5 -1
  46. package/src/client/websocket/handlers/VOICE_CHANNEL_EFFECT_SEND.js +0 -0
  47. package/src/client/websocket/handlers/index.js +20 -15
  48. package/src/errors/Messages.js +69 -24
  49. package/src/index.js +43 -12
  50. package/src/managers/ApplicationCommandManager.js +12 -9
  51. package/src/managers/ApplicationCommandPermissionsManager.js +11 -3
  52. package/src/managers/ChannelManager.js +4 -2
  53. package/src/managers/ClientUserSettingManager.js +279 -161
  54. package/src/managers/DeveloperPortalManager.js +104 -0
  55. package/src/managers/GuildApplicationCommandManager.js +28 -0
  56. package/src/managers/GuildBanManager.js +1 -1
  57. package/src/managers/GuildChannelManager.js +0 -2
  58. package/src/managers/GuildFolderManager.js +24 -0
  59. package/src/managers/GuildForumThreadManager.js +28 -22
  60. package/src/managers/GuildMemberManager.js +216 -40
  61. package/src/managers/GuildSettingManager.js +15 -22
  62. package/src/managers/MessageManager.js +44 -42
  63. package/src/managers/PermissionOverwriteManager.js +1 -1
  64. package/src/managers/ReactionUserManager.js +5 -5
  65. package/src/managers/RelationshipManager.js +74 -81
  66. package/src/managers/SessionManager.js +57 -0
  67. package/src/managers/ThreadManager.js +45 -12
  68. package/src/managers/ThreadMemberManager.js +1 -1
  69. package/src/managers/UserManager.js +10 -6
  70. package/src/rest/APIRequest.js +20 -42
  71. package/src/rest/CaptchaSolver.js +132 -0
  72. package/src/rest/DiscordAPIError.js +16 -17
  73. package/src/rest/RESTManager.js +21 -1
  74. package/src/rest/RequestHandler.js +21 -35
  75. package/src/structures/ApplicationCommand.js +456 -19
  76. package/src/structures/ApplicationRoleConnectionMetadata.js +0 -3
  77. package/src/structures/AutoModerationRule.js +5 -5
  78. package/src/structures/AutocompleteInteraction.js +0 -1
  79. package/src/structures/BaseGuildTextChannel.js +12 -10
  80. package/src/structures/BaseGuildVoiceChannel.js +18 -16
  81. package/src/structures/{CallState.js → Call.js} +12 -17
  82. package/src/structures/CategoryChannel.js +0 -2
  83. package/src/structures/Channel.js +3 -2
  84. package/src/structures/ClientApplication.js +204 -0
  85. package/src/structures/ClientPresence.js +8 -12
  86. package/src/structures/ClientUser.js +338 -117
  87. package/src/structures/ContextMenuInteraction.js +1 -1
  88. package/src/structures/DMChannel.js +92 -29
  89. package/src/structures/DeveloperPortalApplication.js +520 -0
  90. package/src/structures/ForumChannel.js +10 -0
  91. package/src/structures/Guild.js +271 -135
  92. package/src/structures/GuildAuditLogs.js +5 -0
  93. package/src/structures/GuildChannel.js +2 -16
  94. package/src/structures/GuildFolder.js +75 -0
  95. package/src/structures/GuildMember.js +145 -27
  96. package/src/structures/Interaction.js +62 -1
  97. package/src/structures/InteractionResponse.js +114 -0
  98. package/src/structures/Invite.js +52 -35
  99. package/src/structures/Message.js +202 -222
  100. package/src/structures/MessageAttachment.js +0 -11
  101. package/src/structures/MessageButton.js +67 -1
  102. package/src/structures/MessageEmbed.js +1 -1
  103. package/src/structures/MessageMentions.js +2 -3
  104. package/src/structures/MessagePayload.js +46 -4
  105. package/src/structures/MessageReaction.js +1 -1
  106. package/src/structures/MessageSelectMenu.js +252 -1
  107. package/src/structures/Modal.js +180 -75
  108. package/src/structures/PartialGroupDMChannel.js +433 -0
  109. package/src/structures/Presence.js +2 -2
  110. package/src/structures/RichPresence.js +34 -14
  111. package/src/structures/Role.js +2 -18
  112. package/src/structures/SelectMenuInteraction.js +151 -2
  113. package/src/structures/Session.js +81 -0
  114. package/src/structures/Team.js +49 -0
  115. package/src/structures/TextInputComponent.js +70 -0
  116. package/src/structures/ThreadChannel.js +19 -0
  117. package/src/structures/User.js +345 -117
  118. package/src/structures/UserContextMenuInteraction.js +2 -2
  119. package/src/structures/VoiceState.js +39 -74
  120. package/src/structures/WebEmbed.js +52 -38
  121. package/src/structures/Webhook.js +11 -17
  122. package/src/structures/interfaces/Application.js +23 -146
  123. package/src/structures/interfaces/TextBasedChannel.js +256 -411
  124. package/src/util/ApplicationFlags.js +1 -1
  125. package/src/util/Constants.js +284 -106
  126. package/src/util/Formatters.js +2 -16
  127. package/src/util/LimitedCollection.js +1 -1
  128. package/src/util/Options.js +68 -48
  129. package/src/util/Permissions.js +0 -5
  130. package/src/util/PurchasedFlags.js +0 -2
  131. package/src/util/RemoteAuth.js +356 -221
  132. package/src/util/Sweepers.js +1 -1
  133. package/src/util/Util.js +36 -76
  134. package/src/util/Voice.js +1456 -0
  135. package/src/util/arRPC/index.js +229 -0
  136. package/src/util/arRPC/process/detectable.json +1 -0
  137. package/src/util/arRPC/process/index.js +102 -0
  138. package/src/util/arRPC/process/native/index.js +5 -0
  139. package/src/util/arRPC/process/native/linux.js +37 -0
  140. package/src/util/arRPC/process/native/win32.js +25 -0
  141. package/src/util/arRPC/transports/ipc.js +281 -0
  142. package/src/util/arRPC/transports/websocket.js +128 -0
  143. package/typings/enums.d.ts +73 -18
  144. package/typings/index.d.ts +1250 -898
  145. package/typings/rawDataTypes.d.ts +9 -68
  146. package/src/client/websocket/handlers/USER_REQUIRED_ACTION_UPDATE.js +0 -78
  147. package/src/client/websocket/handlers/VOICE_CHANNEL_STATUS_UPDATE.js +0 -12
  148. package/src/managers/UserNoteManager.js +0 -53
  149. package/src/structures/GroupDMChannel.js +0 -387
  150. package/src/util/AttachmentFlags.js +0 -38
  151. package/src/util/InviteFlags.js +0 -29
  152. package/src/util/RoleFlags.js +0 -37
@@ -3,15 +3,15 @@
3
3
  const { Collection } = require('@discordjs/collection');
4
4
  const CachedManager = require('./CachedManager');
5
5
  const { Error } = require('../errors');
6
- const User = require('../structures/User');
7
-
6
+ const { lazy } = require('../util/Util');
7
+ const User = lazy(() => require('../structures/User'));
8
8
  /**
9
9
  * Manages API methods for users who reacted to a reaction and stores their cache.
10
10
  * @extends {CachedManager}
11
11
  */
12
12
  class ReactionUserManager extends CachedManager {
13
13
  constructor(reaction, iterable) {
14
- super(reaction.client, User, iterable);
14
+ super(reaction.client, User(), iterable);
15
15
 
16
16
  /**
17
17
  * The reaction that this manager belongs to
@@ -22,7 +22,7 @@ class ReactionUserManager extends CachedManager {
22
22
 
23
23
  /**
24
24
  * The cache of this manager
25
- * @type {Collection<Snowflake, User>}
25
+ * @type {Collection<Snowflake, Discord.User>}
26
26
  * @name ReactionUserManager#cache
27
27
  */
28
28
 
@@ -36,7 +36,7 @@ class ReactionUserManager extends CachedManager {
36
36
  /**
37
37
  * Fetches all the users that gave this reaction. Resolves with a collection of users, mapped by their ids.
38
38
  * @param {FetchReactionUsersOptions} [options] Options for fetching the users
39
- * @returns {Promise<Collection<Snowflake, User>>}
39
+ * @returns {Promise<Collection<Snowflake, Discord.User>>}
40
40
  */
41
41
  async fetch({ limit = 100, after } = {}) {
42
42
  const message = this.reaction.message;
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ const Buffer = require('node:buffer').Buffer;
3
4
  const { Collection } = require('@discordjs/collection');
4
- const BaseManager = require('./BaseManager');
5
5
  const { GuildMember } = require('../structures/GuildMember');
6
6
  const { Message } = require('../structures/Message');
7
7
  const ThreadMember = require('../structures/ThreadMember');
@@ -11,22 +11,19 @@ const { RelationshipTypes } = require('../util/Constants');
11
11
  /**
12
12
  * Manages API methods for Relationships and stores their cache.
13
13
  */
14
- class RelationshipManager extends BaseManager {
14
+ class RelationshipManager {
15
15
  constructor(client, users) {
16
- super(client);
16
+ /**
17
+ * The client that instantiated this manager.
18
+ * @type {Client}
19
+ */
20
+ this.client = client;
17
21
  /**
18
22
  * A collection of users this manager is caching. (Type: Number)
19
23
  * @type {Collection<Snowflake, RelationshipTypes>}
24
+ * @readonly
20
25
  */
21
26
  this.cache = new Collection();
22
- /**
23
- * @type {Collection<Snowflake, string>}
24
- */
25
- this.friendNicknames = new Collection();
26
- /**
27
- * @type {Collection<Snowflake, Date>}
28
- */
29
- this.sinceCache = new Collection();
30
27
  this._setup(users);
31
28
  }
32
29
 
@@ -38,7 +35,7 @@ class RelationshipManager extends BaseManager {
38
35
  get friendCache() {
39
36
  const users = this.cache
40
37
  .filter(value => value === RelationshipTypes.FRIEND)
41
- .map((_, key) => [key, this.client.users.cache.get(key)]);
38
+ .map((value, key) => [key, this.client.users.cache.get(key)]);
42
39
  return new Collection(users);
43
40
  }
44
41
 
@@ -50,7 +47,7 @@ class RelationshipManager extends BaseManager {
50
47
  get blockedCache() {
51
48
  const users = this.cache
52
49
  .filter(value => value === RelationshipTypes.BLOCKED)
53
- .map((_, key) => [key, this.client.users.cache.get(key)]);
50
+ .map((value, key) => [key, this.client.users.cache.get(key)]);
54
51
  return new Collection(users);
55
52
  }
56
53
 
@@ -62,7 +59,7 @@ class RelationshipManager extends BaseManager {
62
59
  get incomingCache() {
63
60
  const users = this.cache
64
61
  .filter(value => value === RelationshipTypes.PENDING_INCOMING)
65
- .map((_, key) => [key, this.client.users.cache.get(key)]);
62
+ .map((value, key) => [key, this.client.users.cache.get(key)]);
66
63
  return new Collection(users);
67
64
  }
68
65
 
@@ -74,29 +71,16 @@ class RelationshipManager extends BaseManager {
74
71
  get outgoingCache() {
75
72
  const users = this.cache
76
73
  .filter(value => value === RelationshipTypes.PENDING_OUTGOING)
77
- .map((_, key) => [key, this.client.users.cache.get(key)]);
74
+ .map((value, key) => [key, this.client.users.cache.get(key)]);
78
75
  return new Collection(users);
79
76
  }
80
77
 
81
- /**
82
- * @typedef {Object} RelationshipJSONData
83
- * @property {Snowflake} id The ID of the target user
84
- * @property {RelationshipTypes} type The type of relationship
85
- * @property {string | null} nickname The nickname of the user in this relationship (1-32 characters)
86
- * @property {string} since When the user requested a relationship (ISO8601 timestamp)
87
- */
88
-
89
78
  /**
90
79
  * Return array of cache
91
- * @returns {RelationshipJSONData[]}
80
+ * @returns {Array<{id: Snowflake, type: RelationshipTypes}>}
92
81
  */
93
- toJSON() {
94
- return this.cache.map((value, key) => ({
95
- id: key,
96
- type: RelationshipTypes[value],
97
- nickname: this.friendNicknames.get(key),
98
- since: this.sinceCache.get(key).toISOString(),
99
- }));
82
+ toArray() {
83
+ return this.cache.map((value, key) => ({ id: key, type: RelationshipTypes[value] }));
100
84
  }
101
85
 
102
86
  /**
@@ -107,9 +91,8 @@ class RelationshipManager extends BaseManager {
107
91
  _setup(users) {
108
92
  if (!Array.isArray(users)) return;
109
93
  for (const relationShip of users) {
110
- this.friendNicknames.set(relationShip.id, relationShip.nickname);
94
+ this.client.user.friendNicknames.set(relationShip.id, relationShip.nickname);
111
95
  this.cache.set(relationShip.id, relationShip.type);
112
- this.sinceCache.set(relationShip.id, new Date(relationShip.since || 0));
113
96
  }
114
97
  }
115
98
 
@@ -150,55 +133,66 @@ class RelationshipManager extends BaseManager {
150
133
  }
151
134
 
152
135
  /**
153
- * Deletes a friend / blocked relationship with a client user or cancels a friend request.
136
+ * Deletes a friend relationship with a client user.
154
137
  * @param {UserResolvable} user Target
155
138
  * @returns {Promise<boolean>}
156
139
  */
157
- async deleteRelationship(user) {
140
+ deleteFriend(user) {
158
141
  const id = this.resolveId(user);
159
- if (
160
- ![RelationshipTypes.FRIEND, RelationshipTypes.BLOCKED, RelationshipTypes.PENDING_OUTGOING].includes(
161
- this.cache.get(id),
162
- )
163
- ) {
164
- return Promise.resolve(false);
165
- }
166
- await this.client.api.users['@me'].relationships[id].delete({
167
- DiscordContext: { location: 'Friends' },
168
- });
169
- return true;
142
+ // Check if already friends
143
+ if (this.cache.get(id) !== RelationshipTypes.FRIEND) return false;
144
+ return this.__cancel(id);
170
145
  }
171
146
 
172
147
  /**
173
- * @typedef {Object} FriendRequestOptions
174
- * @property {UserResolvable} [user] Target
175
- * @property {string} [username] Discord username
176
- * @property {number | null} [discriminator] Discord discriminator
148
+ * Deletes a blocked relationship with a client user.
149
+ * @param {UserResolvable} user Target
150
+ * @returns {Promise<boolean>}
177
151
  */
152
+ deleteBlocked(user) {
153
+ const id = this.resolveId(user);
154
+ // Check if already blocked
155
+ if (this.cache.get(id) !== RelationshipTypes.BLOCKED) return false;
156
+ return this.__cancel(id);
157
+ }
178
158
 
179
159
  /**
180
160
  * Sends a friend request.
181
- * @param {FriendRequestOptions} options Target
161
+ * @param {string} username Username of the user to send the request to
162
+ * @param {?number} discriminator Discriminator of the user to send the request to
182
163
  * @returns {Promise<boolean>}
183
164
  */
184
- async sendFriendRequest(options) {
185
- if (options?.user) {
186
- const id = this.resolveId(options.user);
187
- await this.client.api.users['@me'].relationships[id].put({
188
- data: {},
189
- DiscordContext: { location: 'ContextMenu' },
190
- });
191
- return true;
192
- } else {
193
- await this.client.api.users['@me'].relationships.post({
194
- data: {
195
- username: options.username,
196
- discriminator: options.discriminator,
197
- },
198
- DiscordContext: { location: 'Add Friend' },
199
- });
200
- return true;
201
- }
165
+ async sendFriendRequest(username, discriminator) {
166
+ await this.client.api.users('@me').relationships.post({
167
+ data: {
168
+ username,
169
+ discriminator: discriminator == 0 ? null : parseInt(discriminator),
170
+ },
171
+ headers: {
172
+ 'X-Context-Properties': Buffer.from(JSON.stringify({ location: 'Add Friend' }), 'utf8').toString('base64'),
173
+ },
174
+ });
175
+ return true;
176
+ }
177
+
178
+ /**
179
+ * Cancels a friend request.
180
+ * @param {UserResolvable} user the user you want to delete
181
+ * @returns {Promise<boolean>}
182
+ */
183
+ cancelFriendRequest(user) {
184
+ const id = this.resolveId(user);
185
+ if (this.cache.get(id) !== RelationshipTypes.PENDING_OUTGOING) return false;
186
+ return this.__cancel(id);
187
+ }
188
+
189
+ async __cancel(id) {
190
+ await this.client.api.users['@me'].relationships[id].delete({
191
+ headers: {
192
+ 'X-Context-Properties': Buffer.from(JSON.stringify({ location: 'Friends' }), 'utf8').toString('base64'),
193
+ },
194
+ });
195
+ return true;
202
196
  }
203
197
 
204
198
  /**
@@ -209,14 +203,16 @@ class RelationshipManager extends BaseManager {
209
203
  async addFriend(user) {
210
204
  const id = this.resolveId(user);
211
205
  // Check if already friends
212
- if (this.cache.get(id) === RelationshipTypes.FRIEND) return Promise.resolve(false);
206
+ if (this.cache.get(id) === RelationshipTypes.FRIEND) return false;
213
207
  // Check if outgoing request
214
- if (this.cache.get(id) === RelationshipTypes.PENDING_OUTGOING) return Promise.resolve(false);
208
+ if (this.cache.get(id) === RelationshipTypes.PENDING_OUTGOING) return false;
215
209
  await this.client.api.users['@me'].relationships[id].put({
216
210
  data: {
217
211
  type: RelationshipTypes.FRIEND,
218
212
  },
219
- DiscordContext: { location: 'Friends' },
213
+ headers: {
214
+ 'X-Context-Properties': Buffer.from(JSON.stringify({ location: 'Friends' }), 'utf8').toString('base64'),
215
+ },
220
216
  });
221
217
  return true;
222
218
  }
@@ -227,19 +223,14 @@ class RelationshipManager extends BaseManager {
227
223
  * @param {?string} nickname New nickname
228
224
  * @returns {Promise<boolean>}
229
225
  */
230
- async setNickname(user, nickname = null) {
226
+ async setNickname(user, nickname) {
231
227
  const id = this.resolveId(user);
232
- if (this.cache.get(id) !== RelationshipTypes.FRIEND) return Promise.resolve(false);
228
+ if (this.cache.get(id) !== RelationshipTypes.FRIEND) return false;
233
229
  await this.client.api.users['@me'].relationships[id].patch({
234
230
  data: {
235
231
  nickname: typeof nickname === 'string' ? nickname : null,
236
232
  },
237
233
  });
238
- if (nickname) {
239
- this.friendNicknames.set(id, nickname);
240
- } else {
241
- this.friendNicknames.delete(id);
242
- }
243
234
  return true;
244
235
  }
245
236
 
@@ -251,12 +242,14 @@ class RelationshipManager extends BaseManager {
251
242
  async addBlocked(user) {
252
243
  const id = this.resolveId(user);
253
244
  // Check
254
- if (this.cache.get(id) === RelationshipTypes.BLOCKED) return Promise.resolve(false);
245
+ if (this.cache.get(id) === RelationshipTypes.BLOCKED) return false;
255
246
  await this.client.api.users['@me'].relationships[id].put({
256
247
  data: {
257
248
  type: RelationshipTypes.BLOCKED,
258
249
  },
259
- DiscordContext: { location: 'ContextMenu' },
250
+ headers: {
251
+ 'X-Context-Properties': Buffer.from(JSON.stringify({ location: 'ContextMenu' }), 'utf8').toString('base64'),
252
+ },
260
253
  });
261
254
  return true;
262
255
  }
@@ -0,0 +1,57 @@
1
+ 'use strict';
2
+
3
+ const CachedManager = require('./CachedManager');
4
+ const { Error } = require('../errors/DJSError');
5
+ const Session = require('../structures/Session');
6
+ /**
7
+ * Manages API methods for users and stores their cache.
8
+ * @extends {CachedManager}
9
+ */
10
+ class SessionManager extends CachedManager {
11
+ constructor(client, iterable) {
12
+ super(client, Session, iterable);
13
+ }
14
+ /**
15
+ * The cache of Sessions
16
+ * @type {Collection<string, Session>}
17
+ * @name SessionManager#cache
18
+ */
19
+
20
+ /**
21
+ * Fetch all sessions of the client.
22
+ * @returns {Promise<SessionManager>}
23
+ */
24
+ fetch() {
25
+ return new Promise((resolve, reject) => {
26
+ this.client.api.auth.sessions
27
+ .get()
28
+ .then(data => {
29
+ const allData = data.user_sessions;
30
+ this.cache.clear();
31
+ for (const session of allData) {
32
+ this._add(new Session(this.client, session), true, { id: session.id_hash });
33
+ }
34
+ resolve(this);
35
+ })
36
+ .catch(reject);
37
+ });
38
+ }
39
+
40
+ /**
41
+ * Logout the client (remote).
42
+ * @param {string | null} mfaCode MFA code (if 2FA is enabled)
43
+ * @returns {Promise<undefined>}
44
+ */
45
+ logoutAllDevices(mfaCode) {
46
+ if (typeof this.client.password !== 'string') throw new Error('REQUIRE_PASSWORD');
47
+ return this.client.api.auth.sessions.logout({
48
+ data: {
49
+ session_id_hashes: this.cache.map(session => session.id),
50
+ password: this.client.password,
51
+ code: typeof mfaCode === 'string' ? mfaCode : undefined,
52
+ },
53
+ });
54
+ }
55
+ }
56
+
57
+ module.exports = SessionManager;
@@ -2,6 +2,7 @@
2
2
 
3
3
  const { Collection } = require('@discordjs/collection');
4
4
  const CachedManager = require('./CachedManager');
5
+ const { TypeError } = require('../errors');
5
6
  const ThreadChannel = require('../structures/ThreadChannel');
6
7
 
7
8
  /**
@@ -118,8 +119,34 @@ class ThreadManager extends CachedManager {
118
119
  * @param {boolean} [cache=true] Whether to cache the new thread objects if they aren't already
119
120
  * @returns {Promise<FetchedThreads>}
120
121
  */
121
- fetchArchived(options = {}, cache = true) {
122
- return this.fetchActive(cache, { archived: true, ...options });
122
+ async fetchArchived(options = {}, cache = true) {
123
+ if (this.client.user.bot) {
124
+ let { type = 'public', fetchAll = false, before, limit } = options;
125
+ let path = this.client.api.channels(this.channel.id);
126
+ if (type === 'private' && !fetchAll) {
127
+ path = path.users('@me');
128
+ }
129
+ let timestamp;
130
+ let id;
131
+ if (typeof before !== 'undefined') {
132
+ if (before instanceof ThreadChannel || /^\d{17,19}$/.test(String(before))) {
133
+ id = this.resolveId(before);
134
+ timestamp = this.resolve(before)?.archivedAt?.toISOString();
135
+ } else {
136
+ try {
137
+ timestamp = new Date(before).toISOString();
138
+ } catch {
139
+ throw new TypeError('INVALID_TYPE', 'before', 'DateResolvable or ThreadChannelResolvable');
140
+ }
141
+ }
142
+ }
143
+ const raw = await path.threads
144
+ .archived(type)
145
+ .get({ query: { before: type === 'private' && !fetchAll ? id : timestamp, limit } });
146
+ return this.constructor._mapThreads(raw, this.client, { parent: this.channel, cache });
147
+ } else {
148
+ return this.fetchActive(cache, { archived: true, ...options });
149
+ }
123
150
  }
124
151
 
125
152
  /**
@@ -138,16 +165,22 @@ class ThreadManager extends CachedManager {
138
165
  * @param {FetchChannelThreadsOptions} [options] Options for self-bots where advanced users can specify further options
139
166
  * @returns {Promise<FetchedThreads>}
140
167
  */
141
- async fetchActive(cache = true, options = {}) {
142
- const raw = await this.client.api.channels(this.channel.id).threads.search.get({
143
- query: {
144
- archived: options?.archived ?? false,
145
- limit: options?.limit ?? 25,
146
- offset: options?.offset ?? 0,
147
- sort_by: options?.sortBy ?? 'last_message_time',
148
- sort_order: options?.sortOrder ?? 'desc',
149
- },
150
- });
168
+ async fetchActive(cache = true, options = null) {
169
+ if (options && this.client.user.bot) {
170
+ throw new Error('INVALID_BOT_OPTIONS: Options can only be specified for user accounts.');
171
+ }
172
+
173
+ const raw = this.client.user.bot
174
+ ? await this.client.api.guilds(this.channel.guild.id).threads.active.get()
175
+ : await this.client.api.channels(this.channel.id).threads.search.get({
176
+ query: {
177
+ archived: options?.archived ?? false,
178
+ limit: options?.limit ?? 25,
179
+ offset: options?.offset ?? 0,
180
+ sort_by: options?.sortBy ?? 'last_message_time',
181
+ sort_order: options?.sortOrder ?? 'desc',
182
+ },
183
+ });
151
184
 
152
185
  return this.constructor._mapThreads(raw, this.client, { parent: this.channel, cache });
153
186
  }
@@ -179,7 +179,7 @@ class ThreadMemberManager extends CachedManager {
179
179
  const id = this.resolveId(member);
180
180
  return id
181
181
  ? this._fetchOne(id, options)
182
- : this._fetchMany(typeof member === 'boolean' ? { ...options, cache: member } : options);
182
+ : this._fetchMany(typeof member !== 'boolean' ? member : { ...options, cache: member });
183
183
  }
184
184
  }
185
185
 
@@ -56,15 +56,16 @@ class UserManager extends CachedManager {
56
56
  if (dmChannel && !dmChannel.partial) return dmChannel;
57
57
  }
58
58
 
59
- const data = await this.client.api.users['@me'].channels.post({
59
+ const data = await this.client.api.users(this.client.user.id).channels.post({
60
60
  data: {
61
61
  recipients: [id],
62
62
  },
63
- DiscordContext: {},
63
+ headers: {
64
+ 'X-Context-Properties': 'e30=', // {}
65
+ },
64
66
  });
65
-
66
67
  const dm_channel = await this.client.channels._add(data, null, { cache });
67
- dm_channel.sync();
68
+ await dm_channel.sync();
68
69
  return dm_channel;
69
70
  }
70
71
 
@@ -86,9 +87,10 @@ class UserManager extends CachedManager {
86
87
  * Obtains a user from Discord, or the user cache if it's already available.
87
88
  * @param {UserResolvable} user The user to fetch
88
89
  * @param {BaseFetchOptions} [options] Additional options for this fetch
90
+ * @param {?Snowflake} [options.guildId] The guild ID to fetch the member for
89
91
  * @returns {Promise<User>}
90
92
  */
91
- async fetch(user, { cache = true, force = false } = {}) {
93
+ async fetch(user, { cache = true, force = false, guildId = null } = {}) {
92
94
  const id = this.resolveId(user);
93
95
  if (!force) {
94
96
  const existing = this.cache.get(id);
@@ -96,7 +98,9 @@ class UserManager extends CachedManager {
96
98
  }
97
99
 
98
100
  const data = await this.client.api.users(id).get();
99
- return this._add(data, cache);
101
+ const userObject = this._add(data, cache);
102
+ await userObject.getProfile(guildId ?? null).catch(() => {});
103
+ return userObject;
100
104
  }
101
105
 
102
106
  /**
@@ -1,14 +1,12 @@
1
1
  'use strict';
2
2
 
3
3
  const Buffer = require('node:buffer').Buffer;
4
- const http = require('node:http');
5
4
  const https = require('node:https');
6
5
  const { setTimeout } = require('node:timers');
7
6
  const makeFetchCookie = require('fetch-cookie');
8
7
  const FormData = require('form-data');
9
8
  const fetchOriginal = require('node-fetch');
10
9
  const { CookieJar } = require('tough-cookie');
11
- const { ciphers } = require('../util/Constants');
12
10
 
13
11
  const cookieJar = new CookieJar();
14
12
  const fetch = makeFetchCookie(fetchOriginal, cookieJar);
@@ -24,10 +22,6 @@ class APIRequest {
24
22
  this.options = options;
25
23
  this.retries = 0;
26
24
 
27
- this.fullUserAgent = this.client.options.http.headers['User-Agent'];
28
-
29
- this.client.options.ws.properties.browser_user_agent = this.fullUserAgent;
30
-
31
25
  let queryString = '';
32
26
  if (options.query) {
33
27
  const query = Object.entries(options.query)
@@ -38,22 +32,16 @@ class APIRequest {
38
32
  this.path = `${path}${queryString && `?${queryString}`}`;
39
33
  }
40
34
 
41
- make(captchaKey, captchaRqToken) {
42
- if (!agent) {
43
- if (this.client.options.http.agent instanceof http.Agent) {
44
- this.client.options.http.agent.options.keepAlive = true;
45
- this.client.options.http.agent.options.honorCipherOrder = true;
46
- this.client.options.http.agent.options.minVersion = 'TLSv1.2';
47
- this.client.options.http.agent.options.ciphers = ciphers.join(':');
35
+ make(captchaKey = undefined, captchaRqtoken = undefined) {
36
+ if (agent === null) {
37
+ if (typeof this.client.options.proxy === 'string' && this.client.options.proxy.length > 0) {
38
+ const proxy = require('proxy-agent');
39
+ agent = new proxy(this.client.options.proxy);
40
+ } else if (this.client.options.http.agent instanceof https.Agent) {
48
41
  agent = this.client.options.http.agent;
42
+ agent.keepAlive = true;
49
43
  } else {
50
- agent = new https.Agent({
51
- ...this.client.options.http.agent,
52
- keepAlive: true,
53
- honorCipherOrder: true,
54
- minVersion: 'TLSv1.2',
55
- ciphers: ciphers.join(':'),
56
- });
44
+ agent = new https.Agent({ ...this.client.options.http.agent, keepAlive: true });
57
45
  }
58
46
  }
59
47
 
@@ -64,10 +52,10 @@ class APIRequest {
64
52
  const url = API + this.path;
65
53
 
66
54
  let headers = {
67
- authority: 'discord.com',
55
+ ...this.client.options.http.headers,
68
56
  accept: '*/*',
69
57
  'accept-language': 'en-US',
70
- 'sec-ch-ua': '"Not?A_Brand";v="8", "Chromium";v="108"',
58
+ 'sec-ch-ua': `"Not?A_Brand";v="8", "Chromium";v="108"`,
71
59
  'sec-ch-ua-mobile': '?0',
72
60
  'sec-ch-ua-platform': '"Windows"',
73
61
  'sec-fetch-dest': 'empty',
@@ -76,20 +64,18 @@ class APIRequest {
76
64
  'x-debug-options': 'bugReporterEnabled',
77
65
  'x-discord-locale': 'en-US',
78
66
  'x-discord-timezone': 'Asia/Saigon',
79
- 'x-super-properties': `${Buffer.from(JSON.stringify(this.client.options.ws.properties), 'ascii').toString(
80
- 'base64',
81
- )}`,
67
+ 'x-super-properties': `${Buffer.from(
68
+ this.client.options.jsonTransformer(this.client.options.ws.properties),
69
+ 'ascii',
70
+ ).toString('base64')}`,
82
71
  Referer: 'https://discord.com/channels/@me',
83
72
  origin: 'https://discord.com',
84
73
  'Referrer-Policy': 'strict-origin-when-cross-origin',
85
- ...this.client.options.http.headers,
86
- 'User-Agent': this.fullUserAgent,
87
74
  };
88
75
 
89
76
  if (this.options.auth !== false) headers.Authorization = this.rest.getAuth();
90
77
  if (this.options.reason) headers['X-Audit-Log-Reason'] = encodeURIComponent(this.options.reason);
91
78
  if (this.options.headers) headers = Object.assign(headers, this.options.headers);
92
-
93
79
  // Delete all headers if undefined
94
80
  for (const [key, value] of Object.entries(headers)) {
95
81
  if (value === undefined) delete headers[key];
@@ -99,15 +85,9 @@ class APIRequest {
99
85
  'User-Agent': this.client.options.http.headers['User-Agent'],
100
86
  };
101
87
  }
102
-
103
- // Some options
104
- if (this.options.DiscordContext) {
105
- headers['X-Context-Properties'] = Buffer.from(JSON.stringify(this.options.DiscordContext), 'utf8').toString(
106
- 'base64',
107
- );
108
- }
109
- if (this.options.mfaToken) {
110
- headers['X-Discord-Mfa-Authorization'] = this.options.mfaToken;
88
+ if (captchaKey && typeof captchaKey == 'string') {
89
+ headers['x-captcha-key'] = captchaKey;
90
+ if (captchaRqtoken) headers['x-captcha-rqtoken'] = captchaRqtoken;
111
91
  }
112
92
 
113
93
  let body;
@@ -126,21 +106,19 @@ class APIRequest {
126
106
  headers = Object.assign(headers, body.getHeaders());
127
107
  // eslint-disable-next-line eqeqeq
128
108
  } else if (this.options.data != null) {
129
- if (this.options.usePayloadJSON) {
109
+ if (this.options.useFormDataPayloadJSON) {
130
110
  body = new FormData();
131
111
  body.append('payload_json', JSON.stringify(this.options.data));
112
+ headers = Object.assign(headers, body.getHeaders());
132
113
  } else {
133
114
  body = JSON.stringify(this.options.data);
134
115
  headers['Content-Type'] = 'application/json';
135
116
  }
136
117
  }
137
118
 
138
- // Captcha
139
- if (captchaKey && typeof captchaKey == 'string') headers['X-Captcha-Key'] = captchaKey;
140
- if (captchaRqToken && typeof captchaRqToken == 'string') headers['X-Captcha-Rqtoken'] = captchaRqToken;
141
-
142
119
  const controller = new AbortController();
143
120
  const timeout = setTimeout(() => controller.abort(), this.client.options.restRequestTimeout).unref();
121
+
144
122
  return fetch(url, {
145
123
  method: this.method,
146
124
  headers,