@biggy1337/discord-sbjs 1.3.11

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