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.
- package/LICENSE +674 -0
- package/README.md +2 -0
- package/package.json +91 -0
- package/src/WebSocket.js +39 -0
- package/src/client/BaseClient.js +86 -0
- package/src/client/Client.js +978 -0
- package/src/client/WebhookClient.js +61 -0
- package/src/client/actions/Action.js +116 -0
- package/src/client/actions/ActionsManager.js +80 -0
- package/src/client/actions/ApplicationCommandPermissionsUpdate.js +34 -0
- package/src/client/actions/AutoModerationActionExecution.js +27 -0
- package/src/client/actions/AutoModerationRuleCreate.js +28 -0
- package/src/client/actions/AutoModerationRuleDelete.js +32 -0
- package/src/client/actions/AutoModerationRuleUpdate.js +30 -0
- package/src/client/actions/ChannelCreate.js +23 -0
- package/src/client/actions/ChannelDelete.js +39 -0
- package/src/client/actions/ChannelUpdate.js +43 -0
- package/src/client/actions/GuildAuditLogEntryCreate.js +29 -0
- package/src/client/actions/GuildBanAdd.js +20 -0
- package/src/client/actions/GuildBanRemove.js +25 -0
- package/src/client/actions/GuildChannelsPositionUpdate.js +21 -0
- package/src/client/actions/GuildDelete.js +65 -0
- package/src/client/actions/GuildEmojiCreate.js +20 -0
- package/src/client/actions/GuildEmojiDelete.js +21 -0
- package/src/client/actions/GuildEmojiUpdate.js +20 -0
- package/src/client/actions/GuildEmojisUpdate.js +34 -0
- package/src/client/actions/GuildIntegrationsUpdate.js +19 -0
- package/src/client/actions/GuildMemberRemove.js +33 -0
- package/src/client/actions/GuildMemberUpdate.js +44 -0
- package/src/client/actions/GuildRoleCreate.js +25 -0
- package/src/client/actions/GuildRoleDelete.js +31 -0
- package/src/client/actions/GuildRoleUpdate.js +39 -0
- package/src/client/actions/GuildRolesPositionUpdate.js +21 -0
- package/src/client/actions/GuildScheduledEventCreate.js +27 -0
- package/src/client/actions/GuildScheduledEventDelete.js +31 -0
- package/src/client/actions/GuildScheduledEventUpdate.js +30 -0
- package/src/client/actions/GuildScheduledEventUserAdd.js +32 -0
- package/src/client/actions/GuildScheduledEventUserRemove.js +32 -0
- package/src/client/actions/GuildStickerCreate.js +20 -0
- package/src/client/actions/GuildStickerDelete.js +21 -0
- package/src/client/actions/GuildStickerUpdate.js +20 -0
- package/src/client/actions/GuildStickersUpdate.js +34 -0
- package/src/client/actions/GuildUpdate.js +33 -0
- package/src/client/actions/InviteCreate.js +28 -0
- package/src/client/actions/InviteDelete.js +30 -0
- package/src/client/actions/MessageCreate.js +50 -0
- package/src/client/actions/MessageDelete.js +32 -0
- package/src/client/actions/MessageDeleteBulk.js +46 -0
- package/src/client/actions/MessagePollVoteAdd.js +33 -0
- package/src/client/actions/MessagePollVoteRemove.js +33 -0
- package/src/client/actions/MessageReactionAdd.js +68 -0
- package/src/client/actions/MessageReactionRemove.js +50 -0
- package/src/client/actions/MessageReactionRemoveAll.js +33 -0
- package/src/client/actions/MessageReactionRemoveEmoji.js +28 -0
- package/src/client/actions/MessageUpdate.js +26 -0
- package/src/client/actions/PresenceUpdate.js +50 -0
- package/src/client/actions/StageInstanceCreate.js +28 -0
- package/src/client/actions/StageInstanceDelete.js +33 -0
- package/src/client/actions/StageInstanceUpdate.js +30 -0
- package/src/client/actions/ThreadCreate.js +24 -0
- package/src/client/actions/ThreadDelete.js +32 -0
- package/src/client/actions/ThreadListSync.js +59 -0
- package/src/client/actions/ThreadMemberUpdate.js +30 -0
- package/src/client/actions/ThreadMembersUpdate.js +34 -0
- package/src/client/actions/TypingStart.js +29 -0
- package/src/client/actions/UserUpdate.js +35 -0
- package/src/client/actions/VoiceStateUpdate.js +50 -0
- package/src/client/actions/WebhooksUpdate.js +20 -0
- package/src/client/voice/ClientVoiceManager.js +151 -0
- package/src/client/voice/VoiceConnection.js +1249 -0
- package/src/client/voice/dispatcher/AnnexBDispatcher.js +120 -0
- package/src/client/voice/dispatcher/AudioDispatcher.js +145 -0
- package/src/client/voice/dispatcher/BaseDispatcher.js +459 -0
- package/src/client/voice/dispatcher/VPxDispatcher.js +54 -0
- package/src/client/voice/dispatcher/VideoDispatcher.js +68 -0
- package/src/client/voice/networking/VoiceUDPClient.js +173 -0
- package/src/client/voice/networking/VoiceWebSocket.js +286 -0
- package/src/client/voice/player/MediaPlayer.js +321 -0
- package/src/client/voice/player/processing/AnnexBNalSplitter.js +244 -0
- package/src/client/voice/player/processing/IvfSplitter.js +106 -0
- package/src/client/voice/player/processing/PCMInsertSilence.js +37 -0
- package/src/client/voice/receiver/PacketHandler.js +260 -0
- package/src/client/voice/receiver/Receiver.js +96 -0
- package/src/client/voice/receiver/Recorder.js +173 -0
- package/src/client/voice/util/Function.js +116 -0
- package/src/client/voice/util/PlayInterface.js +122 -0
- package/src/client/voice/util/Secretbox.js +64 -0
- package/src/client/voice/util/Silence.js +16 -0
- package/src/client/voice/util/Socket.js +62 -0
- package/src/client/voice/util/VolumeInterface.js +104 -0
- package/src/client/websocket/WebSocketManager.js +392 -0
- package/src/client/websocket/WebSocketShard.js +907 -0
- package/src/client/websocket/handlers/APPLICATION_COMMAND_CREATE.js +18 -0
- package/src/client/websocket/handlers/APPLICATION_COMMAND_DELETE.js +20 -0
- package/src/client/websocket/handlers/APPLICATION_COMMAND_PERMISSIONS_UPDATE.js +5 -0
- package/src/client/websocket/handlers/APPLICATION_COMMAND_UPDATE.js +20 -0
- package/src/client/websocket/handlers/AUTO_MODERATION_ACTION_EXECUTION.js +5 -0
- package/src/client/websocket/handlers/AUTO_MODERATION_RULE_CREATE.js +5 -0
- package/src/client/websocket/handlers/AUTO_MODERATION_RULE_DELETE.js +5 -0
- package/src/client/websocket/handlers/AUTO_MODERATION_RULE_UPDATE.js +5 -0
- package/src/client/websocket/handlers/CALL_CREATE.js +14 -0
- package/src/client/websocket/handlers/CALL_DELETE.js +11 -0
- package/src/client/websocket/handlers/CALL_UPDATE.js +11 -0
- package/src/client/websocket/handlers/CHANNEL_CREATE.js +5 -0
- package/src/client/websocket/handlers/CHANNEL_DELETE.js +5 -0
- package/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js +22 -0
- package/src/client/websocket/handlers/CHANNEL_RECIPIENT_ADD.js +19 -0
- package/src/client/websocket/handlers/CHANNEL_RECIPIENT_REMOVE.js +16 -0
- package/src/client/websocket/handlers/CHANNEL_UPDATE.js +16 -0
- package/src/client/websocket/handlers/GUILD_AUDIT_LOG_ENTRY_CREATE.js +5 -0
- package/src/client/websocket/handlers/GUILD_BAN_ADD.js +5 -0
- package/src/client/websocket/handlers/GUILD_BAN_REMOVE.js +5 -0
- package/src/client/websocket/handlers/GUILD_CREATE.js +52 -0
- package/src/client/websocket/handlers/GUILD_DELETE.js +5 -0
- package/src/client/websocket/handlers/GUILD_EMOJIS_UPDATE.js +5 -0
- package/src/client/websocket/handlers/GUILD_INTEGRATIONS_UPDATE.js +5 -0
- package/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js +39 -0
- package/src/client/websocket/handlers/GUILD_MEMBER_ADD.js +20 -0
- package/src/client/websocket/handlers/GUILD_MEMBER_REMOVE.js +5 -0
- package/src/client/websocket/handlers/GUILD_MEMBER_UPDATE.js +5 -0
- package/src/client/websocket/handlers/GUILD_ROLE_CREATE.js +5 -0
- package/src/client/websocket/handlers/GUILD_ROLE_DELETE.js +5 -0
- package/src/client/websocket/handlers/GUILD_ROLE_UPDATE.js +5 -0
- package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_CREATE.js +5 -0
- package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_DELETE.js +5 -0
- package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_UPDATE.js +5 -0
- package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_USER_ADD.js +5 -0
- package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_USER_REMOVE.js +5 -0
- package/src/client/websocket/handlers/GUILD_STICKERS_UPDATE.js +5 -0
- package/src/client/websocket/handlers/GUILD_UPDATE.js +5 -0
- package/src/client/websocket/handlers/INTERACTION_MODAL_CREATE.js +12 -0
- package/src/client/websocket/handlers/INVITE_CREATE.js +5 -0
- package/src/client/websocket/handlers/INVITE_DELETE.js +5 -0
- package/src/client/websocket/handlers/MESSAGE_CREATE.js +5 -0
- package/src/client/websocket/handlers/MESSAGE_DELETE.js +5 -0
- package/src/client/websocket/handlers/MESSAGE_DELETE_BULK.js +5 -0
- package/src/client/websocket/handlers/MESSAGE_POLL_VOTE_ADD.js +5 -0
- package/src/client/websocket/handlers/MESSAGE_POLL_VOTE_REMOVE.js +5 -0
- package/src/client/websocket/handlers/MESSAGE_REACTION_ADD.js +5 -0
- package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE.js +5 -0
- package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_ALL.js +5 -0
- package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.js +5 -0
- package/src/client/websocket/handlers/MESSAGE_UPDATE.js +16 -0
- package/src/client/websocket/handlers/PRESENCE_UPDATE.js +5 -0
- package/src/client/websocket/handlers/READY.js +121 -0
- package/src/client/websocket/handlers/RELATIONSHIP_ADD.js +19 -0
- package/src/client/websocket/handlers/RELATIONSHIP_REMOVE.js +17 -0
- package/src/client/websocket/handlers/RELATIONSHIP_UPDATE.js +41 -0
- package/src/client/websocket/handlers/RESUMED.js +14 -0
- package/src/client/websocket/handlers/STAGE_INSTANCE_CREATE.js +5 -0
- package/src/client/websocket/handlers/STAGE_INSTANCE_DELETE.js +5 -0
- package/src/client/websocket/handlers/STAGE_INSTANCE_UPDATE.js +5 -0
- package/src/client/websocket/handlers/THREAD_CREATE.js +5 -0
- package/src/client/websocket/handlers/THREAD_DELETE.js +5 -0
- package/src/client/websocket/handlers/THREAD_LIST_SYNC.js +5 -0
- package/src/client/websocket/handlers/THREAD_MEMBERS_UPDATE.js +5 -0
- package/src/client/websocket/handlers/THREAD_MEMBER_UPDATE.js +5 -0
- package/src/client/websocket/handlers/THREAD_UPDATE.js +16 -0
- package/src/client/websocket/handlers/TYPING_START.js +5 -0
- package/src/client/websocket/handlers/USER_GUILD_SETTINGS_UPDATE.js +6 -0
- package/src/client/websocket/handlers/USER_NOTE_UPDATE.js +5 -0
- package/src/client/websocket/handlers/USER_REQUIRED_ACTION_UPDATE.js +78 -0
- package/src/client/websocket/handlers/USER_SETTINGS_UPDATE.js +5 -0
- package/src/client/websocket/handlers/USER_UPDATE.js +5 -0
- package/src/client/websocket/handlers/VOICE_CHANNEL_EFFECT_SEND.js +16 -0
- package/src/client/websocket/handlers/VOICE_CHANNEL_STATUS_UPDATE.js +12 -0
- package/src/client/websocket/handlers/VOICE_SERVER_UPDATE.js +6 -0
- package/src/client/websocket/handlers/VOICE_STATE_UPDATE.js +5 -0
- package/src/client/websocket/handlers/WEBHOOKS_UPDATE.js +5 -0
- package/src/client/websocket/handlers/index.js +84 -0
- package/src/errors/DJSError.js +61 -0
- package/src/errors/Messages.js +217 -0
- package/src/errors/index.js +4 -0
- package/src/index.js +172 -0
- package/src/managers/ApplicationCommandManager.js +264 -0
- package/src/managers/ApplicationCommandPermissionsManager.js +417 -0
- package/src/managers/AutoModerationRuleManager.js +296 -0
- package/src/managers/BaseGuildEmojiManager.js +80 -0
- package/src/managers/BaseManager.js +19 -0
- package/src/managers/BillingManager.js +66 -0
- package/src/managers/CachedManager.js +71 -0
- package/src/managers/ChannelManager.js +148 -0
- package/src/managers/ClientUserSettingManager.js +372 -0
- package/src/managers/DataManager.js +61 -0
- package/src/managers/DeveloperManager.js +254 -0
- package/src/managers/GuildBanManager.js +250 -0
- package/src/managers/GuildChannelManager.js +488 -0
- package/src/managers/GuildEmojiManager.js +171 -0
- package/src/managers/GuildEmojiRoleManager.js +118 -0
- package/src/managers/GuildForumThreadManager.js +108 -0
- package/src/managers/GuildInviteManager.js +213 -0
- package/src/managers/GuildManager.js +338 -0
- package/src/managers/GuildMemberManager.js +599 -0
- package/src/managers/GuildMemberRoleManager.js +195 -0
- package/src/managers/GuildScheduledEventManager.js +314 -0
- package/src/managers/GuildSettingManager.js +155 -0
- package/src/managers/GuildStickerManager.js +179 -0
- package/src/managers/GuildTextThreadManager.js +98 -0
- package/src/managers/InteractionManager.js +39 -0
- package/src/managers/MessageManager.js +423 -0
- package/src/managers/PermissionOverwriteManager.js +164 -0
- package/src/managers/PresenceManager.js +71 -0
- package/src/managers/QuestManager.js +353 -0
- package/src/managers/ReactionManager.js +67 -0
- package/src/managers/ReactionUserManager.js +73 -0
- package/src/managers/RelationshipManager.js +278 -0
- package/src/managers/RoleManager.js +448 -0
- package/src/managers/SessionManager.js +66 -0
- package/src/managers/StageInstanceManager.js +162 -0
- package/src/managers/ThreadManager.js +175 -0
- package/src/managers/ThreadMemberManager.js +186 -0
- package/src/managers/UserManager.js +136 -0
- package/src/managers/UserNoteManager.js +53 -0
- package/src/managers/VoiceStateManager.js +59 -0
- package/src/rest/APIRequest.js +154 -0
- package/src/rest/APIRouter.js +53 -0
- package/src/rest/DiscordAPIError.js +119 -0
- package/src/rest/HTTPError.js +62 -0
- package/src/rest/RESTManager.js +67 -0
- package/src/rest/RateLimitError.js +55 -0
- package/src/rest/RequestHandler.js +466 -0
- package/src/sharding/Shard.js +444 -0
- package/src/sharding/ShardClientUtil.js +279 -0
- package/src/sharding/ShardingManager.js +319 -0
- package/src/structures/AnonymousGuild.js +98 -0
- package/src/structures/ApplicationCommand.js +593 -0
- package/src/structures/ApplicationRoleConnectionMetadata.js +48 -0
- package/src/structures/AutoModerationActionExecution.js +89 -0
- package/src/structures/AutoModerationRule.js +294 -0
- package/src/structures/AutocompleteInteraction.js +107 -0
- package/src/structures/Base.js +43 -0
- package/src/structures/BaseCommandInteraction.js +211 -0
- package/src/structures/BaseGuild.js +116 -0
- package/src/structures/BaseGuildEmoji.js +56 -0
- package/src/structures/BaseGuildTextChannel.js +191 -0
- package/src/structures/BaseGuildVoiceChannel.js +241 -0
- package/src/structures/BaseMessageComponent.js +181 -0
- package/src/structures/ButtonInteraction.js +11 -0
- package/src/structures/CallState.js +63 -0
- package/src/structures/CategoryChannel.js +85 -0
- package/src/structures/Channel.js +284 -0
- package/src/structures/ClientPresence.js +77 -0
- package/src/structures/ClientUser.js +655 -0
- package/src/structures/CommandInteraction.js +41 -0
- package/src/structures/CommandInteractionOptionResolver.js +276 -0
- package/src/structures/ContainerComponent.js +68 -0
- package/src/structures/ContextMenuInteraction.js +65 -0
- package/src/structures/DMChannel.js +219 -0
- package/src/structures/DirectoryChannel.js +20 -0
- package/src/structures/Emoji.js +148 -0
- package/src/structures/FileComponent.js +49 -0
- package/src/structures/ForumChannel.js +31 -0
- package/src/structures/GroupDMChannel.js +394 -0
- package/src/structures/Guild.js +1791 -0
- package/src/structures/GuildAuditLogs.js +746 -0
- package/src/structures/GuildBan.js +59 -0
- package/src/structures/GuildBoost.js +108 -0
- package/src/structures/GuildChannel.js +470 -0
- package/src/structures/GuildEmoji.js +161 -0
- package/src/structures/GuildMember.js +636 -0
- package/src/structures/GuildPreview.js +191 -0
- package/src/structures/GuildPreviewEmoji.js +27 -0
- package/src/structures/GuildScheduledEvent.js +536 -0
- package/src/structures/GuildTemplate.js +236 -0
- package/src/structures/Integration.js +188 -0
- package/src/structures/IntegrationApplication.js +96 -0
- package/src/structures/Interaction.js +290 -0
- package/src/structures/InteractionCollector.js +248 -0
- package/src/structures/InteractionWebhook.js +43 -0
- package/src/structures/Invite.js +358 -0
- package/src/structures/InviteGuild.js +23 -0
- package/src/structures/InviteStageInstance.js +86 -0
- package/src/structures/MediaChannel.js +11 -0
- package/src/structures/MediaGalleryComponent.js +41 -0
- package/src/structures/MediaGalleryItem.js +47 -0
- package/src/structures/Message.js +1252 -0
- package/src/structures/MessageActionRow.js +105 -0
- package/src/structures/MessageAttachment.js +216 -0
- package/src/structures/MessageButton.js +166 -0
- package/src/structures/MessageCollector.js +146 -0
- package/src/structures/MessageComponentInteraction.js +120 -0
- package/src/structures/MessageContextMenuInteraction.js +20 -0
- package/src/structures/MessageEmbed.js +596 -0
- package/src/structures/MessageMentions.js +273 -0
- package/src/structures/MessagePayload.js +354 -0
- package/src/structures/MessageReaction.js +181 -0
- package/src/structures/MessageSelectMenu.js +141 -0
- package/src/structures/Modal.js +161 -0
- package/src/structures/ModalSubmitFieldsResolver.js +53 -0
- package/src/structures/ModalSubmitInteraction.js +119 -0
- package/src/structures/NewsChannel.js +32 -0
- package/src/structures/OAuth2Guild.js +28 -0
- package/src/structures/PermissionOverwrites.js +198 -0
- package/src/structures/Poll.js +108 -0
- package/src/structures/PollAnswer.js +88 -0
- package/src/structures/Presence.js +1157 -0
- package/src/structures/ReactionCollector.js +229 -0
- package/src/structures/ReactionEmoji.js +31 -0
- package/src/structures/Role.js +590 -0
- package/src/structures/SectionComponent.js +48 -0
- package/src/structures/SelectMenuInteraction.js +21 -0
- package/src/structures/SeparatorComponent.js +48 -0
- package/src/structures/Session.js +81 -0
- package/src/structures/StageChannel.js +104 -0
- package/src/structures/StageInstance.js +208 -0
- package/src/structures/Sticker.js +310 -0
- package/src/structures/StickerPack.js +95 -0
- package/src/structures/StoreChannel.js +56 -0
- package/src/structures/Team.js +118 -0
- package/src/structures/TeamMember.js +80 -0
- package/src/structures/TextChannel.js +33 -0
- package/src/structures/TextDisplayComponent.js +40 -0
- package/src/structures/TextInputComponent.js +132 -0
- package/src/structures/ThreadChannel.js +605 -0
- package/src/structures/ThreadMember.js +105 -0
- package/src/structures/ThreadOnlyChannel.js +249 -0
- package/src/structures/ThumbnailComponent.js +57 -0
- package/src/structures/Typing.js +74 -0
- package/src/structures/UnfurledMediaItem.js +29 -0
- package/src/structures/User.js +640 -0
- package/src/structures/UserContextMenuInteraction.js +29 -0
- package/src/structures/VoiceChannel.js +110 -0
- package/src/structures/VoiceChannelEffect.js +69 -0
- package/src/structures/VoiceRegion.js +53 -0
- package/src/structures/VoiceState.js +354 -0
- package/src/structures/WebEmbed.js +373 -0
- package/src/structures/Webhook.js +478 -0
- package/src/structures/WelcomeChannel.js +60 -0
- package/src/structures/WelcomeScreen.js +48 -0
- package/src/structures/Widget.js +87 -0
- package/src/structures/WidgetMember.js +99 -0
- package/src/structures/interfaces/Application.js +953 -0
- package/src/structures/interfaces/Collector.js +300 -0
- package/src/structures/interfaces/InteractionResponses.js +313 -0
- package/src/structures/interfaces/TextBasedChannel.js +821 -0
- package/src/util/APITypes.js +59 -0
- package/src/util/ActivityFlags.js +44 -0
- package/src/util/ApplicationFlags.js +76 -0
- package/src/util/AttachmentFlags.js +38 -0
- package/src/util/BitField.js +170 -0
- package/src/util/ChannelFlags.js +45 -0
- package/src/util/Constants.js +1914 -0
- package/src/util/DataResolver.js +146 -0
- package/src/util/Formatters.js +228 -0
- package/src/util/GuildMemberFlags.js +43 -0
- package/src/util/Intents.js +74 -0
- package/src/util/InviteFlags.js +34 -0
- package/src/util/LimitedCollection.js +131 -0
- package/src/util/MessageFlags.js +63 -0
- package/src/util/Options.js +358 -0
- package/src/util/Permissions.js +202 -0
- package/src/util/PremiumUsageFlags.js +31 -0
- package/src/util/PurchasedFlags.js +33 -0
- package/src/util/RemoteAuth.js +415 -0
- package/src/util/RoleFlags.js +37 -0
- package/src/util/SnowflakeUtil.js +92 -0
- package/src/util/Speaking.js +33 -0
- package/src/util/Sweepers.js +466 -0
- package/src/util/SystemChannelFlags.js +55 -0
- package/src/util/ThreadMemberFlags.js +30 -0
- package/src/util/UserFlags.js +104 -0
- package/src/util/Util.js +1048 -0
- package/typings/enums.d.ts +439 -0
- package/typings/index.d.ts +8505 -0
- package/typings/index.test-d.ts +0 -0
- package/typings/rawDataTypes.d.ts +403 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const process = require('node:process');
|
|
4
|
+
const { Error } = require('../errors');
|
|
5
|
+
const { Events } = require('../util/Constants');
|
|
6
|
+
const Util = require('../util/Util');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Helper class for sharded clients spawned as a child process/worker, such as from a {@link ShardingManager}.
|
|
10
|
+
* Utilizes IPC to send and receive data to/from the master process and other shards.
|
|
11
|
+
* @deprecated
|
|
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
|
+
if (mode === 'process') {
|
|
34
|
+
process.on('message', this._handleMessage.bind(this));
|
|
35
|
+
client.on('ready', () => {
|
|
36
|
+
process.send({ _ready: true });
|
|
37
|
+
});
|
|
38
|
+
client.on('disconnect', () => {
|
|
39
|
+
process.send({ _disconnect: true });
|
|
40
|
+
});
|
|
41
|
+
client.on('reconnecting', () => {
|
|
42
|
+
process.send({ _reconnecting: true });
|
|
43
|
+
});
|
|
44
|
+
} else if (mode === 'worker') {
|
|
45
|
+
this.parentPort = require('node:worker_threads').parentPort;
|
|
46
|
+
this.parentPort.on('message', this._handleMessage.bind(this));
|
|
47
|
+
client.on('ready', () => {
|
|
48
|
+
this.parentPort.postMessage({ _ready: true });
|
|
49
|
+
});
|
|
50
|
+
client.on('disconnect', () => {
|
|
51
|
+
this.parentPort.postMessage({ _disconnect: true });
|
|
52
|
+
});
|
|
53
|
+
client.on('reconnecting', () => {
|
|
54
|
+
this.parentPort.postMessage({ _reconnecting: true });
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Array of shard ids of this client
|
|
61
|
+
* @type {number[]}
|
|
62
|
+
* @readonly
|
|
63
|
+
*/
|
|
64
|
+
get ids() {
|
|
65
|
+
return this.client.options.shards;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Total number of shards
|
|
70
|
+
* @type {number}
|
|
71
|
+
* @readonly
|
|
72
|
+
*/
|
|
73
|
+
get count() {
|
|
74
|
+
return this.client.options.shardCount;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Sends a message to the master process.
|
|
79
|
+
* @param {*} message Message to send
|
|
80
|
+
* @returns {Promise<void>}
|
|
81
|
+
* @emits Shard#message
|
|
82
|
+
*/
|
|
83
|
+
send(message) {
|
|
84
|
+
return new Promise((resolve, reject) => {
|
|
85
|
+
if (this.mode === 'process') {
|
|
86
|
+
process.send(message, err => {
|
|
87
|
+
if (err) reject(err);
|
|
88
|
+
else resolve();
|
|
89
|
+
});
|
|
90
|
+
} else if (this.mode === 'worker') {
|
|
91
|
+
this.parentPort.postMessage(message);
|
|
92
|
+
resolve();
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Fetches a client property value of each shard, or a given shard.
|
|
99
|
+
* @param {string} prop Name of the client property to get, using periods for nesting
|
|
100
|
+
* @param {number} [shard] Shard to fetch property from, all if undefined
|
|
101
|
+
* @returns {Promise<*|Array<*>>}
|
|
102
|
+
* @example
|
|
103
|
+
* client.shard.fetchClientValues('guilds.cache.size')
|
|
104
|
+
* .then(results => console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`))
|
|
105
|
+
* .catch(console.error);
|
|
106
|
+
* @see {@link ShardingManager#fetchClientValues}
|
|
107
|
+
*/
|
|
108
|
+
fetchClientValues(prop, shard) {
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
110
|
+
const parent = this.parentPort ?? process;
|
|
111
|
+
|
|
112
|
+
const listener = message => {
|
|
113
|
+
if (message?._sFetchProp !== prop || message._sFetchPropShard !== shard) return;
|
|
114
|
+
parent.removeListener('message', listener);
|
|
115
|
+
this.decrementMaxListeners(parent);
|
|
116
|
+
if (!message._error) resolve(message._result);
|
|
117
|
+
else reject(Util.makeError(message._error));
|
|
118
|
+
};
|
|
119
|
+
this.incrementMaxListeners(parent);
|
|
120
|
+
parent.on('message', listener);
|
|
121
|
+
|
|
122
|
+
this.send({ _sFetchProp: prop, _sFetchPropShard: shard }).catch(err => {
|
|
123
|
+
parent.removeListener('message', listener);
|
|
124
|
+
this.decrementMaxListeners(parent);
|
|
125
|
+
reject(err);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Evaluates a script or function on all shards, or a given shard, in the context of the {@link Client}s.
|
|
132
|
+
* @param {Function} script JavaScript to run on each shard
|
|
133
|
+
* @param {BroadcastEvalOptions} [options={}] The options for the broadcast
|
|
134
|
+
* @returns {Promise<*|Array<*>>} Results of the script execution
|
|
135
|
+
* @example
|
|
136
|
+
* client.shard.broadcastEval(client => client.guilds.cache.size)
|
|
137
|
+
* .then(results => console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`))
|
|
138
|
+
* .catch(console.error);
|
|
139
|
+
* @see {@link ShardingManager#broadcastEval}
|
|
140
|
+
*/
|
|
141
|
+
broadcastEval(script, options = {}) {
|
|
142
|
+
return new Promise((resolve, reject) => {
|
|
143
|
+
const parent = this.parentPort ?? process;
|
|
144
|
+
if (typeof script !== 'function') {
|
|
145
|
+
reject(new TypeError('SHARDING_INVALID_EVAL_BROADCAST'));
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
script = `(${script})(this, ${JSON.stringify(options.context)})`;
|
|
149
|
+
|
|
150
|
+
const listener = message => {
|
|
151
|
+
if (message?._sEval !== script || message._sEvalShard !== options.shard) return;
|
|
152
|
+
parent.removeListener('message', listener);
|
|
153
|
+
this.decrementMaxListeners(parent);
|
|
154
|
+
if (!message._error) resolve(message._result);
|
|
155
|
+
else reject(Util.makeError(message._error));
|
|
156
|
+
};
|
|
157
|
+
this.incrementMaxListeners(parent);
|
|
158
|
+
parent.on('message', listener);
|
|
159
|
+
this.send({ _sEval: script, _sEvalShard: options.shard }).catch(err => {
|
|
160
|
+
parent.removeListener('message', listener);
|
|
161
|
+
this.decrementMaxListeners(parent);
|
|
162
|
+
reject(err);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Requests a respawn of all shards.
|
|
169
|
+
* @param {MultipleShardRespawnOptions} [options] Options for respawning shards
|
|
170
|
+
* @returns {Promise<void>} Resolves upon the message being sent
|
|
171
|
+
* @see {@link ShardingManager#respawnAll}
|
|
172
|
+
*/
|
|
173
|
+
respawnAll({ shardDelay = 5_000, respawnDelay = 500, timeout = 30_000 } = {}) {
|
|
174
|
+
return this.send({ _sRespawnAll: { shardDelay, respawnDelay, timeout } });
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Handles an IPC message.
|
|
179
|
+
* @param {*} message Message received
|
|
180
|
+
* @private
|
|
181
|
+
*/
|
|
182
|
+
async _handleMessage(message) {
|
|
183
|
+
if (!message) return;
|
|
184
|
+
if (message._fetchProp) {
|
|
185
|
+
try {
|
|
186
|
+
const props = message._fetchProp.split('.');
|
|
187
|
+
let value = this.client;
|
|
188
|
+
for (const prop of props) value = value[prop];
|
|
189
|
+
this._respond('fetchProp', { _fetchProp: message._fetchProp, _result: value });
|
|
190
|
+
} catch (err) {
|
|
191
|
+
this._respond('fetchProp', { _fetchProp: message._fetchProp, _error: Util.makePlainError(err) });
|
|
192
|
+
}
|
|
193
|
+
} else if (message._eval) {
|
|
194
|
+
try {
|
|
195
|
+
this._respond('eval', { _eval: message._eval, _result: await this.client._eval(message._eval) });
|
|
196
|
+
} catch (err) {
|
|
197
|
+
this._respond('eval', { _eval: message._eval, _error: Util.makePlainError(err) });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Sends a message to the master process, emitting an error from the client upon failure.
|
|
204
|
+
* @param {string} type Type of response to send
|
|
205
|
+
* @param {*} message Message to send
|
|
206
|
+
* @private
|
|
207
|
+
*/
|
|
208
|
+
_respond(type, message) {
|
|
209
|
+
this.send(message).catch(err => {
|
|
210
|
+
const error = new Error(`Error when sending ${type} response to master process: ${err.message}`);
|
|
211
|
+
error.stack = err.stack;
|
|
212
|
+
/**
|
|
213
|
+
* Emitted when the client encounters an error.
|
|
214
|
+
* <warn>Errors thrown within this event do not have a catch handler, it is
|
|
215
|
+
* recommended to not use async functions as `error` event handlers. See the
|
|
216
|
+
* [Node.js docs](https://nodejs.org/api/events.html#capture-rejections-of-promises) for details.</warn>
|
|
217
|
+
* @event Client#error
|
|
218
|
+
* @param {Error} error The error encountered
|
|
219
|
+
*/
|
|
220
|
+
this.client.emit(Events.ERROR, error);
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Creates/gets the singleton of this class.
|
|
226
|
+
* @param {Client} client The client to use
|
|
227
|
+
* @param {ShardingManagerMode} mode Mode the shard was spawned with
|
|
228
|
+
* @returns {ShardClientUtil}
|
|
229
|
+
*/
|
|
230
|
+
static singleton(client, mode) {
|
|
231
|
+
if (!this._singleton) {
|
|
232
|
+
this._singleton = new this(client, mode);
|
|
233
|
+
} else {
|
|
234
|
+
client.emit(
|
|
235
|
+
Events.WARN,
|
|
236
|
+
'Multiple clients created in child process/worker; only the first will handle sharding helpers.',
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
return this._singleton;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Get the shard id for a given guild id.
|
|
244
|
+
* @param {Snowflake} guildId Snowflake guild id to get shard id for
|
|
245
|
+
* @param {number} shardCount Number of shards
|
|
246
|
+
* @returns {number}
|
|
247
|
+
*/
|
|
248
|
+
static shardIdForGuildId(guildId, shardCount) {
|
|
249
|
+
const shard = Number(BigInt(guildId) >> 22n) % shardCount;
|
|
250
|
+
if (shard < 0) throw new Error('SHARDING_SHARD_MISCALCULATION', shard, guildId, shardCount);
|
|
251
|
+
return shard;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Increments max listeners by one for a given emitter, if they are not zero.
|
|
256
|
+
* @param {EventEmitter|process} emitter The emitter that emits the events.
|
|
257
|
+
* @private
|
|
258
|
+
*/
|
|
259
|
+
incrementMaxListeners(emitter) {
|
|
260
|
+
const maxListeners = emitter.getMaxListeners();
|
|
261
|
+
if (maxListeners !== 0) {
|
|
262
|
+
emitter.setMaxListeners(maxListeners + 1);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Decrements max listeners by one for a given emitter, if they are not zero.
|
|
268
|
+
* @param {EventEmitter|process} emitter The emitter that emits the events.
|
|
269
|
+
* @private
|
|
270
|
+
*/
|
|
271
|
+
decrementMaxListeners(emitter) {
|
|
272
|
+
const maxListeners = emitter.getMaxListeners();
|
|
273
|
+
if (maxListeners !== 0) {
|
|
274
|
+
emitter.setMaxListeners(maxListeners - 1);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
module.exports = ShardClientUtil;
|
|
@@ -0,0 +1,319 @@
|
|
|
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 { Error, TypeError, RangeError } = require('../errors');
|
|
11
|
+
const Util = 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 utilize 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
|
+
* @deprecated
|
|
22
|
+
*/
|
|
23
|
+
class ShardingManager extends EventEmitter {
|
|
24
|
+
/**
|
|
25
|
+
* The mode to spawn shards with for a {@link ShardingManager}. Can be either one of:
|
|
26
|
+
* * 'process' to use child processes
|
|
27
|
+
* * 'worker' to use [Worker threads](https://nodejs.org/api/worker_threads.html)
|
|
28
|
+
* @typedef {string} ShardingManagerMode
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The options to spawn shards with for a {@link ShardingManager}.
|
|
33
|
+
* @typedef {Object} ShardingManagerOptions
|
|
34
|
+
* @property {string|number} [totalShards='auto'] Number of total shards of all shard managers or "auto"
|
|
35
|
+
* @property {string|number[]} [shardList='auto'] List of shards to spawn or "auto"
|
|
36
|
+
* @property {ShardingManagerMode} [mode='process'] Which mode to use for shards
|
|
37
|
+
* @property {boolean} [respawn=true] Whether shards should automatically respawn upon exiting
|
|
38
|
+
* @property {string[]} [shardArgs=[]] Arguments to pass to the shard script when spawning
|
|
39
|
+
* (only available when mode is set to 'process')
|
|
40
|
+
* @property {string[]} [execArgv=[]] Arguments to pass to the shard script executable when spawning
|
|
41
|
+
* (only available when mode is set to 'process')
|
|
42
|
+
* @property {string} [token] Token to use for automatic shard count and passing to shards
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @param {string} file Path to your shard script file
|
|
47
|
+
* @param {ShardingManagerOptions} [options] Options for the sharding manager
|
|
48
|
+
*/
|
|
49
|
+
constructor(file, options = {}) {
|
|
50
|
+
super();
|
|
51
|
+
options = Util.mergeDefault(
|
|
52
|
+
{
|
|
53
|
+
totalShards: 'auto',
|
|
54
|
+
mode: 'process',
|
|
55
|
+
respawn: true,
|
|
56
|
+
shardArgs: [],
|
|
57
|
+
execArgv: [],
|
|
58
|
+
token: process.env.DISCORD_TOKEN,
|
|
59
|
+
},
|
|
60
|
+
options,
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Path to the shard script file
|
|
65
|
+
* @type {string}
|
|
66
|
+
*/
|
|
67
|
+
this.file = file;
|
|
68
|
+
if (!file) throw new Error('CLIENT_INVALID_OPTION', 'File', 'specified.');
|
|
69
|
+
if (!path.isAbsolute(file)) this.file = path.resolve(process.cwd(), file);
|
|
70
|
+
const stats = fs.statSync(this.file);
|
|
71
|
+
if (!stats.isFile()) throw new Error('CLIENT_INVALID_OPTION', 'File', 'a file');
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* List of shards this sharding manager spawns
|
|
75
|
+
* @type {string|number[]}
|
|
76
|
+
*/
|
|
77
|
+
this.shardList = options.shardList ?? 'auto';
|
|
78
|
+
if (this.shardList !== 'auto') {
|
|
79
|
+
if (!Array.isArray(this.shardList)) {
|
|
80
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'shardList', 'an array.');
|
|
81
|
+
}
|
|
82
|
+
this.shardList = [...new Set(this.shardList)];
|
|
83
|
+
if (this.shardList.length < 1) throw new RangeError('CLIENT_INVALID_OPTION', 'shardList', 'at least 1 id.');
|
|
84
|
+
if (
|
|
85
|
+
this.shardList.some(
|
|
86
|
+
shardId => typeof shardId !== 'number' || isNaN(shardId) || !Number.isInteger(shardId) || shardId < 0,
|
|
87
|
+
)
|
|
88
|
+
) {
|
|
89
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'shardList', 'an array of positive integers.');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Amount of shards that all sharding managers spawn in total
|
|
95
|
+
* @type {number}
|
|
96
|
+
*/
|
|
97
|
+
this.totalShards = options.totalShards || 'auto';
|
|
98
|
+
if (this.totalShards !== 'auto') {
|
|
99
|
+
if (typeof this.totalShards !== 'number' || isNaN(this.totalShards)) {
|
|
100
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'a number.');
|
|
101
|
+
}
|
|
102
|
+
if (this.totalShards < 1) throw new RangeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'at least 1.');
|
|
103
|
+
if (!Number.isInteger(this.totalShards)) {
|
|
104
|
+
throw new RangeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'an integer.');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Mode for shards to spawn with
|
|
110
|
+
* @type {ShardingManagerMode}
|
|
111
|
+
*/
|
|
112
|
+
this.mode = options.mode;
|
|
113
|
+
if (this.mode !== 'process' && this.mode !== 'worker') {
|
|
114
|
+
throw new RangeError('CLIENT_INVALID_OPTION', 'Sharding mode', '"process" or "worker"');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Whether shards should automatically respawn upon exiting
|
|
119
|
+
* @type {boolean}
|
|
120
|
+
*/
|
|
121
|
+
this.respawn = options.respawn;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* An array of arguments to pass to shards (only when {@link ShardingManager#mode} is `process`)
|
|
125
|
+
* @type {string[]}
|
|
126
|
+
*/
|
|
127
|
+
this.shardArgs = options.shardArgs;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* An array of arguments to pass to the executable (only when {@link ShardingManager#mode} is `process`)
|
|
131
|
+
* @type {string[]}
|
|
132
|
+
*/
|
|
133
|
+
this.execArgv = options.execArgv;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Token to use for obtaining the automatic shard count, and passing to shards
|
|
137
|
+
* @type {?string}
|
|
138
|
+
*/
|
|
139
|
+
this.token = options.token?.replace(/^Bot\s*/i, '') ?? null;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* A collection of shards that this manager has spawned
|
|
143
|
+
* @type {Collection<number, Shard>}
|
|
144
|
+
*/
|
|
145
|
+
this.shards = new Collection();
|
|
146
|
+
|
|
147
|
+
process.env.SHARDING_MANAGER = true;
|
|
148
|
+
process.env.SHARDING_MANAGER_MODE = this.mode;
|
|
149
|
+
process.env.DISCORD_TOKEN = this.token;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Creates a single shard.
|
|
154
|
+
* <warn>Using this method is usually not necessary if you use the spawn method.</warn>
|
|
155
|
+
* @param {number} [id=this.shards.size] Id of the shard to create
|
|
156
|
+
* <info>This is usually not necessary to manually specify.</info>
|
|
157
|
+
* @returns {Shard} Note that the created shard needs to be explicitly spawned using its spawn method.
|
|
158
|
+
*/
|
|
159
|
+
createShard(id = this.shards.size) {
|
|
160
|
+
const shard = new Shard(this, id);
|
|
161
|
+
this.shards.set(id, shard);
|
|
162
|
+
/**
|
|
163
|
+
* Emitted upon creating a shard.
|
|
164
|
+
* @event ShardingManager#shardCreate
|
|
165
|
+
* @param {Shard} shard Shard that was created
|
|
166
|
+
*/
|
|
167
|
+
this.emit('shardCreate', shard);
|
|
168
|
+
return shard;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Options used to spawn multiple shards.
|
|
173
|
+
* @typedef {Object} MultipleShardSpawnOptions
|
|
174
|
+
* @property {number|string} [amount=this.totalShards] Number of shards to spawn
|
|
175
|
+
* @property {number} [delay=5500] How long to wait in between spawning each shard (in milliseconds)
|
|
176
|
+
* @property {number} [timeout=30000] The amount in milliseconds to wait until the {@link Client} has become ready
|
|
177
|
+
*/
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Spawns multiple shards.
|
|
181
|
+
* @param {MultipleShardSpawnOptions} [options] Options for spawning shards
|
|
182
|
+
* @returns {Promise<Collection<number, Shard>>}
|
|
183
|
+
*/
|
|
184
|
+
async spawn({ amount = this.totalShards, delay = 5500, timeout = 30_000 } = {}) {
|
|
185
|
+
// Obtain/verify the number of shards to spawn
|
|
186
|
+
if (amount === 'auto') {
|
|
187
|
+
amount = 1;
|
|
188
|
+
} else {
|
|
189
|
+
if (typeof amount !== 'number' || isNaN(amount)) {
|
|
190
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'a number.');
|
|
191
|
+
}
|
|
192
|
+
if (amount < 1) throw new RangeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'at least 1.');
|
|
193
|
+
if (!Number.isInteger(amount)) {
|
|
194
|
+
throw new TypeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'an integer.');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Make sure this many shards haven't already been spawned
|
|
199
|
+
if (this.shards.size >= amount) throw new Error('SHARDING_ALREADY_SPAWNED', this.shards.size);
|
|
200
|
+
if (this.shardList === 'auto' || this.totalShards === 'auto' || this.totalShards !== amount) {
|
|
201
|
+
this.shardList = [...Array(amount).keys()];
|
|
202
|
+
}
|
|
203
|
+
if (this.totalShards === 'auto' || this.totalShards !== amount) {
|
|
204
|
+
this.totalShards = amount;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (this.shardList.some(shardId => shardId >= amount)) {
|
|
208
|
+
throw new RangeError(
|
|
209
|
+
'CLIENT_INVALID_OPTION',
|
|
210
|
+
'Amount of shards',
|
|
211
|
+
'bigger than the highest shardId in the shardList option.',
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Spawn the shards
|
|
216
|
+
for (const shardId of this.shardList) {
|
|
217
|
+
const promises = [];
|
|
218
|
+
const shard = this.createShard(shardId);
|
|
219
|
+
promises.push(shard.spawn(timeout));
|
|
220
|
+
if (delay > 0 && this.shards.size !== this.shardList.length) promises.push(sleep(delay));
|
|
221
|
+
await Promise.all(promises); // eslint-disable-line no-await-in-loop
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return this.shards;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Sends a message to all shards.
|
|
229
|
+
* @param {*} message Message to be sent to the shards
|
|
230
|
+
* @returns {Promise<Shard[]>}
|
|
231
|
+
*/
|
|
232
|
+
broadcast(message) {
|
|
233
|
+
const promises = [];
|
|
234
|
+
for (const shard of this.shards.values()) promises.push(shard.send(message));
|
|
235
|
+
return Promise.all(promises);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Options for {@link ShardingManager#broadcastEval} and {@link ShardClientUtil#broadcastEval}.
|
|
240
|
+
* @typedef {Object} BroadcastEvalOptions
|
|
241
|
+
* @property {number} [shard] Shard to run script on, all if undefined
|
|
242
|
+
* @property {*} [context] The JSON-serializable values to call the script with
|
|
243
|
+
*/
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Evaluates a script on all shards, or a given shard, in the context of the {@link Client}s.
|
|
247
|
+
* @param {Function} script JavaScript to run on each shard
|
|
248
|
+
* @param {BroadcastEvalOptions} [options={}] The options for the broadcast
|
|
249
|
+
* @returns {Promise<*|Array<*>>} Results of the script execution
|
|
250
|
+
*/
|
|
251
|
+
async broadcastEval(script, options = {}) {
|
|
252
|
+
if (typeof script !== 'function') throw new TypeError('SHARDING_INVALID_EVAL_BROADCAST');
|
|
253
|
+
return this._performOnShards('eval', [`(${script})(this, ${JSON.stringify(options.context)})`], options.shard);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Fetches a client property value of each shard, or a given shard.
|
|
258
|
+
* @param {string} prop Name of the client property to get, using periods for nesting
|
|
259
|
+
* @param {number} [shard] Shard to fetch property from, all if undefined
|
|
260
|
+
* @returns {Promise<*|Array<*>>}
|
|
261
|
+
* @example
|
|
262
|
+
* manager.fetchClientValues('guilds.cache.size')
|
|
263
|
+
* .then(results => console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`))
|
|
264
|
+
* .catch(console.error);
|
|
265
|
+
*/
|
|
266
|
+
fetchClientValues(prop, shard) {
|
|
267
|
+
return this._performOnShards('fetchClientValue', [prop], shard);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Runs a method with given arguments on all shards, or a given shard.
|
|
272
|
+
* @param {string} method Method name to run on each shard
|
|
273
|
+
* @param {Array<*>} args Arguments to pass through to the method call
|
|
274
|
+
* @param {number} [shard] Shard to run on, all if undefined
|
|
275
|
+
* @returns {Promise<*|Array<*>>} Results of the method execution
|
|
276
|
+
* @private
|
|
277
|
+
*/
|
|
278
|
+
async _performOnShards(method, args, shard) {
|
|
279
|
+
if (this.shards.size === 0) throw new Error('SHARDING_NO_SHARDS');
|
|
280
|
+
|
|
281
|
+
if (typeof shard === 'number') {
|
|
282
|
+
if (this.shards.has(shard)) return this.shards.get(shard)[method](...args);
|
|
283
|
+
throw new Error('SHARDING_SHARD_NOT_FOUND', shard);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (this.shards.size !== this.shardList.length) throw new Error('SHARDING_IN_PROCESS');
|
|
287
|
+
|
|
288
|
+
const promises = [];
|
|
289
|
+
for (const sh of this.shards.values()) promises.push(sh[method](...args));
|
|
290
|
+
return Promise.all(promises);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Options used to respawn all shards.
|
|
295
|
+
* @typedef {Object} MultipleShardRespawnOptions
|
|
296
|
+
* @property {number} [shardDelay=5000] How long to wait between shards (in milliseconds)
|
|
297
|
+
* @property {number} [respawnDelay=500] How long to wait between killing a shard's process and restarting it
|
|
298
|
+
* (in milliseconds)
|
|
299
|
+
* @property {number} [timeout=30000] The amount in milliseconds to wait for a shard to become ready before
|
|
300
|
+
* continuing to another (`-1` or `Infinity` for no wait)
|
|
301
|
+
*/
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Kills all running shards and respawns them.
|
|
305
|
+
* @param {MultipleShardRespawnOptions} [options] Options for respawning shards
|
|
306
|
+
* @returns {Promise<Collection<number, Shard>>}
|
|
307
|
+
*/
|
|
308
|
+
async respawnAll({ shardDelay = 5_000, respawnDelay = 500, timeout = 30_000 } = {}) {
|
|
309
|
+
let s = 0;
|
|
310
|
+
for (const shard of this.shards.values()) {
|
|
311
|
+
const promises = [shard.respawn({ delay: respawnDelay, timeout })];
|
|
312
|
+
if (++s < this.shards.size && shardDelay > 0) promises.push(sleep(shardDelay));
|
|
313
|
+
await Promise.all(promises); // eslint-disable-line no-await-in-loop
|
|
314
|
+
}
|
|
315
|
+
return this.shards;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
module.exports = ShardingManager;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const BaseGuild = require('./BaseGuild');
|
|
4
|
+
const { VerificationLevels, NSFWLevels } = require('../util/Constants');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Bundles common attributes and methods between {@link Guild} and {@link InviteGuild}
|
|
8
|
+
* @extends {BaseGuild}
|
|
9
|
+
* @abstract
|
|
10
|
+
*/
|
|
11
|
+
class AnonymousGuild extends BaseGuild {
|
|
12
|
+
constructor(client, data, immediatePatch = true) {
|
|
13
|
+
super(client, data);
|
|
14
|
+
if (immediatePatch) this._patch(data);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_patch(data) {
|
|
18
|
+
if ('features' in data) this.features = data.features;
|
|
19
|
+
|
|
20
|
+
if ('splash' in data) {
|
|
21
|
+
/**
|
|
22
|
+
* The hash of the guild invite splash image
|
|
23
|
+
* @type {?string}
|
|
24
|
+
*/
|
|
25
|
+
this.splash = data.splash;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if ('banner' in data) {
|
|
29
|
+
/**
|
|
30
|
+
* The hash of the guild banner
|
|
31
|
+
* @type {?string}
|
|
32
|
+
*/
|
|
33
|
+
this.banner = data.banner;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if ('description' in data) {
|
|
37
|
+
/**
|
|
38
|
+
* The description of the guild, if any
|
|
39
|
+
* @type {?string}
|
|
40
|
+
*/
|
|
41
|
+
this.description = data.description;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if ('verification_level' in data) {
|
|
45
|
+
/**
|
|
46
|
+
* The verification level of the guild
|
|
47
|
+
* @type {VerificationLevel}
|
|
48
|
+
*/
|
|
49
|
+
this.verificationLevel = VerificationLevels[data.verification_level];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if ('vanity_url_code' in data) {
|
|
53
|
+
/**
|
|
54
|
+
* The vanity invite code of the guild, if any
|
|
55
|
+
* @type {?string}
|
|
56
|
+
*/
|
|
57
|
+
this.vanityURLCode = data.vanity_url_code;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if ('nsfw_level' in data) {
|
|
61
|
+
/**
|
|
62
|
+
* The NSFW level of this guild
|
|
63
|
+
* @type {NSFWLevel}
|
|
64
|
+
*/
|
|
65
|
+
this.nsfwLevel = NSFWLevels[data.nsfw_level];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if ('premium_subscription_count' in data) {
|
|
69
|
+
/**
|
|
70
|
+
* The total number of boosts for this server
|
|
71
|
+
* @type {?number}
|
|
72
|
+
*/
|
|
73
|
+
this.premiumSubscriptionCount = data.premium_subscription_count;
|
|
74
|
+
} else {
|
|
75
|
+
this.premiumSubscriptionCount ??= null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The URL to this guild's banner.
|
|
81
|
+
* @param {StaticImageURLOptions} [options={}] Options for the Image URL
|
|
82
|
+
* @returns {?string}
|
|
83
|
+
*/
|
|
84
|
+
bannerURL({ format, size } = {}) {
|
|
85
|
+
return this.banner && this.client.rest.cdn.Banner(this.id, this.banner, format, size);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The URL to this guild's invite splash image.
|
|
90
|
+
* @param {StaticImageURLOptions} [options={}] Options for the Image URL
|
|
91
|
+
* @returns {?string}
|
|
92
|
+
*/
|
|
93
|
+
splashURL({ format, size } = {}) {
|
|
94
|
+
return this.splash && this.client.rest.cdn.Splash(this.id, this.splash, format, size);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
module.exports = AnonymousGuild;
|