@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,285 @@
1
+ 'use strict';
2
+
3
+ const process = require('node:process');
4
+ const { calculateShardId } = require('@discordjs/util');
5
+ const { DiscordjsError, DiscordjsTypeError, ErrorCodes } = require('../errors');
6
+ const Events = require('../util/Events');
7
+ const { makeError, makePlainError } = require('../util/Util');
8
+
9
+ /**
10
+ * Helper class for sharded clients spawned as a child process/worker, such as from a {@link ShardingManager}.
11
+ * Utilises IPC to send and receive data to/from the master process and other shards.
12
+ */
13
+ class ShardClientUtil {
14
+ constructor(client, mode) {
15
+ /**
16
+ * Client for the shard
17
+ * @type {Client}
18
+ */
19
+ this.client = client;
20
+
21
+ /**
22
+ * Mode the shard was spawned with
23
+ * @type {ShardingManagerMode}
24
+ */
25
+ this.mode = mode;
26
+
27
+ /**
28
+ * Message port for the master process (only when {@link ShardClientUtil#mode} is `worker`)
29
+ * @type {?MessagePort}
30
+ */
31
+ this.parentPort = null;
32
+
33
+ switch (mode) {
34
+ case 'process':
35
+ process.on('message', this._handleMessage.bind(this));
36
+ client.on(Events.ShardReady, () => {
37
+ process.send({ _ready: true });
38
+ });
39
+ client.on(Events.ShardDisconnect, () => {
40
+ process.send({ _disconnect: true });
41
+ });
42
+ client.on(Events.ShardReconnecting, () => {
43
+ process.send({ _reconnecting: true });
44
+ });
45
+ break;
46
+ case 'worker':
47
+ this.parentPort = require('node:worker_threads').parentPort;
48
+ this.parentPort.on('message', this._handleMessage.bind(this));
49
+ client.on(Events.ShardReady, () => {
50
+ this.parentPort.postMessage({ _ready: true });
51
+ });
52
+ client.on(Events.ShardDisconnect, () => {
53
+ this.parentPort.postMessage({ _disconnect: true });
54
+ });
55
+ client.on(Events.ShardReconnecting, () => {
56
+ this.parentPort.postMessage({ _reconnecting: true });
57
+ });
58
+ break;
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Array of shard ids of this client
64
+ * @type {number[]}
65
+ * @readonly
66
+ */
67
+ get ids() {
68
+ return this.client.options.shards;
69
+ }
70
+
71
+ /**
72
+ * Total number of shards
73
+ * @type {number}
74
+ * @readonly
75
+ */
76
+ get count() {
77
+ return this.client.options.shardCount;
78
+ }
79
+
80
+ /**
81
+ * Sends a message to the master process.
82
+ * @param {*} message Message to send
83
+ * @returns {Promise<void>}
84
+ * @emits Shard#message
85
+ */
86
+ send(message) {
87
+ return new Promise((resolve, reject) => {
88
+ switch (this.mode) {
89
+ case 'process':
90
+ process.send(message, err => {
91
+ if (err) reject(err);
92
+ else resolve();
93
+ });
94
+ break;
95
+ case 'worker':
96
+ this.parentPort.postMessage(message);
97
+ resolve();
98
+ break;
99
+ }
100
+ });
101
+ }
102
+
103
+ /**
104
+ * Fetches a client property value of each shard, or a given shard.
105
+ * @param {string} prop Name of the client property to get, using periods for nesting
106
+ * @param {number} [shard] Shard to fetch property from, all if undefined
107
+ * @returns {Promise<*|Array<*>>}
108
+ * @example
109
+ * client.shard.fetchClientValues('guilds.cache.size')
110
+ * .then(results => console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`))
111
+ * .catch(console.error);
112
+ * @see {@link ShardingManager#fetchClientValues}
113
+ */
114
+ fetchClientValues(prop, shard) {
115
+ return new Promise((resolve, reject) => {
116
+ const parent = this.parentPort ?? process;
117
+
118
+ const listener = message => {
119
+ if (message?._sFetchProp !== prop || message._sFetchPropShard !== shard) return;
120
+ parent.removeListener('message', listener);
121
+ this.decrementMaxListeners(parent);
122
+ if (!message._error) resolve(message._result);
123
+ else reject(makeError(message._error));
124
+ };
125
+ this.incrementMaxListeners(parent);
126
+ parent.on('message', listener);
127
+
128
+ this.send({ _sFetchProp: prop, _sFetchPropShard: shard }).catch(err => {
129
+ parent.removeListener('message', listener);
130
+ this.decrementMaxListeners(parent);
131
+ reject(err);
132
+ });
133
+ });
134
+ }
135
+
136
+ /**
137
+ * Evaluates a script or function on all shards, or a given shard, in the context of the {@link Client}s.
138
+ * @param {Function} script JavaScript to run on each shard
139
+ * @param {BroadcastEvalOptions} [options={}] The options for the broadcast
140
+ * @returns {Promise<*|Array<*>>} Results of the script execution
141
+ * @example
142
+ * client.shard.broadcastEval(client => client.guilds.cache.size)
143
+ * .then(results => console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`))
144
+ * .catch(console.error);
145
+ * @see {@link ShardingManager#broadcastEval}
146
+ */
147
+ broadcastEval(script, options = {}) {
148
+ return new Promise((resolve, reject) => {
149
+ const parent = this.parentPort ?? process;
150
+ if (typeof script !== 'function') {
151
+ reject(new DiscordjsTypeError(ErrorCodes.ShardingInvalidEvalBroadcast));
152
+ return;
153
+ }
154
+ script = `(${script})(this, ${JSON.stringify(options.context)})`;
155
+
156
+ const listener = message => {
157
+ if (message?._sEval !== script || message._sEvalShard !== options.shard) return;
158
+ parent.removeListener('message', listener);
159
+ this.decrementMaxListeners(parent);
160
+ if (!message._error) resolve(message._result);
161
+ else reject(makeError(message._error));
162
+ };
163
+ this.incrementMaxListeners(parent);
164
+ parent.on('message', listener);
165
+ this.send({ _sEval: script, _sEvalShard: options.shard }).catch(err => {
166
+ parent.removeListener('message', listener);
167
+ this.decrementMaxListeners(parent);
168
+ reject(err);
169
+ });
170
+ });
171
+ }
172
+
173
+ /**
174
+ * Requests a respawn of all shards.
175
+ * @param {MultipleShardRespawnOptions} [options] Options for respawning shards
176
+ * @returns {Promise<void>} Resolves upon the message being sent
177
+ * @see {@link ShardingManager#respawnAll}
178
+ */
179
+ respawnAll({ shardDelay = 5_000, respawnDelay = 500, timeout = 30_000 } = {}) {
180
+ return this.send({ _sRespawnAll: { shardDelay, respawnDelay, timeout } });
181
+ }
182
+
183
+ /**
184
+ * Handles an IPC message.
185
+ * @param {*} message Message received
186
+ * @private
187
+ */
188
+ async _handleMessage(message) {
189
+ if (!message) return;
190
+ if (message._fetchProp) {
191
+ try {
192
+ const props = message._fetchProp.split('.');
193
+ let value = this.client;
194
+ for (const prop of props) value = value[prop];
195
+ this._respond('fetchProp', { _fetchProp: message._fetchProp, _result: value });
196
+ } catch (err) {
197
+ this._respond('fetchProp', { _fetchProp: message._fetchProp, _error: makePlainError(err) });
198
+ }
199
+ } else if (message._eval) {
200
+ try {
201
+ this._respond('eval', { _eval: message._eval, _result: await this.client._eval(message._eval) });
202
+ } catch (err) {
203
+ this._respond('eval', { _eval: message._eval, _error: makePlainError(err) });
204
+ }
205
+ }
206
+ }
207
+
208
+ /**
209
+ * Sends a message to the master process, emitting an error from the client upon failure.
210
+ * @param {string} type Type of response to send
211
+ * @param {*} message Message to send
212
+ * @private
213
+ */
214
+ _respond(type, message) {
215
+ this.send(message).catch(err => {
216
+ const error = new Error(`Error when sending ${type} response to master process: ${err.message}`);
217
+ error.stack = err.stack;
218
+ /**
219
+ * Emitted when the client encounters an error.
220
+ * <warn>Errors thrown within this event do not have a catch handler, it is
221
+ * recommended to not use async functions as `error` event handlers. See the
222
+ * [Node.js docs](https://nodejs.org/api/events.html#capture-rejections-of-promises) for details.</warn>
223
+ * @event Client#error
224
+ * @param {Error} error The error encountered
225
+ */
226
+ this.client.emit(Events.Error, error);
227
+ });
228
+ }
229
+
230
+ /**
231
+ * Creates/gets the singleton of this class.
232
+ * @param {Client} client The client to use
233
+ * @param {ShardingManagerMode} mode Mode the shard was spawned with
234
+ * @returns {ShardClientUtil}
235
+ */
236
+ static singleton(client, mode) {
237
+ if (!this._singleton) {
238
+ this._singleton = new this(client, mode);
239
+ } else {
240
+ client.emit(
241
+ Events.Warn,
242
+ 'Multiple clients created in child process/worker; only the first will handle sharding helpers.',
243
+ );
244
+ }
245
+ return this._singleton;
246
+ }
247
+
248
+ /**
249
+ * Get the shard id for a given guild id.
250
+ * @param {Snowflake} guildId Snowflake guild id to get shard id for
251
+ * @param {number} shardCount Number of shards
252
+ * @returns {number}
253
+ */
254
+ static shardIdForGuildId(guildId, shardCount) {
255
+ const shard = calculateShardId(guildId, shardCount);
256
+ if (shard < 0) throw new DiscordjsError(ErrorCodes.ShardingShardMiscalculation, shard, guildId, shardCount);
257
+ return shard;
258
+ }
259
+
260
+ /**
261
+ * Increments max listeners by one for a given emitter, if they are not zero.
262
+ * @param {EventEmitter|process} emitter The emitter that emits the events.
263
+ * @private
264
+ */
265
+ incrementMaxListeners(emitter) {
266
+ const maxListeners = emitter.getMaxListeners();
267
+ if (maxListeners !== 0) {
268
+ emitter.setMaxListeners(maxListeners + 1);
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Decrements max listeners by one for a given emitter, if they are not zero.
274
+ * @param {EventEmitter|process} emitter The emitter that emits the events.
275
+ * @private
276
+ */
277
+ decrementMaxListeners(emitter) {
278
+ const maxListeners = emitter.getMaxListeners();
279
+ if (maxListeners !== 0) {
280
+ emitter.setMaxListeners(maxListeners - 1);
281
+ }
282
+ }
283
+ }
284
+
285
+ module.exports = ShardClientUtil;
@@ -0,0 +1,326 @@
1
+ 'use strict';
2
+
3
+ const EventEmitter = require('node:events');
4
+ const fs = require('node:fs');
5
+ const path = require('node:path');
6
+ const process = require('node:process');
7
+ const { setTimeout: sleep } = require('node:timers/promises');
8
+ const { Collection } = require('@discordjs/collection');
9
+ const Shard = require('./Shard');
10
+ const { DiscordjsError, DiscordjsTypeError, DiscordjsRangeError, ErrorCodes } = require('../errors');
11
+ const { mergeDefault, fetchRecommendedShardCount } = require('../util/Util');
12
+
13
+ /**
14
+ * This is a utility class that makes multi-process sharding of a bot an easy and painless experience.
15
+ * It works by spawning a self-contained {@link ChildProcess} or {@link Worker} for each individual shard, each
16
+ * containing its own instance of your bot's {@link Client}. They all have a line of communication with the master
17
+ * process, and there are several useful methods that utilise it in order to simplify tasks that are normally difficult
18
+ * with sharding. It can spawn a specific number of shards or the amount that Discord suggests for the bot, and takes a
19
+ * path to your main bot script to launch for each one.
20
+ * @extends {EventEmitter}
21
+ */
22
+ class ShardingManager extends EventEmitter {
23
+ /**
24
+ * The mode to spawn shards with for a {@link ShardingManager}. Can be either one of:
25
+ * * 'process' to use child processes
26
+ * * 'worker' to use [Worker threads](https://nodejs.org/api/worker_threads.html)
27
+ * @typedef {string} ShardingManagerMode
28
+ */
29
+
30
+ /**
31
+ * The options to spawn shards with for a {@link ShardingManager}.
32
+ * @typedef {Object} ShardingManagerOptions
33
+ * @property {string|number} [totalShards='auto'] Number of total shards of all shard managers or "auto"
34
+ * @property {string|number[]} [shardList='auto'] List of shards to spawn or "auto"
35
+ * @property {ShardingManagerMode} [mode='process'] Which mode to use for shards
36
+ * @property {boolean} [respawn=true] Whether shards should automatically respawn upon exiting
37
+ * @property {string[]} [shardArgs=[]] Arguments to pass to the shard script when spawning
38
+ * (only available when mode is set to 'process')
39
+ * @property {string[]} [execArgv=[]] Arguments to pass to the shard script executable when spawning
40
+ * (only available when mode is set to 'process')
41
+ * @property {string} [token] Token to use for automatic shard count and passing to shards
42
+ */
43
+
44
+ /**
45
+ * @param {string} file Path to your shard script file
46
+ * @param {ShardingManagerOptions} [options] Options for the sharding manager
47
+ */
48
+ constructor(file, options = {}) {
49
+ super();
50
+ options = mergeDefault(
51
+ {
52
+ totalShards: 'auto',
53
+ mode: 'process',
54
+ respawn: true,
55
+ shardArgs: [],
56
+ execArgv: [],
57
+ token: process.env.DISCORD_TOKEN,
58
+ },
59
+ options,
60
+ );
61
+
62
+ /**
63
+ * Path to the shard script file
64
+ * @type {string}
65
+ */
66
+ this.file = file;
67
+ if (!file) throw new DiscordjsError(ErrorCodes.ClientInvalidOption, 'File', 'specified.');
68
+ if (!path.isAbsolute(file)) this.file = path.resolve(process.cwd(), file);
69
+ const stats = fs.statSync(this.file);
70
+ if (!stats.isFile()) throw new DiscordjsError(ErrorCodes.ClientInvalidOption, 'File', 'a file');
71
+
72
+ /**
73
+ * List of shards this sharding manager spawns
74
+ * @type {string|number[]}
75
+ */
76
+ this.shardList = options.shardList ?? 'auto';
77
+ if (this.shardList !== 'auto') {
78
+ if (!Array.isArray(this.shardList)) {
79
+ throw new DiscordjsTypeError(ErrorCodes.ClientInvalidOption, 'shardList', 'an array.');
80
+ }
81
+ this.shardList = [...new Set(this.shardList)];
82
+ if (this.shardList.length < 1) {
83
+ throw new DiscordjsRangeError(ErrorCodes.ClientInvalidOption, 'shardList', 'at least 1 id.');
84
+ }
85
+ if (
86
+ this.shardList.some(
87
+ shardId => typeof shardId !== 'number' || isNaN(shardId) || !Number.isInteger(shardId) || shardId < 0,
88
+ )
89
+ ) {
90
+ throw new DiscordjsTypeError(ErrorCodes.ClientInvalidOption, 'shardList', 'an array of positive integers.');
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Amount of shards that all sharding managers spawn in total
96
+ * @type {number}
97
+ */
98
+ this.totalShards = options.totalShards || 'auto';
99
+ if (this.totalShards !== 'auto') {
100
+ if (typeof this.totalShards !== 'number' || isNaN(this.totalShards)) {
101
+ throw new DiscordjsTypeError(ErrorCodes.ClientInvalidOption, 'Amount of shards', 'a number.');
102
+ }
103
+ if (this.totalShards < 1) {
104
+ throw new DiscordjsRangeError(ErrorCodes.ClientInvalidOption, 'Amount of shards', 'at least 1.');
105
+ }
106
+ if (!Number.isInteger(this.totalShards)) {
107
+ throw new DiscordjsRangeError(ErrorCodes.ClientInvalidOption, 'Amount of shards', 'an integer.');
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Mode for shards to spawn with
113
+ * @type {ShardingManagerMode}
114
+ */
115
+ this.mode = options.mode;
116
+ if (this.mode !== 'process' && this.mode !== 'worker') {
117
+ throw new DiscordjsRangeError(ErrorCodes.ClientInvalidOption, 'Sharding mode', '"process" or "worker"');
118
+ }
119
+
120
+ /**
121
+ * Whether shards should automatically respawn upon exiting
122
+ * @type {boolean}
123
+ */
124
+ this.respawn = options.respawn;
125
+
126
+ /**
127
+ * An array of arguments to pass to shards (only when {@link ShardingManager#mode} is `process`)
128
+ * @type {string[]}
129
+ */
130
+ this.shardArgs = options.shardArgs;
131
+
132
+ /**
133
+ * An array of arguments to pass to the executable (only when {@link ShardingManager#mode} is `process`)
134
+ * @type {string[]}
135
+ */
136
+ this.execArgv = options.execArgv;
137
+
138
+ /**
139
+ * Token to use for obtaining the automatic shard count, and passing to shards
140
+ * @type {?string}
141
+ */
142
+ this.token = options.token?.replace(/^Bot\s*/i, '') ?? null;
143
+
144
+ /**
145
+ * A collection of shards that this manager has spawned
146
+ * @type {Collection<number, Shard>}
147
+ */
148
+ this.shards = new Collection();
149
+
150
+ process.env.SHARDING_MANAGER = true;
151
+ process.env.SHARDING_MANAGER_MODE = this.mode;
152
+ process.env.DISCORD_TOKEN = this.token;
153
+ }
154
+
155
+ /**
156
+ * Creates a single shard.
157
+ * <warn>Using this method is usually not necessary if you use the spawn method.</warn>
158
+ * @param {number} [id=this.shards.size] Id of the shard to create
159
+ * <info>This is usually not necessary to manually specify.</info>
160
+ * @returns {Shard} Note that the created shard needs to be explicitly spawned using its spawn method.
161
+ */
162
+ createShard(id = this.shards.size) {
163
+ const shard = new Shard(this, id);
164
+ this.shards.set(id, shard);
165
+ /**
166
+ * Emitted upon creating a shard.
167
+ * @event ShardingManager#shardCreate
168
+ * @param {Shard} shard Shard that was created
169
+ */
170
+ this.emit('shardCreate', shard);
171
+ return shard;
172
+ }
173
+
174
+ /**
175
+ * Options used to spawn multiple shards.
176
+ * @typedef {Object} MultipleShardSpawnOptions
177
+ * @property {number|string} [amount=this.totalShards] Number of shards to spawn
178
+ * @property {number} [delay=5500] How long to wait in between spawning each shard (in milliseconds)
179
+ * @property {number} [timeout=30000] The amount in milliseconds to wait until the {@link Client} has become ready
180
+ */
181
+
182
+ /**
183
+ * Spawns multiple shards.
184
+ * @param {MultipleShardSpawnOptions} [options] Options for spawning shards
185
+ * @returns {Promise<Collection<number, Shard>>}
186
+ */
187
+ async spawn({ amount = this.totalShards, delay = 5500, timeout = 30_000 } = {}) {
188
+ // Obtain/verify the number of shards to spawn
189
+ if (amount === 'auto') {
190
+ amount = await fetchRecommendedShardCount(this.token);
191
+ } else {
192
+ if (typeof amount !== 'number' || isNaN(amount)) {
193
+ throw new DiscordjsTypeError(ErrorCodes.ClientInvalidOption, 'Amount of shards', 'a number.');
194
+ }
195
+ if (amount < 1) throw new DiscordjsRangeError(ErrorCodes.ClientInvalidOption, 'Amount of shards', 'at least 1.');
196
+ if (!Number.isInteger(amount)) {
197
+ throw new DiscordjsTypeError(ErrorCodes.ClientInvalidOption, 'Amount of shards', 'an integer.');
198
+ }
199
+ }
200
+
201
+ // Make sure this many shards haven't already been spawned
202
+ if (this.shards.size >= amount) throw new DiscordjsError(ErrorCodes.ShardingAlreadySpawned, this.shards.size);
203
+ if (this.shardList === 'auto' || this.totalShards === 'auto' || this.totalShards !== amount) {
204
+ this.shardList = [...Array(amount).keys()];
205
+ }
206
+ if (this.totalShards === 'auto' || this.totalShards !== amount) {
207
+ this.totalShards = amount;
208
+ }
209
+
210
+ if (this.shardList.some(shardId => shardId >= amount)) {
211
+ throw new DiscordjsRangeError(
212
+ ErrorCodes.ClientInvalidOption,
213
+ 'Amount of shards',
214
+ 'bigger than the highest shardId in the shardList option.',
215
+ );
216
+ }
217
+
218
+ // Spawn the shards
219
+ for (const shardId of this.shardList) {
220
+ const promises = [];
221
+ const shard = this.createShard(shardId);
222
+ promises.push(shard.spawn(timeout));
223
+ if (delay > 0 && this.shards.size !== this.shardList.length) promises.push(sleep(delay));
224
+ await Promise.all(promises); // eslint-disable-line no-await-in-loop
225
+ }
226
+
227
+ return this.shards;
228
+ }
229
+
230
+ /**
231
+ * Sends a message to all shards.
232
+ * @param {*} message Message to be sent to the shards
233
+ * @returns {Promise<Shard[]>}
234
+ */
235
+ broadcast(message) {
236
+ const promises = [];
237
+ for (const shard of this.shards.values()) promises.push(shard.send(message));
238
+ return Promise.all(promises);
239
+ }
240
+
241
+ /**
242
+ * Options for {@link ShardingManager#broadcastEval} and {@link ShardClientUtil#broadcastEval}.
243
+ * @typedef {Object} BroadcastEvalOptions
244
+ * @property {number} [shard] Shard to run script on, all if undefined
245
+ * @property {*} [context] The JSON-serializable values to call the script with
246
+ */
247
+
248
+ /**
249
+ * Evaluates a script on all shards, or a given shard, in the context of the {@link Client}s.
250
+ * @param {Function} script JavaScript to run on each shard
251
+ * @param {BroadcastEvalOptions} [options={}] The options for the broadcast
252
+ * @returns {Promise<*|Array<*>>} Results of the script execution
253
+ */
254
+ broadcastEval(script, options = {}) {
255
+ if (typeof script !== 'function') {
256
+ return Promise.reject(new DiscordjsTypeError(ErrorCodes.ShardingInvalidEvalBroadcast));
257
+ }
258
+ return this._performOnShards('eval', [`(${script})(this, ${JSON.stringify(options.context)})`], options.shard);
259
+ }
260
+
261
+ /**
262
+ * Fetches a client property value of each shard, or a given shard.
263
+ * @param {string} prop Name of the client property to get, using periods for nesting
264
+ * @param {number} [shard] Shard to fetch property from, all if undefined
265
+ * @returns {Promise<*|Array<*>>}
266
+ * @example
267
+ * manager.fetchClientValues('guilds.cache.size')
268
+ * .then(results => console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`))
269
+ * .catch(console.error);
270
+ */
271
+ fetchClientValues(prop, shard) {
272
+ return this._performOnShards('fetchClientValue', [prop], shard);
273
+ }
274
+
275
+ /**
276
+ * Runs a method with given arguments on all shards, or a given shard.
277
+ * @param {string} method Method name to run on each shard
278
+ * @param {Array<*>} args Arguments to pass through to the method call
279
+ * @param {number} [shard] Shard to run on, all if undefined
280
+ * @returns {Promise<*|Array<*>>} Results of the method execution
281
+ * @private
282
+ */
283
+ _performOnShards(method, args, shard) {
284
+ if (this.shards.size === 0) return Promise.reject(new DiscordjsError(ErrorCodes.ShardingNoShards));
285
+
286
+ if (typeof shard === 'number') {
287
+ if (this.shards.has(shard)) return this.shards.get(shard)[method](...args);
288
+ return Promise.reject(new DiscordjsError(ErrorCodes.ShardingShardNotFound, shard));
289
+ }
290
+
291
+ if (this.shards.size !== this.shardList.length) {
292
+ return Promise.reject(new DiscordjsError(ErrorCodes.ShardingInProcess));
293
+ }
294
+
295
+ const promises = [];
296
+ for (const sh of this.shards.values()) promises.push(sh[method](...args));
297
+ return Promise.all(promises);
298
+ }
299
+
300
+ /**
301
+ * Options used to respawn all shards.
302
+ * @typedef {Object} MultipleShardRespawnOptions
303
+ * @property {number} [shardDelay=5000] How long to wait between shards (in milliseconds)
304
+ * @property {number} [respawnDelay=500] How long to wait between killing a shard's process and restarting it
305
+ * (in milliseconds)
306
+ * @property {number} [timeout=30000] The amount in milliseconds to wait for a shard to become ready before
307
+ * continuing to another (`-1` or `Infinity` for no wait)
308
+ */
309
+
310
+ /**
311
+ * Kills all running shards and respawns them.
312
+ * @param {MultipleShardRespawnOptions} [options] Options for respawning shards
313
+ * @returns {Promise<Collection<number, Shard>>}
314
+ */
315
+ async respawnAll({ shardDelay = 5_000, respawnDelay = 500, timeout = 30_000 } = {}) {
316
+ let s = 0;
317
+ for (const shard of this.shards.values()) {
318
+ const promises = [shard.respawn({ delay: respawnDelay, timeout })];
319
+ if (++s < this.shards.size && shardDelay > 0) promises.push(sleep(shardDelay));
320
+ await Promise.all(promises); // eslint-disable-line no-await-in-loop
321
+ }
322
+ return this.shards;
323
+ }
324
+ }
325
+
326
+ module.exports = ShardingManager;
@@ -0,0 +1,46 @@
1
+ 'use strict';
2
+
3
+ const { deprecate } = require('node:util');
4
+ const { isJSONEncodable } = require('@discordjs/util');
5
+ const Component = require('./Component');
6
+ const { createComponent } = require('../util/Components');
7
+
8
+ /**
9
+ * Represents an action row
10
+ * @extends {Component}
11
+ */
12
+ class ActionRow extends Component {
13
+ constructor({ components, ...data }) {
14
+ super(data);
15
+
16
+ /**
17
+ * The components in this action row
18
+ * @type {Component[]}
19
+ * @readonly
20
+ */
21
+ this.components = components.map(c => createComponent(c));
22
+ }
23
+
24
+ /**
25
+ * Creates a new action row builder from JSON data
26
+ * @method from
27
+ * @memberof ActionRow
28
+ * @param {ActionRowBuilder|ActionRow|APIActionRowComponent} other The other data
29
+ * @returns {ActionRowBuilder}
30
+ * @deprecated Use {@link ActionRowBuilder.from} instead.
31
+ */
32
+ static from = deprecate(
33
+ other => new this(isJSONEncodable(other) ? other.toJSON() : other),
34
+ 'ActionRow.from() is deprecated. Use ActionRowBuilder.from() instead.',
35
+ );
36
+
37
+ /**
38
+ * Returns the API-compatible JSON for this component
39
+ * @returns {APIActionRowComponent}
40
+ */
41
+ toJSON() {
42
+ return { ...this.data, components: this.components.map(c => c.toJSON()) };
43
+ }
44
+ }
45
+
46
+ module.exports = ActionRow;
@@ -0,0 +1,35 @@
1
+ 'use strict';
2
+
3
+ const { ActionRowBuilder: BuildersActionRow } = require('@discordjs/builders');
4
+ const { isJSONEncodable } = require('@discordjs/util');
5
+ const { createComponentBuilder } = require('../util/Components');
6
+ const { toSnakeCase } = require('../util/Transformers');
7
+
8
+ /**
9
+ * Represents an action row builder.
10
+ * @extends {BuildersActionRow}
11
+ */
12
+ class ActionRowBuilder extends BuildersActionRow {
13
+ constructor({ components, ...data } = {}) {
14
+ super({
15
+ ...toSnakeCase(data),
16
+ components: components?.map(c => createComponentBuilder(c)),
17
+ });
18
+ }
19
+
20
+ /**
21
+ * Creates a new action row builder from JSON data
22
+ * @param {ActionRow|ActionRowBuilder|APIActionRowComponent} other The other data
23
+ * @returns {ActionRowBuilder}
24
+ */
25
+ static from(other) {
26
+ return new this(isJSONEncodable(other) ? other.toJSON() : other);
27
+ }
28
+ }
29
+
30
+ module.exports = ActionRowBuilder;
31
+
32
+ /**
33
+ * @external BuildersActionRow
34
+ * @see {@link https://discord.js.org/docs/packages/builders/stable/ActionRowBuilder:Class}
35
+ */