djs-selfbot-v13 3.1.7 → 3.2.2

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 (155) hide show
  1. package/README.md +18 -35
  2. package/package.json +85 -100
  3. package/src/client/BaseClient.js +3 -4
  4. package/src/client/Client.js +249 -530
  5. package/src/client/actions/Action.js +18 -13
  6. package/src/client/actions/ActionsManager.js +7 -1
  7. package/src/client/actions/AutoModerationActionExecution.js +1 -0
  8. package/src/client/actions/AutoModerationRuleCreate.js +1 -0
  9. package/src/client/actions/AutoModerationRuleDelete.js +1 -0
  10. package/src/client/actions/AutoModerationRuleUpdate.js +1 -0
  11. package/src/client/actions/GuildMemberRemove.js +0 -1
  12. package/src/client/actions/GuildMemberUpdate.js +0 -1
  13. package/src/client/actions/MessageCreate.js +0 -4
  14. package/src/client/actions/PresenceUpdate.js +17 -16
  15. package/src/client/websocket/WebSocketManager.js +11 -31
  16. package/src/client/websocket/WebSocketShard.js +39 -38
  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 +16 -13
  21. package/src/client/websocket/handlers/CHANNEL_RECIPIENT_REMOVE.js +11 -11
  22. package/src/client/websocket/handlers/GUILD_CREATE.js +19 -13
  23. package/src/client/websocket/handlers/GUILD_MEMBER_ADD.js +0 -1
  24. package/src/client/websocket/handlers/INTERACTION_MODAL_CREATE.js +1 -0
  25. package/src/client/websocket/handlers/MESSAGE_POLL_VOTE_ADD.js +22 -0
  26. package/src/client/websocket/handlers/MESSAGE_POLL_VOTE_REMOVE.js +12 -0
  27. package/src/client/websocket/handlers/READY.js +90 -140
  28. package/src/client/websocket/handlers/RELATIONSHIP_ADD.js +7 -5
  29. package/src/client/websocket/handlers/RELATIONSHIP_REMOVE.js +7 -5
  30. package/src/client/websocket/handlers/RELATIONSHIP_UPDATE.js +32 -9
  31. package/src/client/websocket/handlers/USER_GUILD_SETTINGS_UPDATE.js +2 -8
  32. package/src/client/websocket/handlers/USER_NOTE_UPDATE.js +1 -1
  33. package/src/client/websocket/handlers/USER_REQUIRED_ACTION_UPDATE.js +78 -0
  34. package/src/client/websocket/handlers/USER_SETTINGS_UPDATE.js +1 -5
  35. package/src/client/websocket/handlers/VOICE_CHANNEL_STATUS_UPDATE.js +12 -0
  36. package/src/client/websocket/handlers/index.js +17 -20
  37. package/src/errors/Messages.js +25 -69
  38. package/src/index.js +13 -43
  39. package/src/managers/ApplicationCommandManager.js +9 -12
  40. package/src/managers/ApplicationCommandPermissionsManager.js +3 -11
  41. package/src/managers/ChannelManager.js +2 -3
  42. package/src/managers/ClientUserSettingManager.js +162 -280
  43. package/src/managers/GuildBanManager.js +47 -1
  44. package/src/managers/GuildChannelManager.js +2 -16
  45. package/src/managers/GuildForumThreadManager.js +24 -30
  46. package/src/managers/GuildManager.js +1 -1
  47. package/src/managers/GuildMemberManager.js +50 -222
  48. package/src/managers/GuildSettingManager.js +22 -15
  49. package/src/managers/MessageManager.js +42 -44
  50. package/src/managers/PermissionOverwriteManager.js +1 -1
  51. package/src/managers/ReactionUserManager.js +5 -5
  52. package/src/managers/RelationshipManager.js +83 -76
  53. package/src/managers/ThreadManager.js +12 -45
  54. package/src/managers/ThreadMemberManager.js +1 -1
  55. package/src/managers/UserManager.js +6 -10
  56. package/src/managers/UserNoteManager.js +53 -0
  57. package/src/rest/APIRequest.js +48 -20
  58. package/src/rest/DiscordAPIError.js +17 -16
  59. package/src/rest/RESTManager.js +1 -21
  60. package/src/rest/RequestHandler.js +35 -21
  61. package/src/structures/ApplicationCommand.js +19 -456
  62. package/src/structures/ApplicationRoleConnectionMetadata.js +3 -0
  63. package/src/structures/AutoModerationRule.js +5 -5
  64. package/src/structures/AutocompleteInteraction.js +1 -0
  65. package/src/structures/BaseGuildTextChannel.js +10 -12
  66. package/src/structures/BaseGuildVoiceChannel.js +16 -18
  67. package/src/structures/{Call.js → CallState.js} +17 -12
  68. package/src/structures/CategoryChannel.js +2 -0
  69. package/src/structures/Channel.js +2 -3
  70. package/src/structures/ClientPresence.js +20 -19
  71. package/src/structures/ClientUser.js +117 -338
  72. package/src/structures/ContextMenuInteraction.js +1 -1
  73. package/src/structures/DMChannel.js +29 -92
  74. package/src/structures/ForumChannel.js +0 -10
  75. package/src/structures/GroupDMChannel.js +387 -0
  76. package/src/structures/Guild.js +135 -271
  77. package/src/structures/GuildAuditLogs.js +0 -5
  78. package/src/structures/GuildChannel.js +16 -2
  79. package/src/structures/GuildMember.js +27 -145
  80. package/src/structures/Interaction.js +1 -62
  81. package/src/structures/Invite.js +35 -52
  82. package/src/structures/Message.js +220 -203
  83. package/src/structures/MessageAttachment.js +11 -0
  84. package/src/structures/MessageButton.js +1 -67
  85. package/src/structures/MessageEmbed.js +1 -1
  86. package/src/structures/MessageMentions.js +3 -2
  87. package/src/structures/MessagePayload.js +6 -46
  88. package/src/structures/MessagePoll.js +238 -0
  89. package/src/structures/MessageReaction.js +1 -1
  90. package/src/structures/MessageSelectMenu.js +1 -252
  91. package/src/structures/Modal.js +70 -188
  92. package/src/structures/Presence.js +787 -129
  93. package/src/structures/Role.js +18 -2
  94. package/src/structures/SelectMenuInteraction.js +2 -151
  95. package/src/structures/Team.js +0 -49
  96. package/src/structures/TextInputComponent.js +0 -70
  97. package/src/structures/ThreadChannel.js +0 -19
  98. package/src/structures/User.js +145 -339
  99. package/src/structures/UserContextMenuInteraction.js +2 -2
  100. package/src/structures/VoiceState.js +74 -39
  101. package/src/structures/WebEmbed.js +38 -52
  102. package/src/structures/Webhook.js +17 -11
  103. package/src/structures/interfaces/Application.js +146 -23
  104. package/src/structures/interfaces/TextBasedChannel.js +409 -256
  105. package/src/util/ApplicationFlags.js +1 -1
  106. package/src/util/AttachmentFlags.js +38 -0
  107. package/src/util/Constants.js +120 -285
  108. package/src/util/Formatters.js +16 -2
  109. package/src/util/InviteFlags.js +29 -0
  110. package/src/util/LimitedCollection.js +1 -1
  111. package/src/util/Options.js +48 -74
  112. package/src/util/Permissions.js +15 -0
  113. package/src/util/PurchasedFlags.js +2 -0
  114. package/src/util/RemoteAuth.js +221 -356
  115. package/src/util/RoleFlags.js +37 -0
  116. package/src/util/Sweepers.js +1 -1
  117. package/src/util/Util.js +158 -32
  118. package/typings/enums.d.ts +24 -73
  119. package/typings/index.d.ts +978 -1288
  120. package/typings/rawDataTypes.d.ts +68 -9
  121. package/src/client/actions/InteractionCreate.js +0 -115
  122. package/src/client/websocket/handlers/APPLICATION_COMMAND_AUTOCOMPLETE_RESPONSE.js +0 -23
  123. package/src/client/websocket/handlers/GUILD_APPLICATION_COMMANDS_UPDATE.js +0 -11
  124. package/src/client/websocket/handlers/GUILD_MEMBER_LIST_UPDATE.js +0 -55
  125. package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUNDS_UPDATE.js +0 -0
  126. package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_CREATE.js +0 -0
  127. package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_DELETE.js +0 -0
  128. package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_UPDATE.js +0 -0
  129. package/src/client/websocket/handlers/INTERACTION_CREATE.js +0 -16
  130. package/src/client/websocket/handlers/INTERACTION_FAILURE.js +0 -18
  131. package/src/client/websocket/handlers/INTERACTION_SUCCESS.js +0 -30
  132. package/src/client/websocket/handlers/MESSAGE_ACK.js +0 -16
  133. package/src/client/websocket/handlers/SOUNDBOARD_SOUNDS.js +0 -0
  134. package/src/client/websocket/handlers/VOICE_CHANNEL_EFFECT_SEND.js +0 -0
  135. package/src/managers/DeveloperPortalManager.js +0 -104
  136. package/src/managers/GuildApplicationCommandManager.js +0 -28
  137. package/src/managers/GuildFolderManager.js +0 -24
  138. package/src/managers/SessionManager.js +0 -57
  139. package/src/rest/CaptchaSolver.js +0 -132
  140. package/src/structures/ClientApplication.js +0 -204
  141. package/src/structures/DeveloperPortalApplication.js +0 -520
  142. package/src/structures/GuildFolder.js +0 -75
  143. package/src/structures/InteractionResponse.js +0 -114
  144. package/src/structures/PartialGroupDMChannel.js +0 -433
  145. package/src/structures/RichPresence.js +0 -722
  146. package/src/structures/Session.js +0 -81
  147. package/src/util/Voice.js +0 -1456
  148. package/src/util/arRPC/index.js +0 -229
  149. package/src/util/arRPC/process/detectable.json +0 -1
  150. package/src/util/arRPC/process/index.js +0 -102
  151. package/src/util/arRPC/process/native/index.js +0 -5
  152. package/src/util/arRPC/process/native/linux.js +0 -37
  153. package/src/util/arRPC/process/native/win32.js +0 -25
  154. package/src/util/arRPC/transports/ipc.js +0 -281
  155. package/src/util/arRPC/transports/websocket.js +0 -128
