djs-selfbot-v13 3.2.2 → 3.7.1

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 (363) hide show
  1. package/README.md +37 -36
  2. package/package.json +89 -85
  3. package/src/WebSocket.js +39 -39
  4. package/src/client/BaseClient.js +86 -86
  5. package/src/client/Client.js +934 -836
  6. package/src/client/WebhookClient.js +61 -61
  7. package/src/client/actions/Action.js +116 -120
  8. package/src/client/actions/ActionsManager.js +80 -78
  9. package/src/client/actions/ApplicationCommandPermissionsUpdate.js +34 -34
  10. package/src/client/actions/AutoModerationActionExecution.js +27 -27
  11. package/src/client/actions/AutoModerationRuleCreate.js +28 -28
  12. package/src/client/actions/AutoModerationRuleDelete.js +32 -32
  13. package/src/client/actions/AutoModerationRuleUpdate.js +30 -30
  14. package/src/client/actions/ChannelCreate.js +23 -23
  15. package/src/client/actions/ChannelDelete.js +39 -39
  16. package/src/client/actions/ChannelUpdate.js +43 -43
  17. package/src/client/actions/GuildAuditLogEntryCreate.js +29 -29
  18. package/src/client/actions/GuildBanAdd.js +20 -20
  19. package/src/client/actions/GuildBanRemove.js +25 -25
  20. package/src/client/actions/GuildChannelsPositionUpdate.js +21 -21
  21. package/src/client/actions/GuildDelete.js +65 -65
  22. package/src/client/actions/GuildEmojiCreate.js +20 -20
  23. package/src/client/actions/GuildEmojiDelete.js +21 -21
  24. package/src/client/actions/GuildEmojiUpdate.js +20 -20
  25. package/src/client/actions/GuildEmojisUpdate.js +34 -34
  26. package/src/client/actions/GuildIntegrationsUpdate.js +19 -19
  27. package/src/client/actions/GuildMemberRemove.js +33 -32
  28. package/src/client/actions/GuildMemberUpdate.js +44 -43
  29. package/src/client/actions/GuildRoleCreate.js +25 -25
  30. package/src/client/actions/GuildRoleDelete.js +31 -31
  31. package/src/client/actions/GuildRoleUpdate.js +39 -39
  32. package/src/client/actions/GuildRolesPositionUpdate.js +21 -21
  33. package/src/client/actions/GuildScheduledEventCreate.js +27 -27
  34. package/src/client/actions/GuildScheduledEventDelete.js +31 -31
  35. package/src/client/actions/GuildScheduledEventUpdate.js +30 -30
  36. package/src/client/actions/GuildScheduledEventUserAdd.js +32 -32
  37. package/src/client/actions/GuildScheduledEventUserRemove.js +32 -32
  38. package/src/client/actions/GuildStickerCreate.js +20 -20
  39. package/src/client/actions/GuildStickerDelete.js +21 -21
  40. package/src/client/actions/GuildStickerUpdate.js +20 -20
  41. package/src/client/actions/GuildStickersUpdate.js +34 -34
  42. package/src/client/actions/GuildUpdate.js +33 -33
  43. package/src/client/actions/InviteCreate.js +28 -28
  44. package/src/client/actions/InviteDelete.js +30 -30
  45. package/src/client/actions/MessageCreate.js +50 -46
  46. package/src/client/actions/MessageDelete.js +32 -32
  47. package/src/client/actions/MessageDeleteBulk.js +46 -46
  48. package/src/client/actions/MessagePollVoteAdd.js +33 -0
  49. package/src/client/actions/MessagePollVoteRemove.js +33 -0
  50. package/src/client/actions/MessageReactionAdd.js +68 -56
  51. package/src/client/actions/MessageReactionRemove.js +50 -45
  52. package/src/client/actions/MessageReactionRemoveAll.js +33 -33
  53. package/src/client/actions/MessageReactionRemoveEmoji.js +28 -28
  54. package/src/client/actions/MessageUpdate.js +26 -26
  55. package/src/client/actions/PresenceUpdate.js +50 -46
  56. package/src/client/actions/StageInstanceCreate.js +28 -28
  57. package/src/client/actions/StageInstanceDelete.js +33 -33
  58. package/src/client/actions/StageInstanceUpdate.js +30 -30
  59. package/src/client/actions/ThreadCreate.js +24 -24
  60. package/src/client/actions/ThreadDelete.js +32 -32
  61. package/src/client/actions/ThreadListSync.js +59 -59
  62. package/src/client/actions/ThreadMemberUpdate.js +30 -30
  63. package/src/client/actions/ThreadMembersUpdate.js +34 -34
  64. package/src/client/actions/TypingStart.js +29 -29
  65. package/src/client/actions/UserUpdate.js +35 -35
  66. package/src/client/actions/VoiceStateUpdate.js +50 -57
  67. package/src/client/actions/WebhooksUpdate.js +20 -20
  68. package/src/client/voice/ClientVoiceManager.js +151 -51
  69. package/src/client/voice/VoiceConnection.js +1249 -0
  70. package/src/client/voice/dispatcher/AnnexBDispatcher.js +120 -0
  71. package/src/client/voice/dispatcher/AudioDispatcher.js +145 -0
  72. package/src/client/voice/dispatcher/BaseDispatcher.js +459 -0
  73. package/src/client/voice/dispatcher/VPxDispatcher.js +54 -0
  74. package/src/client/voice/dispatcher/VideoDispatcher.js +68 -0
  75. package/src/client/voice/networking/VoiceUDPClient.js +173 -0
  76. package/src/client/voice/networking/VoiceWebSocket.js +286 -0
  77. package/src/client/voice/player/MediaPlayer.js +321 -0
  78. package/src/client/voice/player/processing/AnnexBNalSplitter.js +244 -0
  79. package/src/client/voice/player/processing/IvfSplitter.js +106 -0
  80. package/src/client/voice/player/processing/PCMInsertSilence.js +37 -0
  81. package/src/client/voice/receiver/PacketHandler.js +260 -0
  82. package/src/client/voice/receiver/Receiver.js +96 -0
  83. package/src/client/voice/receiver/Recorder.js +173 -0
  84. package/src/client/voice/util/Function.js +116 -0
  85. package/src/client/voice/util/PlayInterface.js +122 -0
  86. package/src/client/voice/util/Secretbox.js +64 -0
  87. package/src/client/voice/util/Silence.js +16 -0
  88. package/src/client/voice/util/Socket.js +62 -0
  89. package/src/client/voice/util/VolumeInterface.js +104 -0
  90. package/src/client/websocket/WebSocketManager.js +392 -392
  91. package/src/client/websocket/WebSocketShard.js +907 -906
  92. package/src/client/websocket/handlers/APPLICATION_COMMAND_CREATE.js +18 -18
  93. package/src/client/websocket/handlers/APPLICATION_COMMAND_DELETE.js +20 -20
  94. package/src/client/websocket/handlers/APPLICATION_COMMAND_PERMISSIONS_UPDATE.js +5 -5
  95. package/src/client/websocket/handlers/APPLICATION_COMMAND_UPDATE.js +20 -20
  96. package/src/client/websocket/handlers/AUTO_MODERATION_ACTION_EXECUTION.js +5 -5
  97. package/src/client/websocket/handlers/AUTO_MODERATION_RULE_CREATE.js +5 -5
  98. package/src/client/websocket/handlers/AUTO_MODERATION_RULE_DELETE.js +5 -5
  99. package/src/client/websocket/handlers/AUTO_MODERATION_RULE_UPDATE.js +5 -5
  100. package/src/client/websocket/handlers/CALL_CREATE.js +14 -14
  101. package/src/client/websocket/handlers/CALL_DELETE.js +11 -11
  102. package/src/client/websocket/handlers/CALL_UPDATE.js +11 -11
  103. package/src/client/websocket/handlers/CHANNEL_CREATE.js +5 -5
  104. package/src/client/websocket/handlers/CHANNEL_DELETE.js +5 -5
  105. package/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js +22 -22
  106. package/src/client/websocket/handlers/CHANNEL_RECIPIENT_ADD.js +19 -19
  107. package/src/client/websocket/handlers/CHANNEL_RECIPIENT_REMOVE.js +16 -16
  108. package/src/client/websocket/handlers/CHANNEL_UPDATE.js +16 -16
  109. package/src/client/websocket/handlers/GUILD_AUDIT_LOG_ENTRY_CREATE.js +5 -5
  110. package/src/client/websocket/handlers/GUILD_BAN_ADD.js +5 -5
  111. package/src/client/websocket/handlers/GUILD_BAN_REMOVE.js +5 -5
  112. package/src/client/websocket/handlers/GUILD_CREATE.js +52 -52
  113. package/src/client/websocket/handlers/GUILD_DELETE.js +5 -5
  114. package/src/client/websocket/handlers/GUILD_EMOJIS_UPDATE.js +5 -5
  115. package/src/client/websocket/handlers/GUILD_INTEGRATIONS_UPDATE.js +5 -5
  116. package/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js +39 -39
  117. package/src/client/websocket/handlers/GUILD_MEMBER_ADD.js +20 -19
  118. package/src/client/websocket/handlers/GUILD_MEMBER_REMOVE.js +5 -5
  119. package/src/client/websocket/handlers/GUILD_MEMBER_UPDATE.js +5 -5
  120. package/src/client/websocket/handlers/GUILD_ROLE_CREATE.js +5 -5
  121. package/src/client/websocket/handlers/GUILD_ROLE_DELETE.js +5 -5
  122. package/src/client/websocket/handlers/GUILD_ROLE_UPDATE.js +5 -5
  123. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_CREATE.js +5 -5
  124. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_DELETE.js +5 -5
  125. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_UPDATE.js +5 -5
  126. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_USER_ADD.js +5 -5
  127. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_USER_REMOVE.js +5 -5
  128. package/src/client/websocket/handlers/GUILD_STICKERS_UPDATE.js +5 -5
  129. package/src/client/websocket/handlers/GUILD_UPDATE.js +5 -5
  130. package/src/client/websocket/handlers/INTERACTION_MODAL_CREATE.js +12 -12
  131. package/src/client/websocket/handlers/INVITE_CREATE.js +5 -5
  132. package/src/client/websocket/handlers/INVITE_DELETE.js +5 -5
  133. package/src/client/websocket/handlers/MESSAGE_CREATE.js +5 -5
  134. package/src/client/websocket/handlers/MESSAGE_DELETE.js +5 -5
  135. package/src/client/websocket/handlers/MESSAGE_DELETE_BULK.js +5 -5
  136. package/src/client/websocket/handlers/MESSAGE_POLL_VOTE_ADD.js +5 -22
  137. package/src/client/websocket/handlers/MESSAGE_POLL_VOTE_REMOVE.js +5 -12
  138. package/src/client/websocket/handlers/MESSAGE_REACTION_ADD.js +5 -5
  139. package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE.js +5 -5
  140. package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_ALL.js +5 -5
  141. package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.js +5 -5
  142. package/src/client/websocket/handlers/MESSAGE_UPDATE.js +16 -16
  143. package/src/client/websocket/handlers/PRESENCE_UPDATE.js +5 -5
  144. package/src/client/websocket/handlers/READY.js +121 -120
  145. package/src/client/websocket/handlers/RELATIONSHIP_ADD.js +19 -19
  146. package/src/client/websocket/handlers/RELATIONSHIP_REMOVE.js +17 -17
  147. package/src/client/websocket/handlers/RELATIONSHIP_UPDATE.js +41 -41
  148. package/src/client/websocket/handlers/RESUMED.js +14 -14
  149. package/src/client/websocket/handlers/STAGE_INSTANCE_CREATE.js +5 -5
  150. package/src/client/websocket/handlers/STAGE_INSTANCE_DELETE.js +5 -5
  151. package/src/client/websocket/handlers/STAGE_INSTANCE_UPDATE.js +5 -5
  152. package/src/client/websocket/handlers/THREAD_CREATE.js +5 -5
  153. package/src/client/websocket/handlers/THREAD_DELETE.js +5 -5
  154. package/src/client/websocket/handlers/THREAD_LIST_SYNC.js +5 -5
  155. package/src/client/websocket/handlers/THREAD_MEMBERS_UPDATE.js +5 -5
  156. package/src/client/websocket/handlers/THREAD_MEMBER_UPDATE.js +5 -5
  157. package/src/client/websocket/handlers/THREAD_UPDATE.js +16 -16
  158. package/src/client/websocket/handlers/TYPING_START.js +5 -5
  159. package/src/client/websocket/handlers/USER_GUILD_SETTINGS_UPDATE.js +6 -6
  160. package/src/client/websocket/handlers/USER_NOTE_UPDATE.js +5 -5
  161. package/src/client/websocket/handlers/USER_REQUIRED_ACTION_UPDATE.js +78 -78
  162. package/src/client/websocket/handlers/USER_SETTINGS_UPDATE.js +5 -5
  163. package/src/client/websocket/handlers/USER_UPDATE.js +5 -5
  164. package/src/client/websocket/handlers/VOICE_CHANNEL_EFFECT_SEND.js +16 -0
  165. package/src/client/websocket/handlers/VOICE_CHANNEL_STATUS_UPDATE.js +12 -12
  166. package/src/client/websocket/handlers/VOICE_SERVER_UPDATE.js +6 -6
  167. package/src/client/websocket/handlers/VOICE_STATE_UPDATE.js +5 -5
  168. package/src/client/websocket/handlers/WEBHOOKS_UPDATE.js +5 -5
  169. package/src/client/websocket/handlers/index.js +84 -83
  170. package/src/errors/DJSError.js +61 -61
  171. package/src/errors/Messages.js +217 -183
  172. package/src/errors/index.js +4 -4
  173. package/src/index.js +172 -159
  174. package/src/managers/ApplicationCommandManager.js +264 -264
  175. package/src/managers/ApplicationCommandPermissionsManager.js +417 -417
  176. package/src/managers/AutoModerationRuleManager.js +296 -296
  177. package/src/managers/BaseGuildEmojiManager.js +80 -80
  178. package/src/managers/BaseManager.js +19 -19
  179. package/src/managers/BillingManager.js +66 -66
  180. package/src/managers/CachedManager.js +71 -71
  181. package/src/managers/ChannelManager.js +148 -138
  182. package/src/managers/ClientUserSettingManager.js +372 -372
  183. package/src/managers/DataManager.js +61 -61
  184. package/src/managers/GuildBanManager.js +250 -250
  185. package/src/managers/GuildChannelManager.js +488 -488
  186. package/src/managers/GuildEmojiManager.js +171 -171
  187. package/src/managers/GuildEmojiRoleManager.js +118 -118
  188. package/src/managers/GuildForumThreadManager.js +108 -108
  189. package/src/managers/GuildInviteManager.js +213 -213
  190. package/src/managers/GuildManager.js +338 -304
  191. package/src/managers/GuildMemberManager.js +599 -597
  192. package/src/managers/GuildMemberRoleManager.js +195 -191
  193. package/src/managers/GuildScheduledEventManager.js +314 -296
  194. package/src/managers/GuildSettingManager.js +155 -155
  195. package/src/managers/GuildStickerManager.js +179 -179
  196. package/src/managers/GuildTextThreadManager.js +98 -98
  197. package/src/managers/InteractionManager.js +39 -39
  198. package/src/managers/MessageManager.js +423 -391
  199. package/src/managers/PermissionOverwriteManager.js +164 -166
  200. package/src/managers/PresenceManager.js +71 -58
  201. package/src/managers/ReactionManager.js +67 -67
  202. package/src/managers/ReactionUserManager.js +73 -71
  203. package/src/managers/RelationshipManager.js +278 -265
  204. package/src/managers/RoleManager.js +448 -352
  205. package/src/managers/SessionManager.js +66 -0
  206. package/src/managers/StageInstanceManager.js +162 -162
  207. package/src/managers/ThreadManager.js +175 -174
  208. package/src/managers/ThreadMemberManager.js +186 -186
  209. package/src/managers/UserManager.js +136 -146
  210. package/src/managers/UserNoteManager.js +53 -53
  211. package/src/managers/VoiceStateManager.js +59 -37
  212. package/src/rest/APIRequest.js +154 -160
  213. package/src/rest/APIRouter.js +53 -53
  214. package/src/rest/DiscordAPIError.js +119 -104
  215. package/src/rest/HTTPError.js +62 -62
  216. package/src/rest/RESTManager.js +67 -62
  217. package/src/rest/RateLimitError.js +55 -55
  218. package/src/rest/RequestHandler.js +466 -444
  219. package/src/sharding/Shard.js +444 -443
  220. package/src/sharding/ShardClientUtil.js +279 -275
  221. package/src/sharding/ShardingManager.js +319 -318
  222. package/src/structures/AnonymousGuild.js +98 -98
  223. package/src/structures/ApplicationCommand.js +593 -593
  224. package/src/structures/ApplicationRoleConnectionMetadata.js +48 -48
  225. package/src/structures/AutoModerationActionExecution.js +89 -89
  226. package/src/structures/AutoModerationRule.js +294 -294
  227. package/src/structures/AutocompleteInteraction.js +107 -107
  228. package/src/structures/Base.js +43 -43
  229. package/src/structures/BaseCommandInteraction.js +211 -211
  230. package/src/structures/BaseGuild.js +116 -116
  231. package/src/structures/BaseGuildEmoji.js +56 -56
  232. package/src/structures/BaseGuildTextChannel.js +191 -191
  233. package/src/structures/BaseGuildVoiceChannel.js +241 -241
  234. package/src/structures/BaseMessageComponent.js +181 -114
  235. package/src/structures/ButtonInteraction.js +11 -11
  236. package/src/structures/CallState.js +63 -63
  237. package/src/structures/CategoryChannel.js +85 -85
  238. package/src/structures/Channel.js +284 -270
  239. package/src/structures/ClientPresence.js +77 -85
  240. package/src/structures/ClientUser.js +479 -448
  241. package/src/structures/CommandInteraction.js +41 -41
  242. package/src/structures/CommandInteractionOptionResolver.js +276 -276
  243. package/src/structures/ContainerComponent.js +68 -0
  244. package/src/structures/ContextMenuInteraction.js +65 -65
  245. package/src/structures/DMChannel.js +219 -217
  246. package/src/structures/DirectoryChannel.js +20 -20
  247. package/src/structures/Emoji.js +148 -148
  248. package/src/structures/FileComponent.js +49 -0
  249. package/src/structures/ForumChannel.js +31 -261
  250. package/src/structures/GroupDMChannel.js +394 -387
  251. package/src/structures/Guild.js +1643 -1608
  252. package/src/structures/GuildAuditLogs.js +746 -729
  253. package/src/structures/GuildBan.js +59 -59
  254. package/src/structures/GuildBoost.js +108 -108
  255. package/src/structures/GuildChannel.js +470 -468
  256. package/src/structures/GuildEmoji.js +161 -161
  257. package/src/structures/GuildMember.js +636 -568
  258. package/src/structures/GuildPreview.js +191 -191
  259. package/src/structures/GuildPreviewEmoji.js +27 -27
  260. package/src/structures/GuildScheduledEvent.js +536 -441
  261. package/src/structures/GuildTemplate.js +236 -236
  262. package/src/structures/Integration.js +188 -188
  263. package/src/structures/IntegrationApplication.js +96 -96
  264. package/src/structures/Interaction.js +290 -290
  265. package/src/structures/InteractionCollector.js +248 -248
  266. package/src/structures/InteractionWebhook.js +43 -43
  267. package/src/structures/Invite.js +358 -358
  268. package/src/structures/InviteGuild.js +23 -23
  269. package/src/structures/InviteStageInstance.js +86 -86
  270. package/src/structures/MediaChannel.js +11 -0
  271. package/src/structures/MediaGalleryComponent.js +41 -0
  272. package/src/structures/MediaGalleryItem.js +47 -0
  273. package/src/structures/Message.js +1252 -1227
  274. package/src/structures/MessageActionRow.js +105 -103
  275. package/src/structures/MessageAttachment.js +216 -204
  276. package/src/structures/MessageButton.js +166 -165
  277. package/src/structures/MessageCollector.js +146 -146
  278. package/src/structures/MessageComponentInteraction.js +120 -120
  279. package/src/structures/MessageContextMenuInteraction.js +20 -20
  280. package/src/structures/MessageEmbed.js +596 -586
  281. package/src/structures/MessageMentions.js +273 -273
  282. package/src/structures/MessagePayload.js +354 -318
  283. package/src/structures/MessageReaction.js +181 -171
  284. package/src/structures/MessageSelectMenu.js +141 -140
  285. package/src/structures/Modal.js +161 -161
  286. package/src/structures/ModalSubmitFieldsResolver.js +53 -53
  287. package/src/structures/ModalSubmitInteraction.js +119 -119
  288. package/src/structures/NewsChannel.js +32 -32
  289. package/src/structures/OAuth2Guild.js +28 -28
  290. package/src/structures/PermissionOverwrites.js +198 -196
  291. package/src/structures/Poll.js +108 -0
  292. package/src/structures/PollAnswer.js +88 -0
  293. package/src/structures/Presence.js +1105 -1101
  294. package/src/structures/ReactionCollector.js +229 -229
  295. package/src/structures/ReactionEmoji.js +31 -31
  296. package/src/structures/Role.js +590 -531
  297. package/src/structures/SectionComponent.js +48 -0
  298. package/src/structures/SelectMenuInteraction.js +21 -21
  299. package/src/structures/SeparatorComponent.js +48 -0
  300. package/src/structures/Session.js +81 -0
  301. package/src/structures/StageChannel.js +104 -104
  302. package/src/structures/StageInstance.js +208 -208
  303. package/src/structures/Sticker.js +310 -310
  304. package/src/structures/StickerPack.js +95 -95
  305. package/src/structures/StoreChannel.js +56 -56
  306. package/src/structures/Team.js +118 -118
  307. package/src/structures/TeamMember.js +80 -71
  308. package/src/structures/TextChannel.js +33 -33
  309. package/src/structures/TextDisplayComponent.js +40 -0
  310. package/src/structures/TextInputComponent.js +132 -131
  311. package/src/structures/ThreadChannel.js +605 -607
  312. package/src/structures/ThreadMember.js +105 -105
  313. package/src/structures/ThreadOnlyChannel.js +249 -0
  314. package/src/structures/ThumbnailComponent.js +57 -0
  315. package/src/structures/Typing.js +74 -74
  316. package/src/structures/UnfurledMediaItem.js +29 -0
  317. package/src/structures/User.js +640 -543
  318. package/src/structures/UserContextMenuInteraction.js +29 -29
  319. package/src/structures/VoiceChannel.js +110 -110
  320. package/src/structures/VoiceChannelEffect.js +69 -0
  321. package/src/structures/VoiceRegion.js +53 -53
  322. package/src/structures/VoiceState.js +354 -341
  323. package/src/structures/WebEmbed.js +373 -373
  324. package/src/structures/Webhook.js +478 -467
  325. package/src/structures/WelcomeChannel.js +60 -60
  326. package/src/structures/WelcomeScreen.js +48 -48
  327. package/src/structures/Widget.js +87 -87
  328. package/src/structures/WidgetMember.js +99 -99
  329. package/src/structures/interfaces/Application.js +825 -313
  330. package/src/structures/interfaces/Collector.js +300 -300
  331. package/src/structures/interfaces/InteractionResponses.js +313 -313
  332. package/src/structures/interfaces/TextBasedChannel.js +759 -719
  333. package/src/util/APITypes.js +59 -0
  334. package/src/util/ActivityFlags.js +44 -44
  335. package/src/util/ApplicationFlags.js +76 -76
  336. package/src/util/AttachmentFlags.js +38 -38
  337. package/src/util/BitField.js +170 -170
  338. package/src/util/ChannelFlags.js +45 -45
  339. package/src/util/Constants.js +1914 -1773
  340. package/src/util/DataResolver.js +146 -145
  341. package/src/util/Formatters.js +228 -228
  342. package/src/util/GuildMemberFlags.js +43 -43
  343. package/src/util/Intents.js +74 -74
  344. package/src/util/InviteFlags.js +34 -29
  345. package/src/util/LimitedCollection.js +131 -131
  346. package/src/util/MessageFlags.js +63 -54
  347. package/src/util/Options.js +358 -336
  348. package/src/util/Permissions.js +202 -202
  349. package/src/util/PremiumUsageFlags.js +31 -31
  350. package/src/util/PurchasedFlags.js +33 -33
  351. package/src/util/RemoteAuth.js +382 -379
  352. package/src/util/RoleFlags.js +37 -37
  353. package/src/util/SnowflakeUtil.js +92 -92
  354. package/src/util/Speaking.js +33 -0
  355. package/src/util/Sweepers.js +466 -466
  356. package/src/util/SystemChannelFlags.js +55 -55
  357. package/src/util/ThreadMemberFlags.js +30 -30
  358. package/src/util/UserFlags.js +104 -104
  359. package/src/util/Util.js +1048 -889
  360. package/typings/enums.d.ts +439 -297
  361. package/typings/index.d.ts +8247 -7432
  362. package/typings/rawDataTypes.d.ts +403 -342
  363. package/src/structures/MessagePoll.js +0 -238
