@velliajs/discord 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 (317) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +133 -0
  3. package/package.json +82 -0
  4. package/src/client/BaseClient.js +83 -0
  5. package/src/client/Client.js +591 -0
  6. package/src/client/WebhookClient.js +103 -0
  7. package/src/client/actions/Action.js +119 -0
  8. package/src/client/actions/ActionsManager.js +79 -0
  9. package/src/client/actions/ApplicationCommandPermissionsUpdate.js +34 -0
  10. package/src/client/actions/AutoModerationActionExecution.js +26 -0
  11. package/src/client/actions/AutoModerationRuleCreate.js +27 -0
  12. package/src/client/actions/AutoModerationRuleDelete.js +31 -0
  13. package/src/client/actions/AutoModerationRuleUpdate.js +29 -0
  14. package/src/client/actions/ChannelCreate.js +23 -0
  15. package/src/client/actions/ChannelDelete.js +23 -0
  16. package/src/client/actions/ChannelUpdate.js +33 -0
  17. package/src/client/actions/GuildAuditLogEntryCreate.js +29 -0
  18. package/src/client/actions/GuildBanAdd.js +20 -0
  19. package/src/client/actions/GuildBanRemove.js +25 -0
  20. package/src/client/actions/GuildChannelsPositionUpdate.js +21 -0
  21. package/src/client/actions/GuildDelete.js +44 -0
  22. package/src/client/actions/GuildEmojiCreate.js +20 -0
  23. package/src/client/actions/GuildEmojiDelete.js +19 -0
  24. package/src/client/actions/GuildEmojiUpdate.js +20 -0
  25. package/src/client/actions/GuildEmojisUpdate.js +34 -0
  26. package/src/client/actions/GuildIntegrationsUpdate.js +19 -0
  27. package/src/client/actions/GuildMemberRemove.js +31 -0
  28. package/src/client/actions/GuildMemberUpdate.js +44 -0
  29. package/src/client/actions/GuildRoleCreate.js +25 -0
  30. package/src/client/actions/GuildRoleDelete.js +29 -0
  31. package/src/client/actions/GuildRoleUpdate.js +39 -0
  32. package/src/client/actions/GuildRolesPositionUpdate.js +21 -0
  33. package/src/client/actions/GuildScheduledEventCreate.js +27 -0
  34. package/src/client/actions/GuildScheduledEventDelete.js +31 -0
  35. package/src/client/actions/GuildScheduledEventUpdate.js +30 -0
  36. package/src/client/actions/GuildScheduledEventUserAdd.js +32 -0
  37. package/src/client/actions/GuildScheduledEventUserRemove.js +32 -0
  38. package/src/client/actions/GuildStickerCreate.js +20 -0
  39. package/src/client/actions/GuildStickerDelete.js +19 -0
  40. package/src/client/actions/GuildStickerUpdate.js +20 -0
  41. package/src/client/actions/GuildStickersUpdate.js +34 -0
  42. package/src/client/actions/GuildUpdate.js +33 -0
  43. package/src/client/actions/InteractionCreate.js +101 -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 +37 -0
  47. package/src/client/actions/MessageDelete.js +32 -0
  48. package/src/client/actions/MessageDeleteBulk.js +47 -0
  49. package/src/client/actions/MessageReactionAdd.js +55 -0
  50. package/src/client/actions/MessageReactionRemove.js +45 -0
  51. package/src/client/actions/MessageReactionRemoveAll.js +33 -0
  52. package/src/client/actions/MessageReactionRemoveEmoji.js +28 -0
  53. package/src/client/actions/MessageUpdate.js +26 -0
  54. package/src/client/actions/PresenceUpdate.js +42 -0
  55. package/src/client/actions/StageInstanceCreate.js +28 -0
  56. package/src/client/actions/StageInstanceDelete.js +31 -0
  57. package/src/client/actions/StageInstanceUpdate.js +30 -0
  58. package/src/client/actions/ThreadCreate.js +24 -0
  59. package/src/client/actions/ThreadDelete.js +26 -0
  60. package/src/client/actions/ThreadListSync.js +60 -0
  61. package/src/client/actions/ThreadMemberUpdate.js +30 -0
  62. package/src/client/actions/ThreadMembersUpdate.js +47 -0
  63. package/src/client/actions/TypingStart.js +29 -0
  64. package/src/client/actions/UserUpdate.js +36 -0
  65. package/src/client/actions/VoiceStateUpdate.js +43 -0
  66. package/src/client/actions/WebhooksUpdate.js +20 -0
  67. package/src/client/voice/ClientVoiceManager.js +44 -0
  68. package/src/client/websocket/WebSocketManager.js +393 -0
  69. package/src/client/websocket/WebSocketShard.js +231 -0
  70. package/src/client/websocket/handlers/APPLICATION_COMMAND_PERMISSIONS_UPDATE.js +5 -0
  71. package/src/client/websocket/handlers/AUTO_MODERATION_ACTION_EXECUTION.js +5 -0
  72. package/src/client/websocket/handlers/AUTO_MODERATION_RULE_CREATE.js +5 -0
  73. package/src/client/websocket/handlers/AUTO_MODERATION_RULE_DELETE.js +5 -0
  74. package/src/client/websocket/handlers/AUTO_MODERATION_RULE_UPDATE.js +5 -0
  75. package/src/client/websocket/handlers/CHANNEL_CREATE.js +5 -0
  76. package/src/client/websocket/handlers/CHANNEL_DELETE.js +5 -0
  77. package/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js +22 -0
  78. package/src/client/websocket/handlers/CHANNEL_UPDATE.js +16 -0
  79. package/src/client/websocket/handlers/GUILD_AUDIT_LOG_ENTRY_CREATE.js +5 -0
  80. package/src/client/websocket/handlers/GUILD_BAN_ADD.js +5 -0
  81. package/src/client/websocket/handlers/GUILD_BAN_REMOVE.js +5 -0
  82. package/src/client/websocket/handlers/GUILD_CREATE.js +26 -0
  83. package/src/client/websocket/handlers/GUILD_DELETE.js +5 -0
  84. package/src/client/websocket/handlers/GUILD_EMOJIS_UPDATE.js +5 -0
  85. package/src/client/websocket/handlers/GUILD_INTEGRATIONS_UPDATE.js +5 -0
  86. package/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js +39 -0
  87. package/src/client/websocket/handlers/GUILD_MEMBER_ADD.js +20 -0
  88. package/src/client/websocket/handlers/GUILD_MEMBER_REMOVE.js +5 -0
  89. package/src/client/websocket/handlers/GUILD_MEMBER_UPDATE.js +5 -0
  90. package/src/client/websocket/handlers/GUILD_ROLE_CREATE.js +5 -0
  91. package/src/client/websocket/handlers/GUILD_ROLE_DELETE.js +5 -0
  92. package/src/client/websocket/handlers/GUILD_ROLE_UPDATE.js +5 -0
  93. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_CREATE.js +5 -0
  94. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_DELETE.js +5 -0
  95. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_UPDATE.js +5 -0
  96. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_USER_ADD.js +5 -0
  97. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_USER_REMOVE.js +5 -0
  98. package/src/client/websocket/handlers/GUILD_STICKERS_UPDATE.js +5 -0
  99. package/src/client/websocket/handlers/GUILD_UPDATE.js +5 -0
  100. package/src/client/websocket/handlers/INTERACTION_CREATE.js +5 -0
  101. package/src/client/websocket/handlers/INVITE_CREATE.js +5 -0
  102. package/src/client/websocket/handlers/INVITE_DELETE.js +5 -0
  103. package/src/client/websocket/handlers/MESSAGE_CREATE.js +5 -0
  104. package/src/client/websocket/handlers/MESSAGE_DELETE.js +5 -0
  105. package/src/client/websocket/handlers/MESSAGE_DELETE_BULK.js +5 -0
  106. package/src/client/websocket/handlers/MESSAGE_REACTION_ADD.js +5 -0
  107. package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE.js +5 -0
  108. package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_ALL.js +5 -0
  109. package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.js +5 -0
  110. package/src/client/websocket/handlers/MESSAGE_UPDATE.js +16 -0
  111. package/src/client/websocket/handlers/PRESENCE_UPDATE.js +5 -0
  112. package/src/client/websocket/handlers/READY.js +27 -0
  113. package/src/client/websocket/handlers/RESUMED.js +14 -0
  114. package/src/client/websocket/handlers/STAGE_INSTANCE_CREATE.js +5 -0
  115. package/src/client/websocket/handlers/STAGE_INSTANCE_DELETE.js +5 -0
  116. package/src/client/websocket/handlers/STAGE_INSTANCE_UPDATE.js +5 -0
  117. package/src/client/websocket/handlers/THREAD_CREATE.js +5 -0
  118. package/src/client/websocket/handlers/THREAD_DELETE.js +5 -0
  119. package/src/client/websocket/handlers/THREAD_LIST_SYNC.js +5 -0
  120. package/src/client/websocket/handlers/THREAD_MEMBERS_UPDATE.js +5 -0
  121. package/src/client/websocket/handlers/THREAD_MEMBER_UPDATE.js +5 -0
  122. package/src/client/websocket/handlers/THREAD_UPDATE.js +16 -0
  123. package/src/client/websocket/handlers/TYPING_START.js +5 -0
  124. package/src/client/websocket/handlers/USER_UPDATE.js +5 -0
  125. package/src/client/websocket/handlers/VOICE_SERVER_UPDATE.js +6 -0
  126. package/src/client/websocket/handlers/VOICE_STATE_UPDATE.js +5 -0
  127. package/src/client/websocket/handlers/WEBHOOKS_UPDATE.js +5 -0
  128. package/src/client/websocket/handlers/index.js +64 -0
  129. package/src/errors/DJSError.js +48 -0
  130. package/src/errors/ErrorCodes.js +319 -0
  131. package/src/errors/Messages.js +170 -0
  132. package/src/errors/index.js +5 -0
  133. package/src/index.js +213 -0
  134. package/src/managers/ApplicationCommandManager.js +263 -0
  135. package/src/managers/ApplicationCommandPermissionsManager.js +434 -0
  136. package/src/managers/AutoModerationRuleManager.js +288 -0
  137. package/src/managers/BaseGuildEmojiManager.js +80 -0
  138. package/src/managers/BaseManager.js +19 -0
  139. package/src/managers/CachedManager.js +57 -0
  140. package/src/managers/CategoryChannelChildManager.js +77 -0
  141. package/src/managers/ChannelManager.js +128 -0
  142. package/src/managers/DataManager.js +61 -0
  143. package/src/managers/GuildApplicationCommandManager.js +28 -0
  144. package/src/managers/GuildBanManager.js +204 -0
  145. package/src/managers/GuildChannelManager.js +494 -0
  146. package/src/managers/GuildEmojiManager.js +174 -0
  147. package/src/managers/GuildEmojiRoleManager.js +118 -0
  148. package/src/managers/GuildForumThreadManager.js +83 -0
  149. package/src/managers/GuildInviteManager.js +213 -0
  150. package/src/managers/GuildManager.js +283 -0
  151. package/src/managers/GuildMemberManager.js +540 -0
  152. package/src/managers/GuildMemberRoleManager.js +204 -0
  153. package/src/managers/GuildScheduledEventManager.js +297 -0
  154. package/src/managers/GuildStickerManager.js +182 -0
  155. package/src/managers/GuildTextThreadManager.js +91 -0
  156. package/src/managers/MessageManager.js +259 -0
  157. package/src/managers/PermissionOverwriteManager.js +168 -0
  158. package/src/managers/PresenceManager.js +58 -0
  159. package/src/managers/ReactionManager.js +68 -0
  160. package/src/managers/ReactionUserManager.js +77 -0
  161. package/src/managers/RoleManager.js +360 -0
  162. package/src/managers/StageInstanceManager.js +154 -0
  163. package/src/managers/ThreadManager.js +204 -0
  164. package/src/managers/ThreadMemberManager.js +182 -0
  165. package/src/managers/UserManager.js +139 -0
  166. package/src/managers/VoiceStateManager.js +37 -0
  167. package/src/sharding/Shard.js +457 -0
  168. package/src/sharding/ShardClientUtil.js +285 -0
  169. package/src/sharding/ShardingManager.js +326 -0
  170. package/src/structures/ActionRow.js +46 -0
  171. package/src/structures/ActionRowBuilder.js +35 -0
  172. package/src/structures/AnonymousGuild.js +97 -0
  173. package/src/structures/ApplicationCommand.js +606 -0
  174. package/src/structures/ApplicationRoleConnectionMetadata.js +46 -0
  175. package/src/structures/Attachment.js +140 -0
  176. package/src/structures/AttachmentBuilder.js +116 -0
  177. package/src/structures/AutoModerationActionExecution.js +116 -0
  178. package/src/structures/AutoModerationRule.js +284 -0
  179. package/src/structures/AutocompleteInteraction.js +97 -0
  180. package/src/structures/Base.js +43 -0
  181. package/src/structures/BaseChannel.js +160 -0
  182. package/src/structures/BaseGuild.js +119 -0
  183. package/src/structures/BaseGuildEmoji.js +56 -0
  184. package/src/structures/BaseGuildTextChannel.js +186 -0
  185. package/src/structures/BaseGuildVoiceChannel.js +234 -0
  186. package/src/structures/BaseInteraction.js +344 -0
  187. package/src/structures/BaseSelectMenuComponent.js +56 -0
  188. package/src/structures/ButtonBuilder.js +44 -0
  189. package/src/structures/ButtonComponent.js +65 -0
  190. package/src/structures/ButtonInteraction.js +11 -0
  191. package/src/structures/CategoryChannel.js +45 -0
  192. package/src/structures/ChannelSelectMenuBuilder.js +31 -0
  193. package/src/structures/ChannelSelectMenuComponent.js +20 -0
  194. package/src/structures/ChannelSelectMenuInteraction.js +33 -0
  195. package/src/structures/ChatInputCommandInteraction.js +41 -0
  196. package/src/structures/ClientApplication.js +193 -0
  197. package/src/structures/ClientPresence.js +82 -0
  198. package/src/structures/ClientUser.js +185 -0
  199. package/src/structures/CommandInteraction.js +224 -0
  200. package/src/structures/CommandInteractionOptionResolver.js +308 -0
  201. package/src/structures/Component.js +47 -0
  202. package/src/structures/ContextMenuCommandInteraction.js +64 -0
  203. package/src/structures/DMChannel.js +129 -0
  204. package/src/structures/DirectoryChannel.js +36 -0
  205. package/src/structures/Embed.js +220 -0
  206. package/src/structures/EmbedBuilder.js +41 -0
  207. package/src/structures/Emoji.js +108 -0
  208. package/src/structures/ForumChannel.js +264 -0
  209. package/src/structures/Guild.js +1361 -0
  210. package/src/structures/GuildAuditLogs.js +91 -0
  211. package/src/structures/GuildAuditLogsEntry.js +527 -0
  212. package/src/structures/GuildBan.js +59 -0
  213. package/src/structures/GuildChannel.js +457 -0
  214. package/src/structures/GuildEmoji.js +148 -0
  215. package/src/structures/GuildMember.js +518 -0
  216. package/src/structures/GuildPreview.js +193 -0
  217. package/src/structures/GuildPreviewEmoji.js +27 -0
  218. package/src/structures/GuildScheduledEvent.js +439 -0
  219. package/src/structures/GuildTemplate.js +241 -0
  220. package/src/structures/Integration.js +220 -0
  221. package/src/structures/IntegrationApplication.js +85 -0
  222. package/src/structures/InteractionCollector.js +263 -0
  223. package/src/structures/InteractionResponse.js +102 -0
  224. package/src/structures/InteractionWebhook.js +59 -0
  225. package/src/structures/Invite.js +322 -0
  226. package/src/structures/InviteGuild.js +22 -0
  227. package/src/structures/InviteStageInstance.js +87 -0
  228. package/src/structures/MentionableSelectMenuBuilder.js +32 -0
  229. package/src/structures/MentionableSelectMenuComponent.js +11 -0
  230. package/src/structures/MentionableSelectMenuInteraction.js +71 -0
  231. package/src/structures/Message.js +997 -0
  232. package/src/structures/MessageCollector.js +146 -0
  233. package/src/structures/MessageComponentInteraction.js +107 -0
  234. package/src/structures/MessageContextMenuCommandInteraction.js +20 -0
  235. package/src/structures/MessageMentions.js +297 -0
  236. package/src/structures/MessagePayload.js +299 -0
  237. package/src/structures/MessageReaction.js +142 -0
  238. package/src/structures/ModalBuilder.js +34 -0
  239. package/src/structures/ModalSubmitFields.js +55 -0
  240. package/src/structures/ModalSubmitInteraction.js +121 -0
  241. package/src/structures/NewsChannel.js +32 -0
  242. package/src/structures/OAuth2Guild.js +28 -0
  243. package/src/structures/PartialGroupDMChannel.js +60 -0
  244. package/src/structures/PermissionOverwrites.js +196 -0
  245. package/src/structures/Presence.js +372 -0
  246. package/src/structures/ReactionCollector.js +229 -0
  247. package/src/structures/ReactionEmoji.js +31 -0
  248. package/src/structures/Role.js +458 -0
  249. package/src/structures/RoleSelectMenuBuilder.js +31 -0
  250. package/src/structures/RoleSelectMenuComponent.js +11 -0
  251. package/src/structures/RoleSelectMenuInteraction.js +33 -0
  252. package/src/structures/SelectMenuBuilder.js +26 -0
  253. package/src/structures/SelectMenuComponent.js +26 -0
  254. package/src/structures/SelectMenuInteraction.js +26 -0
  255. package/src/structures/SelectMenuOptionBuilder.js +26 -0
  256. package/src/structures/StageChannel.js +112 -0
  257. package/src/structures/StageInstance.js +167 -0
  258. package/src/structures/Sticker.js +272 -0
  259. package/src/structures/StickerPack.js +95 -0
  260. package/src/structures/StringSelectMenuBuilder.js +79 -0
  261. package/src/structures/StringSelectMenuComponent.js +20 -0
  262. package/src/structures/StringSelectMenuInteraction.js +21 -0
  263. package/src/structures/StringSelectMenuOptionBuilder.js +49 -0
  264. package/src/structures/Team.js +117 -0
  265. package/src/structures/TeamMember.js +70 -0
  266. package/src/structures/TextChannel.js +33 -0
  267. package/src/structures/TextInputBuilder.js +31 -0
  268. package/src/structures/TextInputComponent.js +29 -0
  269. package/src/structures/ThreadChannel.js +606 -0
  270. package/src/structures/ThreadMember.js +113 -0
  271. package/src/structures/Typing.js +74 -0
  272. package/src/structures/User.js +331 -0
  273. package/src/structures/UserContextMenuCommandInteraction.js +29 -0
  274. package/src/structures/UserSelectMenuBuilder.js +31 -0
  275. package/src/structures/UserSelectMenuComponent.js +11 -0
  276. package/src/structures/UserSelectMenuInteraction.js +51 -0
  277. package/src/structures/VoiceChannel.js +96 -0
  278. package/src/structures/VoiceRegion.js +46 -0
  279. package/src/structures/VoiceState.js +303 -0
  280. package/src/structures/Webhook.js +481 -0
  281. package/src/structures/WelcomeChannel.js +60 -0
  282. package/src/structures/WelcomeScreen.js +49 -0
  283. package/src/structures/Widget.js +88 -0
  284. package/src/structures/WidgetMember.js +99 -0
  285. package/src/structures/interfaces/Application.js +108 -0
  286. package/src/structures/interfaces/Collector.js +335 -0
  287. package/src/structures/interfaces/InteractionResponses.js +320 -0
  288. package/src/structures/interfaces/TextBasedChannel.js +413 -0
  289. package/src/util/APITypes.js +456 -0
  290. package/src/util/ActivityFlagsBitField.js +26 -0
  291. package/src/util/ApplicationFlagsBitField.js +26 -0
  292. package/src/util/BitField.js +176 -0
  293. package/src/util/ChannelFlagsBitField.js +41 -0
  294. package/src/util/Channels.js +150 -0
  295. package/src/util/Colors.js +73 -0
  296. package/src/util/Components.js +152 -0
  297. package/src/util/Constants.js +230 -0
  298. package/src/util/DataResolver.js +140 -0
  299. package/src/util/Enums.js +13 -0
  300. package/src/util/Events.js +160 -0
  301. package/src/util/Formatters.js +413 -0
  302. package/src/util/GuildMemberFlagsBitField.js +41 -0
  303. package/src/util/IntentsBitField.js +34 -0
  304. package/src/util/LimitedCollection.js +68 -0
  305. package/src/util/MessageFlagsBitField.js +32 -0
  306. package/src/util/Options.js +216 -0
  307. package/src/util/Partials.js +44 -0
  308. package/src/util/PermissionsBitField.js +104 -0
  309. package/src/util/ShardEvents.js +27 -0
  310. package/src/util/Status.js +33 -0
  311. package/src/util/Sweepers.js +467 -0
  312. package/src/util/SystemChannelFlagsBitField.js +43 -0
  313. package/src/util/ThreadMemberFlagsBitField.js +31 -0
  314. package/src/util/Transformers.js +36 -0
  315. package/src/util/UserFlagsBitField.js +32 -0
  316. package/src/util/Util.js +394 -0
  317. package/src/util/WebSocketShardEvents.js +25 -0
