discord-sb.js 1.0.0

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