@@ -0,0 +1,1249 @@
1
+ 'use strict';
2
+
3
+ const EventEmitter = require('events');
4
+ const { getCiphers } = require('node:crypto');
5
+ const { setTimeout } = require('node:timers');
6
+ const { Collection } = require('@discordjs/collection');
7
+ const VoiceUDP = require('./networking/VoiceUDPClient');
8
+ const VoiceWebSocket = require('./networking/VoiceWebSocket');
9
+ const MediaPlayer = require('./player/MediaPlayer');
10
+ const VoiceReceiver = require('./receiver/Receiver');
11
+ const { parseStreamKey } = require('./util/Function');
12
+ const PlayInterface = require('./util/PlayInterface');
13
+ const Silence = require('./util/Silence');
14
+ const { Error } = require('../../errors');
15
+ const { Opcodes, VoiceOpcodes, VoiceStatus, Events } = require('../../util/Constants');
16
+ const Speaking = require('../../util/Speaking');
17
+ const Util = require('../../util/Util');
18
+
19
+ // Workaround for Discord now requiring silence to be sent before being able to receive audio
20
+ class SingleSilence extends Silence {
21
+ _read() {
22
+ super._read();
23
+ this.push(null);
24
+ }
25
+ }
26
+
27
+ const SUPPORTED_MODES = ['aead_xchacha20_poly1305_rtpsize'];
28
+
29
+ // Just in case there's some system that doesn't come with aes-256-gcm, conditionally add it as supported
30
+ if (getCiphers().includes('aes-256-gcm')) {
31
+ SUPPORTED_MODES.unshift('aead_aes256_gcm_rtpsize');
32
+ }
33
+
34
+ const SUPPORTED_CODECS = ['VP8', 'H264'];
35
+
36
+ /**
37
+ * Represents a connection to a guild's voice server.
38
+ * ```js
39
+ * // Obtained using:
40
+ * client.voice.joinChannel(channel)
41
+ * .then(connection => {
42
+ *
43
+ * });
44
+ * ```
45
+ * @extends {EventEmitter}
46
+ * @implements {PlayInterface}
47
+ */
48
+ class VoiceConnection extends EventEmitter {
49
+ constructor(voiceManager, channel) {
50
+ super();
51
+
52
+ /**
53
+ * The voice manager that instantiated this connection
54
+ * @type {ClientVoiceManager}
55
+ */
56
+ this.voiceManager = voiceManager;
57
+
58
+ /**
59
+ * The voice channel this connection is currently serving
60
+ * @type {VoiceChannel}
61
+ */
62
+ this.channel = channel;
63
+
64
+ /**
65
+ * The current status of the voice connection
66
+ * @type {VoiceStatus}
67
+ */
68
+ this.status = VoiceStatus.AUTHENTICATING;
69
+
70
+ /**
71
+ * Our current speaking state
72
+ * @type {Readonly<Speaking>}
73
+ */
74
+ this.speaking = new Speaking().freeze();
75
+
76
+ /**
77
+ * Our current video state
78
+ * @type {boolean | null}
79
+ */
80
+ this.videoStatus = null;
81
+
82
+ /**
83
+ * The authentication data needed to connect to the voice server
84
+ * @type {Object}
85
+ * @private
86
+ */
87
+ this.authentication = {};
88
+
89
+ /**
90
+ * The audio player for this voice connection
91
+ * @type {MediaPlayer}
92
+ */
93
+ this.player = new MediaPlayer(this, this.constructor.name === 'StreamConnection');
94
+
95
+ this.player.on('debug', m => {
96
+ /**
97
+ * Debug info from the connection.
98
+ * @event VoiceConnection#debug
99
+ * @param {string} message The debug message
100
+ */
101
+ this.emit('debug', `media player - ${m}`);
102
+ });
103
+
104
+ this.player.on('error', e => {
105
+ /**
106
+ * Warning info from the connection.
107
+ * @event VoiceConnection#warn
108
+ * @param {string|Error} warning The warning
109
+ */
110
+ this.emit('warn', e);
111
+ });
112
+
113
+ this.once('closing', () => this.player.destroy());
114
+
115
+ /**
116
+ * Map SSRC values to user IDs
117
+ * @type {Map<number, { userId: Snowflake, speaking: boolean, hasVideo: boolean }>}
118
+ * @private
119
+ */
120
+ this.ssrcMap = new Map();
121
+
122
+ /**
123
+ * Tracks which users are talking
124
+ * @type {Map<Snowflake, Readonly<Speaking>>}
125
+ * @private
126
+ */
127
+ this._speaking = new Map();
128
+
129
+ /**
130
+ * Object that wraps contains the `ws` and `udp` sockets of this voice connection
131
+ * @type {Object}
132
+ * @private
133
+ */
134
+ this.sockets = {};
135
+
136
+ /**
137
+ * The voice receiver of this connection
138
+ * @type {VoiceReceiver}
139
+ */
140
+ this.receiver = new VoiceReceiver(this);
141
+
142
+ /**
143
+ * Video codec
144
+ * * `VP8`
145
+ * * `VP9` (Not supported for encoding & decoding)
146
+ * * `H264`
147
+ * * `H265` (Not supported for encoding & decoding)
148
+ * * `AV1` (Not supported for encoding & decoding)
149
+ * @typedef {string} VideoCodec
150
+ */
151
+
152
+ /**
153
+ * Video codec (encoded) of this connection
154
+ * @type {VideoCodec}
155
+ */
156
+ this.videoCodec = 'H264';
157
+
158
+ /**
159
+ * Create a stream connection ?
160
+ * @type {?StreamConnection}
161
+ */
162
+ this.streamConnection = null;
163
+
164
+ /**
165
+ * All stream watch connection
166
+ * @type {Collection<Snowflake, StreamConnectionReadonly>}
167
+ */
168
+ this.streamWatchConnection = new Collection();
169
+ }
170
+
171
+ /**
172
+ * The client that instantiated this connection
173
+ * @type {Client}
174
+ * @readonly
175
+ */
176
+ get client() {
177
+ return this.voiceManager.client;
178
+ }
179
+
180
+ /**
181
+ * The current audio dispatcher (if any)
182
+ * @type {?AudioDispatcher}
183
+ * @readonly
184
+ */
185
+ get dispatcher() {
186
+ return this.player.dispatcher;
187
+ }
188
+
189
+ /**
190
+ * The current video dispatcher (if any)
191
+ * @type {?VideoDispatcher}
192
+ * @readonly
193
+ */
194
+ get videoDispatcher() {
195
+ return this.player.videoDispatcher;
196
+ }
197
+
198
+ /**
199
+ * Sets whether the voice connection should display as "speaking", "soundshare" or "none".
200
+ * @param {BitFieldResolvable} value The new speaking state
201
+ */
202
+ setSpeaking(value) {
203
+ if (this.speaking.equals(value)) return;
204
+ if (this.status !== VoiceStatus.CONNECTED) return;
205
+ this.speaking = new Speaking(value).freeze();
206
+ this.sockets.ws
207
+ .sendPacket({
208
+ op: VoiceOpcodes.SPEAKING,
209
+ d: {
210
+ speaking: this.speaking.bitfield,
211
+ delay: 0,
212
+ ssrc: this.authentication.ssrc,
213
+ },
214
+ })
215
+ .catch(e => {
216
+ this.emit('debug', e);
217
+ });
218
+ }
219
+
220
+ /**
221
+ * Set video codec before select protocol
222
+ * @param {VideoCodec} value Codec
223
+ * @returns {VoiceConnection}
224
+ */
225
+ setVideoCodec(value) {
226
+ if (!SUPPORTED_CODECS.includes(value)) throw new Error('INVALID_VIDEO_CODEC', SUPPORTED_CODECS);
227
+ this.videoCodec = value;
228
+ return this;
229
+ }
230
+
231
+ /**
232
+ * Sets video status
233
+ * @param {boolean} value Video on or off
234
+ */
235
+ setVideoStatus(value) {
236
+ if (value === this.videoStatus) return;
237
+ if (this.status !== VoiceStatus.CONNECTED) return;
238
+ this.videoStatus = value;
239
+ if (!value) {
240
+ this.sockets.ws
241
+ .sendPacket({
242
+ op: VoiceOpcodes.SOURCES,
243
+ d: {
244
+ audio_ssrc: this.authentication.ssrc,
245
+ video_ssrc: 0,
246
+ rtx_ssrc: 0,
247
+ streams: [],
248
+ },
249
+ })
250
+ .catch(e => {
251
+ this.emit('debug', e);
252
+ });
253
+ } else {
254
+ this.sockets.ws
255
+ .sendPacket({
256
+ op: VoiceOpcodes.SOURCES,
257
+ d: {
258
+ audio_ssrc: this.authentication.ssrc,
259
+ video_ssrc: this.authentication.ssrc + 1,
260
+ rtx_ssrc: this.authentication.ssrc + 2,
261
+ streams: [
262
+ {
263
+ type: 'video',
264
+ rid: '100',
265
+ ssrc: this.authentication.ssrc + 1,
266
+ active: true,
267
+ quality: 100,
268
+ rtx_ssrc: this.authentication.ssrc + 2,
269
+ max_bitrate: 8000000,
270
+ max_framerate: 60,
271
+ max_resolution: {
272
+ type: 'source',
273
+ width: 0,
274
+ height: 0,
275
+ },
276
+ },
277
+ ],
278
+ },
279
+ })
280
+ .catch(e => {
281
+ this.emit('debug', e);
282
+ });
283
+ }
284
+ }
285
+
286
+ /**
287
+ * The voice state of this connection
288
+ * @type {?VoiceState}
289
+ */
290
+ get voice() {
291
+ return this.client.user.voice;
292
+ }
293
+
294
+ /**
295
+ * Sends a request to the main gateway to join a voice channel.
296
+ * @param {Object} [options] The options to provide
297
+ * @returns {Promise<Shard>}
298
+ * @private
299
+ */
300
+ sendVoiceStateUpdate(options = {}) {
301
+ options = Util.mergeDefault(
302
+ {
303
+ guild_id: this.channel.guild?.id || null,
304
+ channel_id: this.channel.id,
305
+ self_mute: this.voice ? this.voice.selfMute : false,
306
+ self_deaf: this.voice ? this.voice.selfDeaf : false,
307
+ self_video: this.voice ? this.voice.selfVideo : false,
308
+ flags: 2,
309
+ },
310
+ options,
311
+ );
312
+
313
+ this.emit('debug', `Sending voice state update: ${JSON.stringify(options)}`);
314
+
315
+ return this.channel.client.ws.broadcast({
316
+ op: Opcodes.VOICE_STATE_UPDATE,
317
+ d: options,
318
+ });
319
+ }
320
+
321
+ /**
322
+ * Set the token and endpoint required to connect to the voice servers.
323
+ * @param {string} token The voice token
324
+ * @param {string} endpoint The voice endpoint
325
+ * @returns {void}
326
+ * @private
327
+ */
328
+ setTokenAndEndpoint(token, endpoint) {
329
+ this.emit('debug', `Token "${token}" and endpoint "${endpoint}"`);
330
+ if (!endpoint) {
331
+ // Signifies awaiting endpoint stage
332
+ return;
333
+ }
334
+
335
+ if (!token) {
336
+ this.authenticateFailed('VOICE_TOKEN_ABSENT');
337
+ return;
338
+ }
339
+
340
+ endpoint = endpoint.match(/([^:]*)/)[0];
341
+ this.emit('debug', `Endpoint resolved as ${endpoint}`);
342
+
343
+ if (!endpoint) {
344
+ this.authenticateFailed('VOICE_INVALID_ENDPOINT');
345
+ return;
346
+ }
347
+
348
+ if (this.status === VoiceStatus.AUTHENTICATING) {
349
+ this.authentication.token = token;
350
+ this.authentication.endpoint = endpoint;
351
+ this.checkAuthenticated();
352
+ } else if (token !== this.authentication.token || endpoint !== this.authentication.endpoint) {
353
+ this.reconnect(token, endpoint);
354
+ }
355
+ }
356
+
357
+ /**
358
+ * Sets the Session ID for the connection.
359
+ * @param {string} sessionId The voice session ID
360
+ * @private
361
+ */
362
+ setSessionId(sessionId) {
363
+ this.emit('debug', `Setting sessionId ${sessionId} (stored as "${this.authentication.sessionId}")`);
364
+ if (!sessionId) {
365
+ this.authenticateFailed('VOICE_SESSION_ABSENT');
366
+ return;
367
+ }
368
+
369
+ if (this.status === VoiceStatus.AUTHENTICATING) {
370
+ this.authentication.sessionId = sessionId;
371
+ this.checkAuthenticated();
372
+ } else if (sessionId !== this.authentication.sessionId) {
373
+ this.authentication.sessionId = sessionId;
374
+ /**
375
+ * Emitted when a new session ID is received.
376
+ * @event VoiceConnection#newSession
377
+ * @private
378
+ */
379
+ this.emit('newSession', sessionId);
380
+ }
381
+ }
382
+
383
+ /**
384
+ * Checks whether the voice connection is authenticated.
385
+ * @private
386
+ */
387
+ checkAuthenticated() {
388
+ const { token, endpoint, sessionId } = this.authentication;
389
+ this.emit('debug', `Authenticated with sessionId ${sessionId}`);
390
+ if (token && endpoint && sessionId) {
391
+ this.status = VoiceStatus.CONNECTING;
392
+ /**
393
+ * Emitted when we successfully initiate a voice connection.
394
+ * @event VoiceConnection#authenticated
395
+ */
396
+ this.emit('authenticated');
397
+ this.connect();
398
+ }
399
+ }
400
+
401
+ /**
402
+ * Invoked when we fail to initiate a voice connection.
403
+ * @param {string} reason The reason for failure
404
+ * @private
405
+ */
406
+ authenticateFailed(reason) {
407
+ clearTimeout(this.connectTimeout);
408
+ this.emit('debug', `Authenticate failed - ${reason}`);
409
+ if (this.status === VoiceStatus.AUTHENTICATING) {
410
+ /**
411
+ * Emitted when we fail to initiate a voice connection.
412
+ * @event VoiceConnection#failed
413
+ * @param {Error} error The encountered error
414
+ */
415
+ this.emit('failed', new Error(reason));
416
+ } else {
417
+ /**
418
+ * Emitted whenever the connection encounters an error.
419
+ * @event VoiceConnection#error
420
+ * @param {Error} error The encountered error
421
+ */
422
+ this.emit('error', new Error(reason));
423
+ }
424
+ this.status = VoiceStatus.DISCONNECTED;
425
+ }
426
+
427
+ /**
428
+ * Move to a different voice channel in the same guild.
429
+ * @param {VoiceChannel} channel The channel to move to
430
+ * @private
431
+ */
432
+ updateChannel(channel) {
433
+ this.channel = channel;
434
+ this.sendVoiceStateUpdate();
435
+ }
436
+
437
+ /**
438
+ * Attempts to authenticate to the voice server.
439
+ * @param {Object} options Join config
440
+ * @private
441
+ */
442
+ authenticate(options = {}) {
443
+ this.sendVoiceStateUpdate(options);
444
+ this.connectTimeout = setTimeout(() => this.authenticateFailed('VOICE_CONNECTION_TIMEOUT'), 15_000).unref();
445
+ }
446
+
447
+ /**
448
+ * Attempts to reconnect to the voice server (typically after a region change).
449
+ * @param {string} token The voice token
450
+ * @param {string} endpoint The voice endpoint
451
+ * @private
452
+ */
453
+ reconnect(token, endpoint) {
454
+ this.authentication.token = token;
455
+ this.authentication.endpoint = endpoint;
456
+ this.speaking = new Speaking().freeze();
457
+ this.status = VoiceStatus.RECONNECTING;
458
+ this.emit('debug', `Reconnecting to ${endpoint}`);
459
+ /**
460
+ * Emitted when the voice connection is reconnecting (typically after a region change).
461
+ * @event VoiceConnection#reconnecting
462
+ */
463
+ this.emit('reconnecting');
464
+ this.connect();
465
+ }
466
+
467
+ /**
468
+ * Disconnects the voice connection, causing a disconnect and closing event to be emitted.
469
+ */
470
+ disconnect() {
471
+ this.emit('closing');
472
+ this.emit('debug', 'disconnect() triggered');
473
+ clearTimeout(this.connectTimeout);
474
+ const conn = this.voiceManager.connection;
475
+ if (conn === this) this.voiceManager.connection = null;
476
+ this.sendVoiceStateUpdate({
477
+ channel_id: null,
478
+ });
479
+ this._disconnect();
480
+ }
481
+
482
+ /**
483
+ * Internally disconnects (doesn't send disconnect packet).
484
+ * @private
485
+ */
486
+ _disconnect() {
487
+ this.cleanup();
488
+ this.status = VoiceStatus.DISCONNECTED;
489
+ /**
490
+ * Emitted when the voice connection disconnects.
491
+ * @event VoiceConnection#disconnect
492
+ */
493
+ this.emit('disconnect');
494
+ }
495
+
496
+ /**
497
+ * Cleans up after disconnect.
498
+ * @private
499
+ */
500
+ cleanup() {
501
+ this.player.destroy();
502
+ this.speaking = new Speaking().freeze();
503
+ const { ws, udp } = this.sockets;
504
+
505
+ this.emit('debug', 'Connection clean up');
506
+
507
+ if (ws) {
508
+ ws.removeAllListeners('error');
509
+ ws.removeAllListeners('ready');
510
+ ws.removeAllListeners('sessionDescription');
511
+ ws.removeAllListeners('speaking');
512
+ ws.shutdown();
513
+ }
514
+
515
+ if (udp) udp.removeAllListeners('error');
516
+
517
+ this.sockets.ws = null;
518
+ this.sockets.udp = null;
519
+ }
520
+
521
+ /**
522
+ * Connect the voice connection.
523
+ * @private
524
+ */
525
+ connect() {
526
+ this.emit('debug', `Connect triggered`);
527
+ if (this.status !== VoiceStatus.RECONNECTING) {
528
+ if (this.sockets.ws) throw new Error('WS_CONNECTION_EXISTS');
529
+ if (this.sockets.udp) throw new Error('UDP_CONNECTION_EXISTS');
530
+ }
531
+
532
+ if (this.sockets.ws) this.sockets.ws.shutdown();
533
+ if (this.sockets.udp) this.sockets.udp.shutdown();
534
+
535
+ this.sockets.ws = new VoiceWebSocket(this);
536
+ this.sockets.udp = new VoiceUDP(this);
537
+
538
+ const { ws, udp } = this.sockets;
539
+
540
+ ws.on('debug', msg => this.emit('debug', msg));
541
+ udp.on('debug', msg => this.emit('debug', msg));
542
+ ws.on('error', err => this.emit('error', err));
543
+ udp.on('error', err => this.emit('error', err));
544
+ ws.on('ready', this.onReady.bind(this));
545
+ ws.on('sessionDescription', this.onSessionDescription.bind(this));
546
+ ws.on('startSpeaking', this.onStartSpeaking.bind(this));
547
+ ws.on('startStreaming', this.onStartStreaming.bind(this));
548
+
549
+ this.sockets.ws.connect();
550
+ }
551
+
552
+ /**
553
+ * Invoked when the voice websocket is ready.
554
+ * @param {Object} data The received data
555
+ * @private
556
+ */
557
+ onReady(data) {
558
+ Object.assign(this.authentication, data);
559
+ for (let mode of data.modes) {
560
+ if (SUPPORTED_MODES.includes(mode)) {
561
+ this.authentication.mode = mode;
562
+ this.emit('debug', `Selecting the ${mode} mode`);
563
+ break;
564
+ }
565
+ }
566
+ this.sockets.udp.createUDPSocket(data.ip);
567
+ }
568
+
569
+ /**
570
+ * Invoked when a session description is received.
571
+ * @param {Object} data The received data
572
+ * @private
573
+ */
574
+ onSessionDescription(data) {
575
+ Object.assign(this.authentication, data);
576
+ this.status = VoiceStatus.CONNECTED;
577
+ const ready = () => {
578
+ clearTimeout(this.connectTimeout);
579
+ this.emit('debug', `Ready with authentication details: ${JSON.stringify(this.authentication)}`);
580
+ /**
581
+ * Emitted once the connection is ready, when a promise to join a voice channel resolves,
582
+ * the connection will already be ready.
583
+ * @event VoiceConnection#ready
584
+ */
585
+ this.emit('ready');
586
+ };
587
+ if (this.dispatcher || this.videoDispatcher) {
588
+ ready();
589
+ } else {
590
+ // This serves to provide support for voice receive, sending audio is required to receive it.
591
+ const dispatcher = this.playAudio(new SingleSilence(), { type: 'opus', volume: false });
592
+ dispatcher.once('finish', ready);
593
+ }
594
+ }
595
+
596
+ onStartSpeaking({ user_id, ssrc, speaking }) {
597
+ this.ssrcMap.set(+ssrc, {
598
+ ...(this.ssrcMap.get(+ssrc) || {}),
599
+ userId: user_id,
600
+ speaking: speaking,
601
+ });
602
+ }
603
+
604
+ onStartStreaming({ video_ssrc, user_id, audio_ssrc }) {
605
+ this.ssrcMap.set(+audio_ssrc, {
606
+ ...(this.ssrcMap.get(+audio_ssrc) || {}),
607
+ userId: user_id,
608
+ hasVideo: Boolean(video_ssrc), // Maybe ?
609
+ });
610
+ /**
611
+ {
612
+ video_ssrc: 0,
613
+ user_id: 'uid',
614
+ streams: [
615
+ {
616
+ ssrc: 27734,
617
+ rtx_ssrc: 27735,
618
+ rid: '100',
619
+ quality: 100,
620
+ max_resolution: { width: 0, type: 'source', height: 0 },,
621
+ max_framerate: 60,
622
+ active: false
623
+ }
624
+ ],
625
+ audio_ssrc: 27733
626
+ }
627
+ */
628
+ }
629
+
630
+ /**
631
+ * Invoked when a speaking event is received.
632
+ * @param {Object} data The received data
633
+ * @private
634
+ */
635
+ onSpeaking({ user_id, speaking }) {
636
+ speaking = new Speaking(speaking).freeze();
637
+ const guild = this.channel.guild;
638
+ const user = this.client.users.cache.get(user_id);
639
+ const old = this._speaking.get(user_id) || new Speaking(0).freeze();
640
+ this._speaking.set(user_id, speaking);
641
+ /**
642
+ * Emitted whenever a user changes speaking state.
643
+ * @event VoiceConnection#speaking
644
+ * @param {User} user The user that has changed speaking state
645
+ * @param {Readonly<Speaking>} speaking The speaking state of the user
646
+ */
647
+ if (this.status === VoiceStatus.CONNECTED) {
648
+ this.emit('speaking', user, speaking);
649
+ if (!speaking.has(Speaking.FLAGS.SPEAKING)) {
650
+ this.receiver.packets._stoppedSpeaking(user_id);
651
+ }
652
+ }
653
+
654
+ if (guild && user && !speaking.equals(old)) {
655
+ const member = guild.members.cache.get(user);
656
+ if (member) {
657
+ /**
658
+ * Emitted once a guild member changes speaking state.
659
+ * @event Client#guildMemberSpeaking
660
+ * @param {GuildMember} member The member that started/stopped speaking
661
+ * @param {Readonly<Speaking>} speaking The speaking state of the member
662
+ */
663
+ this.client.emit(Events.GUILD_MEMBER_SPEAKING, member, speaking);
664
+ }
665
+ }
666
+ }
667
+
668
+ playAudio() {} // eslint-disable-line no-empty-function
669
+ playVideo() {} // eslint-disable-line no-empty-function
670
+
671
+ /**
672
+ * Create new connection to screenshare stream
673
+ * @returns {Promise<StreamConnection>}
674
+ */
675
+ createStreamConnection() {
676
+ // eslint-disable-next-line consistent-return
677
+ return new Promise((resolve, reject) => {
678
+ if (this.streamConnection) {
679
+ return resolve(this.streamConnection);
680
+ } else {
681
+ const connection = (this.streamConnection = new StreamConnection(this.voiceManager, this.channel, this));
682
+ connection.setVideoCodec(this.videoCodec); // Sync :?
683
+ // Setup event...
684
+ if (!this.eventHook) {
685
+ this.eventHook = true; // Dont listen this event two times :/
686
+ this.channel.client.on('raw', packet => {
687
+ if (typeof packet !== 'object' || !packet.t || !packet.d || !packet.d?.stream_key) {
688
+ return;
689
+ }
690
+ const { t: event, d: data } = packet;
691
+ const StreamKey = parseStreamKey(data.stream_key);
692
+ if (
693
+ StreamKey.userId === this.channel.client.user.id &&
694
+ this.channel.id == StreamKey.channelId &&
695
+ this.streamConnection
696
+ ) {
697
+ // Current user stream
698
+ switch (event) {
699
+ case 'STREAM_CREATE': {
700
+ this.streamConnection.setSessionId(this.authentication.sessionId);
701
+ this.streamConnection.serverId = data.rtc_server_id;
702
+ break;
703
+ }
704
+ case 'STREAM_SERVER_UPDATE': {
705
+ this.streamConnection.setTokenAndEndpoint(data.token, data.endpoint);
706
+ break;
707
+ }
708
+ case 'STREAM_DELETE': {
709
+ this.streamConnection.disconnect();
710
+ break;
711
+ }
712
+ case 'STREAM_UPDATE': {
713
+ this.streamConnection.update(data);
714
+ break;
715
+ }
716
+ }
717
+ }
718
+ if (this.streamWatchConnection.has(StreamKey.userId) && this.channel.id == StreamKey.channelId) {
719
+ const streamConnection = this.streamWatchConnection.get(StreamKey.userId);
720
+ // Watch user stream
721
+ switch (event) {
722
+ case 'STREAM_CREATE': {
723
+ streamConnection.setSessionId(this.authentication.sessionId);
724
+ streamConnection.serverId = data.rtc_server_id;
725
+ break;
726
+ }
727
+ case 'STREAM_SERVER_UPDATE': {
728
+ streamConnection.setTokenAndEndpoint(data.token, data.endpoint);
729
+ break;
730
+ }
731
+ case 'STREAM_DELETE': {
732
+ streamConnection.disconnect();
733
+ streamConnection.receiver.packets.destroyAllStream();
734
+ break;
735
+ }
736
+ case 'STREAM_UPDATE': {
737
+ streamConnection.update(data);
738
+ break;
739
+ }
740
+ }
741
+ }
742
+ });
743
+ }
744
+
745
+ connection.sendSignalScreenshare();
746
+ connection.sendScreenshareState(true);
747
+
748
+ connection.on('debug', msg =>
749
+ this.channel.client.emit(
750
+ 'debug',
751
+ `[VOICE STREAM (${this.channel.guild?.id || this.channel.id}:${connection.status})]: ${msg}`,
752
+ ),
753
+ );
754
+ connection.once('failed', reason => {
755
+ this.streamConnection = null;
756
+ reject(reason);
757
+ });
758
+
759
+ connection.on('error', reject);
760
+
761
+ connection.once('authenticated', () => {
762
+ connection.once('ready', () => {
763
+ resolve(connection);
764
+ connection.removeListener('error', reject);
765
+ });
766
+ connection.once('disconnect', () => {
767
+ this.streamConnection = null;
768
+ });
769
+ });
770
+ }
771
+ });
772
+ }
773
+
774
+ /**
775
+ * Watch user stream
776
+ * @param {UserResolvable} user Discord user
777
+ * @returns {Promise<StreamConnectionReadonly>}
778
+ */
779
+ async joinStreamConnection(user) {
780
+ const userId = this.client.users.resolveId(user);
781
+ // Check if user is streaming
782
+ if (!userId) {
783
+ throw new Error('VOICE_USER_MISSING');
784
+ }
785
+ const voiceState = this.channel.guild?.voiceStates.cache.get(userId) || this.client.voiceStates.cache.get(userId);
786
+ if (!voiceState || !voiceState.streaming) {
787
+ throw new Error('VOICE_USER_NOT_STREAMING');
788
+ }
789
+ // eslint-disable-next-line consistent-return
790
+ return new Promise((resolve, reject) => {
791
+ if (this.streamWatchConnection.has(userId)) {
792
+ return resolve(this.streamWatchConnection.get(userId));
793
+ } else {
794
+ const connection = new StreamConnectionReadonly(this.voiceManager, this.channel, this, userId);
795
+ this.streamWatchConnection.set(userId, connection);
796
+ connection.setVideoCodec(this.videoCodec);
797
+ // Setup event...
798
+ if (!this.eventHook) {
799
+ this.eventHook = true; // Dont listen this event two times :/
800
+ this.channel.client.on('raw', packet => {
801
+ if (typeof packet !== 'object' || !packet.t || !packet.d || !packet.d?.stream_key) {
802
+ return;
803
+ }
804
+ const { t: event, d: data } = packet;
805
+ const StreamKey = parseStreamKey(data.stream_key);
806
+ if (
807
+ StreamKey.userId === this.channel.client.user.id &&
808
+ this.channel.id == StreamKey.channelId &&
809
+ this.streamConnection
810
+ ) {
811
+ // Current user stream
812
+ switch (event) {
813
+ case 'STREAM_CREATE': {
814
+ this.streamConnection.setSessionId(this.authentication.sessionId);
815
+ this.streamConnection.serverId = data.rtc_server_id;
816
+ break;
817
+ }
818
+ case 'STREAM_SERVER_UPDATE': {
819
+ this.streamConnection.setTokenAndEndpoint(data.token, data.endpoint);
820
+ break;
821
+ }
822
+ case 'STREAM_DELETE': {
823
+ this.streamConnection.disconnect();
824
+ break;
825
+ }
826
+ case 'STREAM_UPDATE': {
827
+ this.streamConnection.update(data);
828
+ break;
829
+ }
830
+ }
831
+ }
832
+ if (this.streamWatchConnection.has(StreamKey.userId) && this.channel.id == StreamKey.channelId) {
833
+ const streamConnection = this.streamWatchConnection.get(StreamKey.userId);
834
+ // Watch user stream
835
+ switch (event) {
836
+ case 'STREAM_CREATE': {
837
+ streamConnection.setSessionId(this.authentication.sessionId);
838
+ streamConnection.serverId = data.rtc_server_id;
839
+ break;
840
+ }
841
+ case 'STREAM_SERVER_UPDATE': {
842
+ streamConnection.setTokenAndEndpoint(data.token, data.endpoint);
843
+ break;
844
+ }
845
+ case 'STREAM_DELETE': {
846
+ streamConnection.disconnect();
847
+ streamConnection.receiver.packets.destroyAllStream();
848
+ break;
849
+ }
850
+ case 'STREAM_UPDATE': {
851
+ streamConnection.update(data);
852
+ break;
853
+ }
854
+ }
855
+ }
856
+ });
857
+ }
858
+
859
+ connection.sendSignalScreenshare();
860
+
861
+ connection.on('debug', msg =>
862
+ this.channel.client.emit(
863
+ 'debug',
864
+ `[VOICE STREAM WATCH (${userId}>${this.channel.guild?.id || this.channel.id}:${
865
+ connection.status
866
+ })]: ${msg}`,
867
+ ),
868
+ );
869
+ connection.once('failed', reason => {
870
+ this.streamWatchConnection.delete(userId);
871
+ reject(reason);
872
+ });
873
+
874
+ connection.on('error', reject);
875
+
876
+ connection.once('authenticated', () => {
877
+ connection.once('ready', () => {
878
+ resolve(connection);
879
+ connection.removeListener('error', reject);
880
+ });
881
+ connection.once('disconnect', () => {
882
+ this.streamWatchConnection.delete(userId);
883
+ });
884
+ });
885
+ }
886
+ });
887
+ }
888
+
889
+ /**
890
+ * @event VoiceConnection#streamUpdate
891
+ * @description Emitted when the StreamConnection or StreamConnectionReadonly
892
+ * state changes, providing the previous and current stream state.
893
+ *
894
+ * @param {StreamState} oldData - The previous state of the stream.
895
+ * @param {StreamState} newData - The current state of the stream.
896
+ *
897
+ * @typedef {Object} StreamState
898
+ * @property {boolean} isPaused - Indicates whether the stream is currently paused.
899
+ * @property {string|null} region - The region where the stream is hosted, or null if not specified.
900
+ * @property {Snowflake[]} viewerIds - An array of Snowflake IDs representing the viewers connected to the stream.
901
+ */
902
+ }
903
+
904
+ /**
905
+ * Represents a connection to a guild's voice server.
906
+ * ```js
907
+ * // Obtained using:
908
+ * client.voice.joinChannel(channel)
909
+ * .then(connection => connection.createStreamConnection())
910
+ * .then(connection => {
911
+ *
912
+ * });
913
+ * ```
914
+ * @extends {VoiceConnection}
915
+ */
916
+ class StreamConnection extends VoiceConnection {
917
+ #requestDisconnect = false;
918
+ /**
919
+ * @param {ClientVoiceManager} voiceManager Voice manager
920
+ * @param {Channel} channel any channel (joinable)
921
+ * @param {VoiceConnection} voiceConnection parent
922
+ */
923
+ constructor(voiceManager, channel, voiceConnection) {
924
+ super(voiceManager, channel);
925
+
926
+ /**
927
+ * Current voice connection
928
+ * @type {VoiceConnection}
929
+ */
930
+ this.voiceConnection = voiceConnection;
931
+
932
+ Object.defineProperty(this, 'voiceConnection', {
933
+ value: voiceConnection,
934
+ writable: false,
935
+ });
936
+
937
+ /**
938
+ * Server Id
939
+ * @type {string | null}
940
+ */
941
+ this.serverId = null;
942
+
943
+ /**
944
+ * Stream state
945
+ * @type {boolean | null}
946
+ */
947
+ this.isPaused = null;
948
+
949
+ /**
950
+ * Viewer IDs
951
+ * @type {Snowflake[]}
952
+ */
953
+ this.viewerIds = [];
954
+
955
+ /**
956
+ * Voice region name
957
+ * @type {string | null}
958
+ */
959
+ this.region = null;
960
+ }
961
+
962
+ createStreamConnection() {
963
+ return Promise.resolve(this);
964
+ }
965
+
966
+ joinStreamConnection() {
967
+ throw new Error('STREAM_CANNOT_JOIN');
968
+ }
969
+
970
+ get streamConnection() {
971
+ return this;
972
+ }
973
+
974
+ set streamConnection(value) {
975
+ // Why ?
976
+ }
977
+
978
+ get streamWatchConnection() {
979
+ return new Collection();
980
+ }
981
+
982
+ set streamWatchConnection(value) {
983
+ // Why ?
984
+ }
985
+
986
+ disconnect() {
987
+ if (this.#requestDisconnect) return;
988
+ this.emit('closing');
989
+ this.emit('debug', 'Stream: disconnect() triggered');
990
+ clearTimeout(this.connectTimeout);
991
+ if (this.voiceConnection.streamConnection === this) this.voiceConnection.streamConnection = null;
992
+ this.sendStopScreenshare();
993
+ this._disconnect();
994
+ }
995
+
996
+ /**
997
+ * Create new stream connection (WS packet)
998
+ * @returns {void}
999
+ */
1000
+ sendSignalScreenshare() {
1001
+ const data = {
1002
+ type: ['DM', 'GROUP_DM'].includes(this.channel.type) ? 'call' : 'guild',
1003
+ guild_id: this.channel.guild?.id || null,
1004
+ channel_id: this.channel.id,
1005
+ preferred_region: null,
1006
+ };
1007
+ this.emit('debug', `Signal Stream: ${JSON.stringify(data)}`);
1008
+ return this.channel.client.ws.broadcast({
1009
+ op: Opcodes.STREAM_CREATE,
1010
+ d: data,
1011
+ });
1012
+ }
1013
+
1014
+ /**
1015
+ * Send screenshare state... (WS)
1016
+ * @param {boolean} isPaused screenshare paused ?
1017
+ * @returns {void}
1018
+ */
1019
+ sendScreenshareState(isPaused = false) {
1020
+ if (isPaused == this.isPaused) return;
1021
+ this.emit(
1022
+ 'streamUpdate',
1023
+ {
1024
+ isPaused: this.isPaused,
1025
+ region: this.region,
1026
+ viewerIds: this.viewerIds,
1027
+ },
1028
+ {
1029
+ isPaused,
1030
+ region: this.region,
1031
+ viewerIds: this.viewerIds,
1032
+ },
1033
+ );
1034
+ this.isPaused = isPaused;
1035
+ this.channel.client.ws.broadcast({
1036
+ op: Opcodes.STREAM_SET_PAUSED,
1037
+ d: {
1038
+ stream_key: this.streamKey,
1039
+ paused: isPaused,
1040
+ },
1041
+ });
1042
+ }
1043
+
1044
+ /**
1045
+ * Stop screenshare, delete this connection (WS)
1046
+ * @returns {void}
1047
+ * @private Using StreamConnection#disconnect()
1048
+ */
1049
+ sendStopScreenshare() {
1050
+ this.#requestDisconnect = true;
1051
+ this.channel.client.ws.broadcast({
1052
+ op: Opcodes.STREAM_DELETE,
1053
+ d: {
1054
+ stream_key: this.streamKey,
1055
+ },
1056
+ });
1057
+ }
1058
+
1059
+ update(data) {
1060
+ this.emit(
1061
+ 'streamUpdate',
1062
+ {
1063
+ isPaused: this.isPaused,
1064
+ region: this.region,
1065
+ viewerIds: this.viewerIds.slice(),
1066
+ },
1067
+ {
1068
+ isPaused: data.paused,
1069
+ region: data.region,
1070
+ viewerIds: data.viewer_ids,
1071
+ },
1072
+ );
1073
+ this.viewerIds = data.viewer_ids;
1074
+ this.region = data.region;
1075
+ }
1076
+
1077
+ /**
1078
+ * Current stream key
1079
+ * @type {string}
1080
+ */
1081
+ get streamKey() {
1082
+ return `${['DM', 'GROUP_DM'].includes(this.channel.type) ? 'call' : `guild:${this.channel.guild.id}`}:${
1083
+ this.channel.id
1084
+ }:${this.channel.client.user.id}`;
1085
+ }
1086
+ }
1087
+
1088
+ /**
1089
+ * Represents a connection to a guild's voice server.
1090
+ * ```js
1091
+ * // Obtained using:
1092
+ * client.voice.joinChannel(channel)
1093
+ * .then(connection => connection.createStreamConnection())
1094
+ * .then(connection => {
1095
+ *
1096
+ * });
1097
+ * ```
1098
+ * @extends {VoiceConnection}
1099
+ */
1100
+ class StreamConnectionReadonly extends VoiceConnection {
1101
+ #requestDisconnect = false;
1102
+ /**
1103
+ * @param {ClientVoiceManager} voiceManager Voice manager
1104
+ * @param {Channel} channel any channel (joinable)
1105
+ * @param {VoiceConnection} voiceConnection parent
1106
+ * @param {Snowflake} userId User ID
1107
+ */
1108
+ constructor(voiceManager, channel, voiceConnection, userId) {
1109
+ super(voiceManager, channel);
1110
+
1111
+ /**
1112
+ * Current voice connection
1113
+ * @type {VoiceConnection}
1114
+ */
1115
+ this.voiceConnection = voiceConnection;
1116
+
1117
+ /**
1118
+ * User ID (who started the stream)
1119
+ * @type {Snowflake}
1120
+ */
1121
+ this.userId = userId;
1122
+
1123
+ Object.defineProperty(this, 'voiceConnection', {
1124
+ value: voiceConnection,
1125
+ writable: false,
1126
+ });
1127
+
1128
+ /**
1129
+ * Server Id
1130
+ * @type {string | null}
1131
+ */
1132
+ this.serverId = null;
1133
+
1134
+ /**
1135
+ * Stream state
1136
+ * @type {boolean}
1137
+ */
1138
+ this.isPaused = false;
1139
+
1140
+ /**
1141
+ * Viewer IDs
1142
+ * @type {Snowflake[]}
1143
+ */
1144
+ this.viewerIds = [];
1145
+
1146
+ /**
1147
+ * Voice region name
1148
+ * @type {string | null}
1149
+ */
1150
+ this.region = null;
1151
+ }
1152
+
1153
+ createStreamConnection() {
1154
+ throw new Error('STREAM_CONNECTION_READONLY');
1155
+ }
1156
+
1157
+ joinStreamConnection() {
1158
+ return Promise.resolve(this);
1159
+ }
1160
+
1161
+ get streamConnection() {
1162
+ return null;
1163
+ }
1164
+
1165
+ set streamConnection(value) {
1166
+ // Why ?
1167
+ }
1168
+
1169
+ get streamWatchConnection() {
1170
+ return new Collection();
1171
+ }
1172
+
1173
+ set streamWatchConnection(value) {
1174
+ // Why ?
1175
+ }
1176
+
1177
+ disconnect() {
1178
+ if (this.#requestDisconnect) return;
1179
+ this.emit('closing');
1180
+ this.emit('debug', 'Stream: disconnect() triggered');
1181
+ clearTimeout(this.connectTimeout);
1182
+ this.voiceConnection.streamWatchConnection.delete(this.userId);
1183
+ this.sendStopScreenshare();
1184
+ this._disconnect();
1185
+ }
1186
+
1187
+ /**
1188
+ * Create new stream connection (WS packet)
1189
+ * @returns {void}
1190
+ */
1191
+ sendSignalScreenshare() {
1192
+ this.emit('debug', `Signal Stream Watch: ${this.streamKey}`);
1193
+ return this.channel.client.ws.broadcast({
1194
+ op: Opcodes.STREAM_WATCH,
1195
+ d: {
1196
+ stream_key: this.streamKey,
1197
+ },
1198
+ });
1199
+ }
1200
+
1201
+ /**
1202
+ * Stop screenshare, delete this connection (WS)
1203
+ * @returns {void}
1204
+ * @private Using StreamConnection#disconnect()
1205
+ */
1206
+ sendStopScreenshare() {
1207
+ this.#requestDisconnect = true;
1208
+ this.channel.client.ws.broadcast({
1209
+ op: Opcodes.STREAM_DELETE,
1210
+ d: {
1211
+ stream_key: this.streamKey,
1212
+ },
1213
+ });
1214
+ }
1215
+
1216
+ update(data) {
1217
+ this.emit(
1218
+ 'streamUpdate',
1219
+ {
1220
+ isPaused: this.isPaused,
1221
+ region: this.region,
1222
+ viewerIds: this.viewerIds.slice(),
1223
+ },
1224
+ {
1225
+ isPaused: data.paused,
1226
+ region: data.region,
1227
+ viewerIds: data.viewer_ids,
1228
+ },
1229
+ );
1230
+ this.isPaused = data.paused;
1231
+ this.viewerIds = data.viewer_ids;
1232
+ this.region = data.region;
1233
+ }
1234
+
1235
+ /**
1236
+ * Current stream key
1237
+ * @type {string}
1238
+ */
1239
+ get streamKey() {
1240
+ return `${['DM', 'GROUP_DM'].includes(this.channel.type) ? 'call' : `guild:${this.channel.guild.id}`}:${
1241
+ this.channel.id
1242
+ }:${this.userId}`;
1243
+ }
1244
+ }
1245
+
1246
+ PlayInterface.applyToClass(VoiceConnection);
1247
+ PlayInterface.applyToClass(StreamConnection);
1248
+
1249
+ module.exports = VoiceConnection;