@@ -86,11 +86,15 @@ class VoiceState extends Base {
86
86
 
87
87
  // The self_stream is property is omitted if false, check for another property
88
88
  // here to avoid incorrectly clearing this when partial data is specified
89
- /**
90
- * Whether this member is streaming using "Screen Share"
91
- * @type {boolean}
92
- */
93
- this.streaming = data.self_stream ?? false;
89
+ if ('self_stream' in data) {
90
+ /**
91
+ * Whether this member is streaming using "Screen Share"
92
+ * @type {boolean}
93
+ */
94
+ this.streaming = data.self_stream ?? false;
95
+ } else {
96
+ this.streaming ??= null;
97
+ }
94
98
 
95
99
  if ('channel_id' in data) {
96
100
  /**
@@ -144,12 +148,11 @@ class VoiceState extends Base {
144
148
 
145
149
  /**
146
150
  * The channel that the member is connected to
147
- * @type {?(VoiceChannel|StageChannel)}
151
+ * @type {?(VoiceChannel|StageChannel|DMChannel|GroupDMChannel)}
148
152
  * @readonly
149
153
  */
150
154
  get channel() {
151
- if (!this.guild?.id) return this.guild.client.channels.cache.get(this.channelId) ?? null;
152
- return this.guild.channels.cache.get(this.channelId) ?? null;
155
+ return (this.guild || this.client).channels.cache.get(this.channelId) ?? null;
153
156
  }
154
157
 
155
158
  /**
@@ -177,7 +180,6 @@ class VoiceState extends Base {
177
180
  * @returns {Promise<GuildMember>}
178
181
  */
179
182
  setMute(mute = true, reason) {
180
- if (!this.guild?.id) return null;
181
183
  return this.guild.members.edit(this.id, { mute }, reason);
182
184
  }
183
185
 
@@ -188,7 +190,6 @@ class VoiceState extends Base {
188
190
  * @returns {Promise<GuildMember>}
189
191
  */
190
192
  setDeaf(deaf = true, reason) {
191
- if (!this.guild?.id) return null;
192
193
  return this.guild.members.edit(this.id, { deaf }, reason);
193
194
  }
194
195
 
@@ -198,7 +199,6 @@ class VoiceState extends Base {
198
199
  * @returns {Promise<GuildMember>}
199
200
  */
200
201
  disconnect(reason) {
201
- if (!this.guild?.id) return this.callVoice?.disconnect();
202
202
  return this.setChannel(null, reason);
203
203
  }
204
204
 
@@ -210,7 +210,6 @@ class VoiceState extends Base {
210
210
  * @returns {Promise<GuildMember>}
211
211
  */
212
212
  setChannel(channel, reason) {
213
- if (!this.guild?.id) return null;
214
213
  return this.guild.members.edit(this.id, { channel }, reason);
215
214
  }
216
215
 
@@ -227,18 +226,16 @@ class VoiceState extends Base {
227
226
  * @returns {Promise<void>}
228
227
  */
229
228
  async setRequestToSpeak(request = true) {
230
- if (this.guild?.id) {
231
- if (this.channel?.type !== 'GUILD_STAGE_VOICE') throw new Error('VOICE_NOT_STAGE_CHANNEL');
229
+ if (this.channel?.type !== 'GUILD_STAGE_VOICE') throw new Error('VOICE_NOT_STAGE_CHANNEL');
232
230
 
233
- if (this.client.user.id !== this.id) throw new Error('VOICE_STATE_NOT_OWN');
231
+ if (this.client.user.id !== this.id) throw new Error('VOICE_STATE_NOT_OWN');
234
232
 
235
- await this.client.api.guilds(this.guild.id, 'voice-states', '@me').patch({
236
- data: {
237
- channel_id: this.channelId,
238
- request_to_speak_timestamp: request ? new Date().toISOString() : null,
239
- },
240
- });
241
- }
233
+ await this.client.api.guilds(this.guild.id, 'voice-states', '@me').patch({
234
+ data: {
235
+ channel_id: this.channelId,
236
+ request_to_speak_timestamp: request ? new Date().toISOString() : null,
237
+ },
238
+ });
242
239
  }
243
240
 
244
241
  /**
@@ -259,37 +256,75 @@ class VoiceState extends Base {
259
256
  * @returns {Promise<void>}
260
257
  */
261
258
  async setSuppressed(suppressed = true) {
262
- if (this.guild?.id) {
263
- if (typeof suppressed !== 'boolean') throw new TypeError('VOICE_STATE_INVALID_TYPE', 'suppressed');
259
+ if (typeof suppressed !== 'boolean') throw new TypeError('VOICE_STATE_INVALID_TYPE', 'suppressed');
264
260
 
265
- if (this.channel?.type !== 'GUILD_STAGE_VOICE') throw new Error('VOICE_NOT_STAGE_CHANNEL');
261
+ if (this.channel?.type !== 'GUILD_STAGE_VOICE') throw new Error('VOICE_NOT_STAGE_CHANNEL');
266
262
 
267
- const target = this.client.user.id === this.id ? '@me' : this.id;
263
+ const target = this.client.user.id === this.id ? '@me' : this.id;
268
264
 
269
- await this.client.api.guilds(this.guild.id, 'voice-states', target).patch({
270
- data: {
271
- channel_id: this.channelId,
272
- suppress: suppressed,
273
- },
274
- });
275
- }
265
+ await this.client.api.guilds(this.guild.id, 'voice-states', target).patch({
266
+ data: {
267
+ channel_id: this.channelId,
268
+ suppress: suppressed,
269
+ request_to_speak_timestamp: null,
270
+ },
271
+ });
272
+ }
273
+
274
+ /**
275
+ * Sets the status of the voice channel
276
+ * @param {string} [status=""] The message to set the channel status to
277
+ * @example
278
+ * // Setting the status to something
279
+ * guild.members.me.voice.setStatus("something")
280
+ * @example
281
+ * // Removing the status
282
+ * guild.members.me.voice.setStatus()
283
+ * @returns {Promise<void>}
284
+ */
285
+ setStatus(status = '') {
286
+ // PUT https://discord.com/api/v9/channels/:id/voice-status
287
+ return this.client.api.channels(this.channel.id, 'voice-status').put({
288
+ data: {
289
+ status,
290
+ },
291
+ });
276
292
  }
277
293
 
278
294
  /**
279
295
  * Get URL Image of the user's streaming video (NOT STREAMING !!!)
280
- * @returns {string} URL Image of the user's streaming video
296
+ * @returns {Promise<string>} URL Image of the user's streaming video
281
297
  */
282
298
  async getPreview() {
283
- if (!this.guild?.id) return null;
284
-
285
299
  if (!this.streaming) throw new Error('USER_NOT_STREAMING');
286
300
  // URL: https://discord.com/api/v9/streams/guild:guildid:voicechannelid:userid/preview
287
- const data = await this.client.api.streams[
288
- `guild%3A${this.guild.id}%3A${this.channelId}%3A${this.id}`
289
- ].preview.get();
301
+ // URL: https://discord.com/api/v9/streams/call:channelId:userId/preview
302
+ const streamKey = this.guild.id
303
+ ? `guild:${this.guild.id}:${this.channelId}:${this.id}`
304
+ : `call:${this.channelId}:${this.id}`;
305
+ const data = await this.client.api.streams[encodeURIComponent(streamKey)].preview.get();
290
306
  return data.url;
291
307
  }
292
308
 
309
+ /**
310
+ * Post Preview Image to the client user's streaming video
311
+ * @param {string} base64Image Base64 URI (data:image/jpeg;base64,data)
312
+ * @returns {Promise<void>}
313
+ */
314
+ postPreview(base64Image) {
315
+ if (!this.client.user.id === this.id || !this.streaming) throw new Error('USER_NOT_STREAMING');
316
+ // URL: https://discord.com/api/v9/streams/guild:guildid:voicechannelid:userid/preview
317
+ // URL: https://discord.com/api/v9/streams/call:channelId:userId/preview
318
+ const streamKey = this.guild.id
319
+ ? `guild:${this.guild.id}:${this.channelId}:${this.id}`
320
+ : `call:${this.channelId}:${this.id}`;
321
+ return this.client.api.streams[encodeURIComponent(streamKey)].preview.post({
322
+ data: {
323
+ thumbnail: base64Image,
324
+ },
325
+ });
326
+ }
327
+
293
328
  toJSON() {
294
329
  return super.toJSON({
295
330
  id: true,
@@ -1,14 +1,18 @@
1
1
  'use strict';
2
+
2
3
  const baseURL = 'https://webembed-sb.onrender.com/embed?';
3
4
  const hiddenCharter =
4
5
  '||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||||​||';
5
- const fetch = require('node-fetch');
6
6
  const { RangeError } = require('../errors');
7
7
  const Util = require('../util/Util');
8
8
 
9
9
  /**
10
10
  * Send Embedlink to Discord
11
- * Need to change WebEmbed API server (because heroku is no longer free)
11
+ * <info>Only works with Discord Web and Discord Client (no custom theme installed)</info>
12
+ * - No Timestamp, Footer, Fields, Author iconURL
13
+ * - Video with Embed working
14
+ * - Can only choose between image and thumbnail
15
+ * - Description limit 350 characters
12
16
  */
13
17
  class WebEmbed {
14
18
  /**
@@ -35,6 +39,7 @@ class WebEmbed {
35
39
  * @property {Partial<WebEmbedVideo>} [video] The video of this embed
36
40
  * @property {Partial<WebEmbedFooter>} [footer] The footer of this embed
37
41
  * @property {Partial<WebEmbedProvider>} [provider] The provider of this embed
42
+ * @property {string} [redirect] Redirect URL
38
43
  */
39
44
 
40
45
  // eslint-disable-next-line valid-jsdoc
@@ -42,24 +47,6 @@ class WebEmbed {
42
47
  * @param {WebEmbed|WebEmbedOptions|APIEmbed} [data={}] WebEmbed to clone or raw embed data
43
48
  */
44
49
  this._setup(data);
45
- /**
46
- * Shorten the link
47
- * @type {?boolean}
48
- */
49
- this.shorten = data.shorten ?? true;
50
-
51
- /**
52
- * Hidden Embed link
53
- * @type {?boolean}
54
- */
55
- this.hidden = data.hidden ?? false;
56
-
57
- /**
58
- * Using Custom WebEmbed server ?
59
- * @type {?string} https://webembed-sb.onrender.com/embed?
60
- * @see https://github.com/aiko-chan-ai/WebEmbed
61
- */
62
- this.baseURL = data.baseURL ?? baseURL;
63
50
  }
64
51
  /**
65
52
  * @private
@@ -188,6 +175,12 @@ class WebEmbed {
188
175
  url: data.provider.name,
189
176
  }
190
177
  : null;
178
+
179
+ /**
180
+ * Redirect URL
181
+ * @type {string}
182
+ */
183
+ this.redirect = data.redirect;
191
184
  }
192
185
  /**
193
186
  * The options to provide for setting an author for a {@link WebEmbed}.
@@ -320,66 +313,59 @@ class WebEmbed {
320
313
  }
321
314
 
322
315
  /**
323
- * Return Message Content + Embed (if hidden, pls check content length because it has 1000+ length)
324
- * @returns {string} Message Content
316
+ * Sets the redirect URL of this embed.
317
+ * @param {string} url The URL
318
+ * @returns {WebEmbed}
325
319
  */
326
- async toMessage() {
327
- const arrayQuery = [`image_type=${this.imageType}`];
320
+ setRedirect(url) {
321
+ this.redirect = url;
322
+ return this;
323
+ }
324
+
325
+ toString() {
326
+ const url = new URL(baseURL);
327
+ url.searchParams.set('image_type', this.imageType);
328
328
  if (this.title) {
329
- arrayQuery.push(`title=${encodeURIComponent(this.title)}`);
329
+ url.searchParams.set('title', this.title);
330
330
  }
331
331
  if (this.description) {
332
- arrayQuery.push(`description=${encodeURIComponent(this.description)}`);
332
+ url.searchParams.set('description', this.description);
333
333
  }
334
334
  if (this.url) {
335
- arrayQuery.push(`url=${encodeURIComponent(this.url)}`);
335
+ url.searchParams.set('url', this.url);
336
336
  }
337
337
  if (this.color) {
338
- arrayQuery.push(`color=${encodeURIComponent(`#${this.color.toString(16)}`)}`);
338
+ url.searchParams.set('color', `#${this.color.toString(16)}`);
339
339
  }
340
340
  if (this.image?.url) {
341
- arrayQuery.push(`image=${encodeURIComponent(this.image.url)}`);
341
+ url.searchParams.set('image', this.image.url);
342
342
  }
343
343
  if (this.video?.url) {
344
- arrayQuery.push(`video=${encodeURIComponent(this.video.url)}`);
344
+ url.searchParams.set('video', this.video.url);
345
345
  }
346
346
  if (this.author) {
347
347
  if (this.author.name) {
348
- arrayQuery.push(`author_name=${encodeURIComponent(this.author.name)}`);
348
+ url.searchParams.set('author_name', this.author.name);
349
349
  }
350
350
  if (this.author.url) {
351
- arrayQuery.push(`author_url=${encodeURIComponent(this.author.url)}`);
351
+ url.searchParams.set('author_url', this.author.url);
352
352
  }
353
353
  }
354
354
  if (this.provider) {
355
355
  if (this.provider.name) {
356
- arrayQuery.push(`provider_name=${encodeURIComponent(this.provider.name)}`);
356
+ url.searchParams.set('provider_name', this.provider.name);
357
357
  }
358
358
  if (this.provider.url) {
359
- arrayQuery.push(`provider_url=${encodeURIComponent(this.provider.url)}`);
359
+ url.searchParams.set('provider_url', this.provider.url);
360
360
  }
361
361
  }
362
362
  if (this.thumbnail?.url) {
363
- arrayQuery.push(`image=${encodeURIComponent(this.thumbnail.url)}`);
364
- }
365
- const fullURL = `${this.baseURL}${arrayQuery.join('&')}`;
366
- if (this.shorten) {
367
- const url = await this.constructor.getShorten(fullURL);
368
- if (!url) console.log('Cannot shorten URL in WebEmbed');
369
- return this.hidden ? `${hiddenCharter} ${url || fullURL}` : url || fullURL;
370
- } else {
371
- return this.hidden ? `${hiddenCharter} ${fullURL}` : fullURL;
363
+ url.searchParams.set('image', this.thumbnail.url);
372
364
  }
373
- }
374
-
375
- static async getShorten(url) {
376
- const shorten = `https://tinyurl.com/api-create.php?url=${encodeURIComponent(url)}`;
377
- try {
378
- const res = await (await fetch(shorten)).text();
379
- return res;
380
- } catch {
381
- return undefined;
365
+ if (this.redirect) {
366
+ url.searchParams.set('redirect', this.redirect);
382
367
  }
368
+ return url.toString();
383
369
  }
384
370
  }
385
371
 
@@ -72,7 +72,7 @@ class Webhook {
72
72
 
73
73
  if ('channel_id' in data) {
74
74
  /**
75
- * The channel the webhook belongs to
75
+ * The id of the channel the webhook belongs to
76
76
  * @type {Snowflake}
77
77
  */
78
78
  this.channelId = data.channel_id;
@@ -116,6 +116,7 @@ class Webhook {
116
116
  * @property {string} [avatarURL] Avatar URL override for the message
117
117
  * @property {Snowflake} [threadId] The id of the thread in the channel to send to.
118
118
  * <info>For interaction webhooks, this property is ignored</info>
119
+ * @property {string} [threadName] Name of the thread to create (only available if webhook is in a forum channel)
119
120
  * @property {MessageFlags} [flags] Which flags to set for the message. Only `SUPPRESS_EMBEDS` can be set.
120
121
  */
121
122
 
@@ -127,11 +128,10 @@ class Webhook {
127
128
  * @property {FileOptions[]|BufferResolvable[]|MessageAttachment[]} [files] See {@link BaseMessageOptions#files}
128
129
  * @property {MessageMentionOptions} [allowedMentions] See {@link BaseMessageOptions#allowedMentions}
129
130
  * @property {MessageAttachment[]} [attachments] Attachments to send with the message
130
- * @property {Array<(MessageActionRow|MessageActionRowOptions)>} [components]
131
+ * @property {MessageActionRow[]|MessageActionRowOptions[]} [components]
131
132
  * Action rows containing interactive components for the message (buttons, select menus)
132
133
  * @property {Snowflake} [threadId] The id of the thread this message belongs to
133
134
  * <info>For interaction webhooks, this property is ignored</info>
134
- * @property {string} [threadName] Name of the thread to create (only available if webhook is in a forum channel)
135
135
  */
136
136
 
137
137
  /**
@@ -188,9 +188,9 @@ class Webhook {
188
188
  let messagePayload;
189
189
 
190
190
  if (options instanceof MessagePayload) {
191
- messagePayload = await options.resolveData();
191
+ messagePayload = options.resolveData();
192
192
  } else {
193
- messagePayload = await MessagePayload.create(this, options).resolveData();
193
+ messagePayload = MessagePayload.create(this, options).resolveData();
194
194
  }
195
195
 
196
196
  const { data, files } = await messagePayload.resolveFiles();
@@ -324,13 +324,10 @@ class Webhook {
324
324
 
325
325
  let messagePayload;
326
326
 
327
- if (options instanceof MessagePayload) {
328
- messagePayload = await options.resolveData();
329
- } else {
330
- messagePayload = await MessagePayload.create(this, options).resolveData();
331
- }
327
+ if (options instanceof MessagePayload) messagePayload = options;
328
+ else messagePayload = MessagePayload.create(this, options);
332
329
 
333
- const { data, files } = await messagePayload.resolveFiles();
330
+ const { data, files } = await messagePayload.resolveData().resolveFiles();
334
331
 
335
332
  const d = await this.client.api
336
333
  .webhooks(this.id, this.token)
@@ -386,6 +383,15 @@ class Webhook {
386
383
  });
387
384
  }
388
385
 
386
+ /**
387
+ * The channel the webhook belongs to
388
+ * @type {?(TextChannel|VoiceChannel|NewsChannel|ForumChannel)}
389
+ * @readonly
390
+ */
391
+ get channel() {
392
+ return this.client.channels.resolve(this.channelId);
393
+ }
394
+
389
395
  /**
390
396
  * The timestamp the webhook was created at
391
397
  * @type {number}
@@ -1,10 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  const process = require('node:process');
4
+ const { ApplicationFlags } = require('../../util/ApplicationFlags');
4
5
  const { ClientApplicationAssetTypes, Endpoints } = require('../../util/Constants');
5
6
  const Permissions = require('../../util/Permissions');
6
7
  const SnowflakeUtil = require('../../util/SnowflakeUtil');
8
+ const { ApplicationRoleConnectionMetadata } = require('../ApplicationRoleConnectionMetadata');
7
9
  const Base = require('../Base');
10
+ const Team = require('../Team');
8
11
 
9
12
  const AssetTypes = Object.keys(ClientApplicationAssetTypes);
10
13
 
@@ -67,6 +70,132 @@ class Application extends Base {
67
70
  } else {
68
71
  this.roleConnectionsVerificationURL ??= null;
69
72
  }
73
+
74
+ // ClientApplication
75
+ /**
76
+ * The tags this application has (max of 5)
77
+ * @type {string[]}
78
+ */
79
+ this.tags = data.tags ?? [];
80
+
81
+ if ('install_params' in data) {
82
+ /**
83
+ * Settings for this application's default in-app authorization
84
+ * @type {?ClientApplicationInstallParams}
85
+ */
86
+ this.installParams = {
87
+ scopes: data.install_params.scopes,
88
+ permissions: new Permissions(data.install_params.permissions).freeze(),
89
+ };
90
+ } else {
91
+ this.installParams ??= null;
92
+ }
93
+
94
+ if ('custom_install_url' in data) {
95
+ /**
96
+ * This application's custom installation URL
97
+ * @type {?string}
98
+ */
99
+ this.customInstallURL = data.custom_install_url;
100
+ } else {
101
+ this.customInstallURL = null;
102
+ }
103
+
104
+ if ('flags' in data) {
105
+ /**
106
+ * The flags this application has
107
+ * @type {ApplicationFlags}
108
+ */
109
+ this.flags = new ApplicationFlags(data.flags).freeze();
110
+ }
111
+
112
+ if ('approximate_guild_count' in data) {
113
+ /**
114
+ * An approximate amount of guilds this application is in.
115
+ * @type {?number}
116
+ */
117
+ this.approximateGuildCount = data.approximate_guild_count;
118
+ } else {
119
+ this.approximateGuildCount ??= null;
120
+ }
121
+
122
+ if ('guild_id' in data) {
123
+ /**
124
+ * The id of the guild associated with this application.
125
+ * @type {?Snowflake}
126
+ */
127
+ this.guildId = data.guild_id;
128
+ } else {
129
+ this.guildId ??= null;
130
+ }
131
+
132
+ if ('cover_image' in data) {
133
+ /**
134
+ * The hash of the application's cover image
135
+ * @type {?string}
136
+ */
137
+ this.cover = data.cover_image;
138
+ } else {
139
+ this.cover ??= null;
140
+ }
141
+
142
+ if ('rpc_origins' in data) {
143
+ /**
144
+ * The application's RPC origins, if enabled
145
+ * @type {string[]}
146
+ */
147
+ this.rpcOrigins = data.rpc_origins;
148
+ } else {
149
+ this.rpcOrigins ??= [];
150
+ }
151
+
152
+ if ('bot_require_code_grant' in data) {
153
+ /**
154
+ * If this application's bot requires a code grant when using the OAuth2 flow
155
+ * @type {?boolean}
156
+ */
157
+ this.botRequireCodeGrant = data.bot_require_code_grant;
158
+ } else {
159
+ this.botRequireCodeGrant ??= null;
160
+ }
161
+
162
+ if ('bot_public' in data) {
163
+ /**
164
+ * If this application's bot is public
165
+ * @type {?boolean}
166
+ */
167
+ this.botPublic = data.bot_public;
168
+ } else {
169
+ this.botPublic ??= null;
170
+ }
171
+
172
+ /**
173
+ * The owner of this OAuth application
174
+ * @type {?(User|Team)}
175
+ */
176
+ this.owner = data.team
177
+ ? new Team(this.client, data.team)
178
+ : data.owner
179
+ ? this.client.users._add(data.owner)
180
+ : this.owner ?? null;
181
+ }
182
+
183
+ /**
184
+ * The guild associated with this application.
185
+ * @type {?Guild}
186
+ * @readonly
187
+ */
188
+ get guild() {
189
+ return this.client.guilds.cache.get(this.guildId) ?? null;
190
+ }
191
+
192
+ /**
193
+ * Whether this application is partial
194
+ * @type {boolean}
195
+ * @readonly
196
+ */
197
+ get partial() {
198
+ return !this.name;
70
199
  }
71
200
 
72
201
  /**
@@ -88,35 +217,29 @@ class Application extends Base {
88
217
  }
89
218
 
90
219
  /**
91
- * Invites this application to a guild / server
92
- * @param {Snowflake} guild_id The id of the guild that you want to invite the bot to
93
- * @param {PermissionResolvable} [permissions] The permissions for the bot in number form (the default is 8 / Administrator)
94
- * @param {string} [captcha] The captcha key to add
95
- * @returns {Promise<void>} nothing :)
220
+ * Obtains this application from Discord.
221
+ * @returns {Promise<Application>}
96
222
  */
97
- async invite(guild_id, permissions, captcha = null) {
98
- permissions = Permissions.resolve(permissions || 0n);
99
- const postData = {
100
- authorize: true,
101
- guild_id,
102
- permissions: '0',
103
- };
104
- if (permissions) {
105
- postData.permissions = permissions;
106
- }
107
- if (captcha && typeof captcha === 'string' && captcha.length > 0) {
108
- postData.captcha = captcha;
109
- }
110
- await this.client.api.oauth2.authorize.post({
223
+ async fetch() {
224
+ const app = await this.client.api.oauth2.authorize.get({
111
225
  query: {
112
226
  client_id: this.id,
113
227
  scope: 'bot applications.commands',
114
228
  },
115
- data: postData,
116
- headers: {
117
- referer: `https://discord.com/oauth2/authorize?client_id=${this.id}&permissions=${permissions}&scope=bot`,
118
- },
119
229
  });
230
+ const user = this.client.users._add(app.bot);
231
+ user._partial = false;
232
+ this._patch(app.application);
233
+ return this;
234
+ }
235
+
236
+ /**
237
+ * Gets this application's role connection metadata records
238
+ * @returns {Promise<ApplicationRoleConnectionMetadata[]>}
239
+ */
240
+ async fetchRoleConnectionMetadataRecords() {
241
+ const metadata = await this.client.api.applications(this.id)('role-connections').metadata.get();
242
+ return metadata.map(data => new ApplicationRoleConnectionMetadata(data));
120
243
  }
121
244
 
122
245
  /**