rockcord 4.0.0-dev.4

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