@@ -0,0 +1,36 @@
1
+ 'use strict';
2
+
3
+ const Action = require('./Action');
4
+ const Events = require('../../util/Events');
5
+
6
+ class UserUpdateAction extends Action {
7
+ handle(data) {
8
+ const client = this.client;
9
+
10
+ const newUser = data.id === client.user.id ? client.user : client.users.cache.get(data.id);
11
+ const oldUser = newUser._update(data);
12
+
13
+ if (!oldUser.equals(newUser)) {
14
+ /**
15
+ * Emitted whenever a user's details (e.g. username) are changed.
16
+ * Triggered by the Discord gateway events {@link Events.UserUpdate},
17
+ * {@link Events.GuildMemberUpdate}, and {@link Events.PresenceUpdate}.
18
+ * @event Client#userUpdate
19
+ * @param {User} oldUser The user before the update
20
+ * @param {User} newUser The user after the update
21
+ */
22
+ client.emit(Events.UserUpdate, oldUser, newUser);
23
+ return {
24
+ old: oldUser,
25
+ updated: newUser,
26
+ };
27
+ }
28
+
29
+ return {
30
+ old: null,
31
+ updated: null,
32
+ };
33
+ }
34
+ }
35
+
36
+ module.exports = UserUpdateAction;
@@ -0,0 +1,43 @@
1
+ 'use strict';
2
+
3
+ const Action = require('./Action');
4
+ const VoiceState = require('../../structures/VoiceState');
5
+ const Events = require('../../util/Events');
6
+
7
+ class VoiceStateUpdate extends Action {
8
+ handle(data) {
9
+ const client = this.client;
10
+ const guild = client.guilds.cache.get(data.guild_id);
11
+ if (guild) {
12
+ // Update the state
13
+ const oldState =
14
+ guild.voiceStates.cache.get(data.user_id)?._clone() ?? new VoiceState(guild, { user_id: data.user_id });
15
+
16
+ const newState = guild.voiceStates._add(data);
17
+
18
+ // Get the member
19
+ let member = guild.members.cache.get(data.user_id);
20
+ if (member && data.member) {
21
+ member._patch(data.member);
22
+ } else if (data.member?.user && data.member.joined_at) {
23
+ member = guild.members._add(data.member);
24
+ }
25
+
26
+ // Emit event
27
+ if (member?.user.id === client.user.id) {
28
+ client.emit('debug', `[VOICE] received voice state update: ${JSON.stringify(data)}`);
29
+ client.voice.onVoiceStateUpdate(data);
30
+ }
31
+
32
+ /**
33
+ * Emitted whenever a member changes voice state - e.g. joins/leaves a channel, mutes/unmutes.
34
+ * @event Client#voiceStateUpdate
35
+ * @param {VoiceState} oldState The voice state before the update
36
+ * @param {VoiceState} newState The voice state after the update
37
+ */
38
+ client.emit(Events.VoiceStateUpdate, oldState, newState);
39
+ }
40
+ }
41
+ }
42
+
43
+ module.exports = VoiceStateUpdate;
@@ -0,0 +1,20 @@
1
+ 'use strict';
2
+
3
+ const Action = require('./Action');
4
+ const Events = require('../../util/Events');
5
+
6
+ class WebhooksUpdate extends Action {
7
+ handle(data) {
8
+ const client = this.client;
9
+ const channel = client.channels.cache.get(data.channel_id);
10
+ /**
11
+ * Emitted whenever a channel has its webhooks changed.
12
+ * @event Client#webhookUpdate
13
+ * @param {TextChannel|NewsChannel|VoiceChannel|StageChannel|ForumChannel} channel
14
+ * The channel that had a webhook update
15
+ */
16
+ if (channel) client.emit(Events.WebhooksUpdate, channel);
17
+ }
18
+ }
19
+
20
+ module.exports = WebhooksUpdate;
@@ -0,0 +1,44 @@
1
+ 'use strict';
2
+
3
+ const Events = require('../../util/Events');
4
+
5
+ /**
6
+ * Manages voice connections for the client
7
+ */
8
+ class ClientVoiceManager {
9
+ constructor(client) {
10
+ /**
11
+ * The client that instantiated this voice manager
12
+ * @type {Client}
13
+ * @readonly
14
+ * @name ClientVoiceManager#client
15
+ */
16
+ Object.defineProperty(this, 'client', { value: client });
17
+
18
+ /**
19
+ * Maps guild ids to voice adapters created for use with @discordjs/voice.
20
+ * @type {Map<Snowflake, Object>}
21
+ */
22
+ this.adapters = new Map();
23
+
24
+ client.on(Events.ShardDisconnect, (_, shardId) => {
25
+ for (const [guildId, adapter] of this.adapters.entries()) {
26
+ if (client.guilds.cache.get(guildId)?.shardId === shardId) {
27
+ adapter.destroy();
28
+ }
29
+ }
30
+ });
31
+ }
32
+
33
+ onVoiceServer(payload) {
34
+ this.adapters.get(payload.guild_id)?.onVoiceServerUpdate(payload);
35
+ }
36
+
37
+ onVoiceStateUpdate(payload) {
38
+ if (payload.guild_id && payload.session_id && payload.user_id === this.client.user?.id) {
39
+ this.adapters.get(payload.guild_id)?.onVoiceStateUpdate(payload);
40
+ }
41
+ }
42
+ }
43
+
44
+ module.exports = ClientVoiceManager;
@@ -0,0 +1,393 @@
1
+ 'use strict';
2
+
3
+ const EventEmitter = require('node:events');
4
+ const process = require('node:process');
5
+ const { setImmediate } = require('node:timers');
6
+ const { Collection } = require('@discordjs/collection');
7
+ const {
8
+ WebSocketManager: WSWebSocketManager,
9
+ WebSocketShardEvents: WSWebSocketShardEvents,
10
+ CompressionMethod,
11
+ CloseCodes,
12
+ } = require('@discordjs/ws');
13
+ const { GatewayCloseCodes, GatewayDispatchEvents } = require('discord-api-types/v10');
14
+ const WebSocketShard = require('./WebSocketShard');
15
+ const PacketHandlers = require('./handlers');
16
+ const { DiscordjsError, ErrorCodes } = require('../../errors');
17
+ const Events = require('../../util/Events');
18
+ const Status = require('../../util/Status');
19
+ const WebSocketShardEvents = require('../../util/WebSocketShardEvents');
20
+
21
+ let zlib;
22
+
23
+ try {
24
+ zlib = require('zlib-sync');
25
+ } catch {} // eslint-disable-line no-empty
26
+
27
+ const BeforeReadyWhitelist = [
28
+ GatewayDispatchEvents.Ready,
29
+ GatewayDispatchEvents.Resumed,
30
+ GatewayDispatchEvents.GuildCreate,
31
+ GatewayDispatchEvents.GuildDelete,
32
+ GatewayDispatchEvents.GuildMembersChunk,
33
+ GatewayDispatchEvents.GuildMemberAdd,
34
+ GatewayDispatchEvents.GuildMemberRemove,
35
+ ];
36
+
37
+ const WaitingForGuildEvents = [GatewayDispatchEvents.GuildCreate, GatewayDispatchEvents.GuildDelete];
38
+
39
+ const UNRESUMABLE_CLOSE_CODES = [
40
+ CloseCodes.Normal,
41
+ GatewayCloseCodes.AlreadyAuthenticated,
42
+ GatewayCloseCodes.InvalidSeq,
43
+ ];
44
+
45
+ const reasonIsDeprecated = 'the reason property is deprecated, use the code property to determine the reason';
46
+ let deprecationEmittedForInvalidSessionEvent = false;
47
+ let deprecationEmittedForDestroyedEvent = false;
48
+
49
+ /**
50
+ * The WebSocket manager for this client.
51
+ * <info>This class forwards raw dispatch events,
52
+ * read more about it here {@link https://discord.com/developers/docs/topics/gateway}</info>
53
+ * @extends {EventEmitter}
54
+ */
55
+ class WebSocketManager extends EventEmitter {
56
+ constructor(client) {
57
+ super();
58
+
59
+ /**
60
+ * The client that instantiated this WebSocketManager
61
+ * @type {Client}
62
+ * @readonly
63
+ * @name WebSocketManager#client
64
+ */
65
+ Object.defineProperty(this, 'client', { value: client });
66
+
67
+ /**
68
+ * The gateway this manager uses
69
+ * @type {?string}
70
+ */
71
+ this.gateway = null;
72
+
73
+ /**
74
+ * A collection of all shards this manager handles
75
+ * @type {Collection<number, WebSocketShard>}
76
+ */
77
+ this.shards = new Collection();
78
+
79
+ /**
80
+ * An array of queued events before this WebSocketManager became ready
81
+ * @type {Object[]}
82
+ * @private
83
+ * @name WebSocketManager#packetQueue
84
+ */
85
+ Object.defineProperty(this, 'packetQueue', { value: [] });
86
+
87
+ /**
88
+ * The current status of this WebSocketManager
89
+ * @type {Status}
90
+ */
91
+ this.status = Status.Idle;
92
+
93
+ /**
94
+ * If this manager was destroyed. It will prevent shards from reconnecting
95
+ * @type {boolean}
96
+ * @private
97
+ */
98
+ this.destroyed = false;
99
+
100
+ /**
101
+ * The internal WebSocketManager from `@discordjs/ws`.
102
+ * @type {WSWebSocketManager}
103
+ * @private
104
+ */
105
+ this._ws = null;
106
+ }
107
+
108
+ /**
109
+ * The average ping of all WebSocketShards
110
+ * @type {number}
111
+ * @readonly
112
+ */
113
+ get ping() {
114
+ const sum = this.shards.reduce((a, b) => a + b.ping, 0);
115
+ return sum / this.shards.size;
116
+ }
117
+
118
+ /**
119
+ * Emits a debug message.
120
+ * @param {string} message The debug message
121
+ * @param {?number} [shardId] The id of the shard that emitted this message, if any
122
+ * @private
123
+ */
124
+ debug(message, shardId) {
125
+ this.client.emit(
126
+ Events.Debug,
127
+ `[WS => ${typeof shardId === 'number' ? `Shard ${shardId}` : 'Manager'}] ${message}`,
128
+ );
129
+ }
130
+
131
+ /**
132
+ * Connects this manager to the gateway.
133
+ * @private
134
+ */
135
+ async connect() {
136
+ const invalidToken = new DiscordjsError(ErrorCodes.TokenInvalid);
137
+ const { shards, shardCount, intents, ws } = this.client.options;
138
+ if (this._ws && this._ws.options.token !== this.client.token) {
139
+ await this._ws.destroy({ code: CloseCodes.Normal, reason: 'Login with differing token requested' });
140
+ this._ws = null;
141
+ }
142
+ if (!this._ws) {
143
+ const wsOptions = {
144
+ intents: intents.bitfield,
145
+ rest: this.client.rest,
146
+ token: this.client.token,
147
+ largeThreshold: ws.large_threshold,
148
+ version: ws.version,
149
+ shardIds: shards === 'auto' ? null : shards,
150
+ shardCount: shards === 'auto' ? null : shardCount,
151
+ initialPresence: ws.presence,
152
+ retrieveSessionInfo: shardId => this.shards.get(shardId).sessionInfo,
153
+ updateSessionInfo: (shardId, sessionInfo) => {
154
+ this.shards.get(shardId).sessionInfo = sessionInfo;
155
+ },
156
+ compression: zlib ? CompressionMethod.ZlibStream : null,
157
+ };
158
+ if (ws.buildStrategy) wsOptions.buildStrategy = ws.buildStrategy;
159
+ this._ws = new WSWebSocketManager(wsOptions);
160
+ this.attachEvents();
161
+ }
162
+
163
+ const {
164
+ url: gatewayURL,
165
+ shards: recommendedShards,
166
+ session_start_limit: sessionStartLimit,
167
+ } = await this._ws.fetchGatewayInformation().catch(error => {
168
+ throw error.status === 401 ? invalidToken : error;
169
+ });
170
+
171
+ const { total, remaining } = sessionStartLimit;
172
+
173
+ this.debug(`Fetched Gateway Information
174
+ URL: ${gatewayURL}
175
+ Recommended Shards: ${recommendedShards}`);
176
+
177
+ this.debug(`Session Limit Information
178
+ Total: ${total}
179
+ Remaining: ${remaining}`);
180
+
181
+ this.gateway = `${gatewayURL}/`;
182
+
183
+ this.client.options.shardCount = await this._ws.getShardCount();
184
+ this.client.options.shards = await this._ws.getShardIds();
185
+ this.totalShards = this.client.options.shards.length;
186
+ for (const id of this.client.options.shards) {
187
+ if (!this.shards.has(id)) {
188
+ const shard = new WebSocketShard(this, id);
189
+ this.shards.set(id, shard);
190
+
191
+ shard.on(WebSocketShardEvents.AllReady, unavailableGuilds => {
192
+ /**
193
+ * Emitted when a shard turns ready.
194
+ * @event Client#shardReady
195
+ * @param {number} id The shard id that turned ready
196
+ * @param {?Set<Snowflake>} unavailableGuilds Set of unavailable guild ids, if any
197
+ */
198
+ this.client.emit(Events.ShardReady, shard.id, unavailableGuilds);
199
+
200
+ this.checkShardsReady();
201
+ });
202
+ shard.status = Status.Connecting;
203
+ }
204
+ }
205
+
206
+ await this._ws.connect();
207
+
208
+ this.shards.forEach(shard => {
209
+ if (shard.listenerCount(WebSocketShardEvents.InvalidSession) > 0 && !deprecationEmittedForInvalidSessionEvent) {
210
+ process.emitWarning(
211
+ 'The WebSocketShard#invalidSession event is deprecated and will never emit.',
212
+ 'DeprecationWarning',
213
+ );
214
+
215
+ deprecationEmittedForInvalidSessionEvent = true;
216
+ }
217
+ if (shard.listenerCount(WebSocketShardEvents.Destroyed) > 0 && !deprecationEmittedForDestroyedEvent) {
218
+ process.emitWarning(
219
+ 'The WebSocketShard#destroyed event is deprecated and will never emit.',
220
+ 'DeprecationWarning',
221
+ );
222
+
223
+ deprecationEmittedForDestroyedEvent = true;
224
+ }
225
+ });
226
+ }
227
+
228
+ /**
229
+ * Attaches event handlers to the internal WebSocketShardManager from `@discordjs/ws`.
230
+ * @private
231
+ */
232
+ attachEvents() {
233
+ this._ws.on(WSWebSocketShardEvents.Debug, ({ message, shardId }) => this.debug(message, shardId));
234
+ this._ws.on(WSWebSocketShardEvents.Dispatch, ({ data, shardId }) => {
235
+ this.client.emit(Events.Raw, data, shardId);
236
+ this.emit(data.t, data.d, shardId);
237
+ const shard = this.shards.get(shardId);
238
+ this.handlePacket(data, shard);
239
+ if (shard.status === Status.WaitingForGuilds && WaitingForGuildEvents.includes(data.t)) {
240
+ shard.gotGuild(data.d.id);
241
+ }
242
+ });
243
+
244
+ this._ws.on(WSWebSocketShardEvents.Ready, ({ data, shardId }) => {
245
+ this.shards.get(shardId).onReadyPacket(data);
246
+ });
247
+
248
+ this._ws.on(WSWebSocketShardEvents.Closed, ({ code, shardId }) => {
249
+ const shard = this.shards.get(shardId);
250
+ shard.emit(WebSocketShardEvents.Close, { code, reason: reasonIsDeprecated, wasClean: true });
251
+ if (UNRESUMABLE_CLOSE_CODES.includes(code) && this.destroyed) {
252
+ shard.status = Status.Disconnected;
253
+ /**
254
+ * Emitted when a shard's WebSocket disconnects and will no longer reconnect.
255
+ * @event Client#shardDisconnect
256
+ * @param {CloseEvent} event The WebSocket close event
257
+ * @param {number} id The shard id that disconnected
258
+ */
259
+ this.client.emit(Events.ShardDisconnect, { code, reason: reasonIsDeprecated, wasClean: true }, shardId);
260
+ this.debug(GatewayCloseCodes[code], shardId);
261
+ return;
262
+ }
263
+
264
+ this.shards.get(shardId).status = Status.Connecting;
265
+ /**
266
+ * Emitted when a shard is attempting to reconnect or re-identify.
267
+ * @event Client#shardReconnecting
268
+ * @param {number} id The shard id that is attempting to reconnect
269
+ */
270
+ this.client.emit(Events.ShardReconnecting, shardId);
271
+ });
272
+ this._ws.on(WSWebSocketShardEvents.Hello, ({ shardId }) => {
273
+ const shard = this.shards.get(shardId);
274
+ if (shard.sessionInfo) {
275
+ shard.closeSequence = shard.sessionInfo.sequence;
276
+ shard.status = Status.Resuming;
277
+ } else {
278
+ shard.status = Status.Identifying;
279
+ }
280
+ });
281
+
282
+ this._ws.on(WSWebSocketShardEvents.Resumed, ({ shardId }) => {
283
+ const shard = this.shards.get(shardId);
284
+ shard.status = Status.Ready;
285
+ /**
286
+ * Emitted when the shard resumes successfully
287
+ * @event WebSocketShard#resumed
288
+ */
289
+ shard.emit(WebSocketShardEvents.Resumed);
290
+ });
291
+
292
+ this._ws.on(WSWebSocketShardEvents.HeartbeatComplete, ({ heartbeatAt, latency, shardId }) => {
293
+ this.debug(`Heartbeat acknowledged, latency of ${latency}ms.`, shardId);
294
+ const shard = this.shards.get(shardId);
295
+ shard.lastPingTimestamp = heartbeatAt;
296
+ shard.ping = latency;
297
+ });
298
+
299
+ this._ws.on(WSWebSocketShardEvents.Error, ({ error, shardId }) => {
300
+ /**
301
+ * Emitted whenever a shard's WebSocket encounters a connection error.
302
+ * @event Client#shardError
303
+ * @param {Error} error The encountered error
304
+ * @param {number} shardId The shard that encountered this error
305
+ */
306
+ this.client.emit(Events.ShardError, error, shardId);
307
+ });
308
+ }
309
+
310
+ /**
311
+ * Broadcasts a packet to every shard this manager handles.
312
+ * @param {Object} packet The packet to send
313
+ * @private
314
+ */
315
+ broadcast(packet) {
316
+ for (const shardId of this.shards.keys()) this._ws.send(shardId, packet);
317
+ }
318
+
319
+ /**
320
+ * Destroys this manager and all its shards.
321
+ * @private
322
+ */
323
+ destroy() {
324
+ if (this.destroyed) return;
325
+ // TODO: Make a util for getting a stack
326
+ this.debug(`Manager was destroyed. Called by:\n${new Error().stack}`);
327
+ this.destroyed = true;
328
+ this._ws.destroy({ code: CloseCodes.Normal });
329
+ }
330
+
331
+ /**
332
+ * Processes a packet and queues it if this WebSocketManager is not ready.
333
+ * @param {Object} [packet] The packet to be handled
334
+ * @param {WebSocketShard} [shard] The shard that will handle this packet
335
+ * @returns {boolean}
336
+ * @private
337
+ */
338
+ handlePacket(packet, shard) {
339
+ if (packet && this.status !== Status.Ready) {
340
+ if (!BeforeReadyWhitelist.includes(packet.t)) {
341
+ this.packetQueue.push({ packet, shard });
342
+ return false;
343
+ }
344
+ }
345
+
346
+ if (this.packetQueue.length) {
347
+ const item = this.packetQueue.shift();
348
+ setImmediate(() => {
349
+ this.handlePacket(item.packet, item.shard);
350
+ }).unref();
351
+ }
352
+
353
+ if (packet && PacketHandlers[packet.t]) {
354
+ PacketHandlers[packet.t](this.client, packet, shard);
355
+ }
356
+
357
+ return true;
358
+ }
359
+
360
+ /**
361
+ * Checks whether the client is ready to be marked as ready.
362
+ * @private
363
+ */
364
+ checkShardsReady() {
365
+ if (this.status === Status.Ready) return;
366
+ if (this.shards.size !== this.totalShards || this.shards.some(s => s.status !== Status.Ready)) {
367
+ return;
368
+ }
369
+
370
+ this.triggerClientReady();
371
+ }
372
+
373
+ /**
374
+ * Causes the client to be marked as ready and emits the ready event.
375
+ * @private
376
+ */
377
+ triggerClientReady() {
378
+ this.status = Status.Ready;
379
+
380
+ this.client.readyTimestamp = Date.now();
381
+
382
+ /**
383
+ * Emitted when the client becomes ready to start working.
384
+ * @event Client#ready
385
+ * @param {Client} client The client
386
+ */
387
+ this.client.emit(Events.ClientReady, this.client);
388
+
389
+ this.handlePacket();
390
+ }
391
+ }
392
+
393
+ module.exports = WebSocketManager;