discord-sb-v13 0.0.1-security → 2.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.
Potentially problematic release.
This version of discord-sb-v13 might be problematic. Click here for more details.
- package/LICENSE +674 -0
- package/README.md +119 -5
- package/package.json +101 -6
- package/src/WebSocket.js +39 -0
- package/src/client/BaseClient.js +87 -0
- package/src/client/Client.js +1154 -0
- package/src/client/WebhookClient.js +61 -0
- package/src/client/actions/Action.js +115 -0
- package/src/client/actions/ActionsManager.js +72 -0
- package/src/client/actions/ApplicationCommandPermissionsUpdate.js +34 -0
- package/src/client/actions/AutoModerationActionExecution.js +26 -0
- package/src/client/actions/AutoModerationRuleCreate.js +27 -0
- package/src/client/actions/AutoModerationRuleDelete.js +31 -0
- package/src/client/actions/AutoModerationRuleUpdate.js +29 -0
- package/src/client/actions/ChannelCreate.js +23 -0
- package/src/client/actions/ChannelDelete.js +39 -0
- package/src/client/actions/ChannelUpdate.js +34 -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/InteractionCreate.js +115 -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/MessageReactionAdd.js +56 -0
- package/src/client/actions/MessageReactionRemove.js +45 -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 +45 -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 +57 -0
- package/src/client/actions/WebhooksUpdate.js +20 -0
- package/src/client/voice/ClientVoiceManager.js +51 -0
- package/src/client/websocket/WebSocketManager.js +412 -0
- package/src/client/websocket/WebSocketShard.js +908 -0
- package/src/client/websocket/handlers/APPLICATION_COMMAND_AUTOCOMPLETE_RESPONSE.js +23 -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 +16 -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_APPLICATION_COMMANDS_UPDATE.js +11 -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 +46 -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_LIST_UPDATE.js +55 -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_CREATE.js +16 -0
- package/src/client/websocket/handlers/INTERACTION_FAILURE.js +18 -0
- package/src/client/websocket/handlers/INTERACTION_MODAL_CREATE.js +11 -0
- package/src/client/websocket/handlers/INTERACTION_SUCCESS.js +30 -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_ACK.js +16 -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_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 +172 -0
- package/src/client/websocket/handlers/RELATIONSHIP_ADD.js +17 -0
- package/src/client/websocket/handlers/RELATIONSHIP_REMOVE.js +15 -0
- package/src/client/websocket/handlers/RELATIONSHIP_UPDATE.js +18 -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 +12 -0
- package/src/client/websocket/handlers/USER_NOTE_UPDATE.js +5 -0
- package/src/client/websocket/handlers/USER_SETTINGS_UPDATE.js +9 -0
- package/src/client/websocket/handlers/USER_UPDATE.js +5 -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 +86 -0
- package/src/errors/DJSError.js +61 -0
- package/src/errors/Messages.js +227 -0
- package/src/errors/index.js +4 -0
- package/src/index.js +190 -0
- package/src/main.js +42 -0
- package/src/managers/ApplicationCommandManager.js +267 -0
- package/src/managers/ApplicationCommandPermissionsManager.js +425 -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 +139 -0
- package/src/managers/ClientUserSettingManager.js +490 -0
- package/src/managers/DataManager.js +61 -0
- package/src/managers/DeveloperPortalManager.js +104 -0
- package/src/managers/GuildApplicationCommandManager.js +28 -0
- package/src/managers/GuildBanManager.js +204 -0
- package/src/managers/GuildChannelManager.js +502 -0
- package/src/managers/GuildEmojiManager.js +171 -0
- package/src/managers/GuildEmojiRoleManager.js +118 -0
- package/src/managers/GuildFolderManager.js +24 -0
- package/src/managers/GuildForumThreadManager.js +114 -0
- package/src/managers/GuildInviteManager.js +213 -0
- package/src/managers/GuildManager.js +304 -0
- package/src/managers/GuildMemberManager.js +724 -0
- package/src/managers/GuildMemberRoleManager.js +191 -0
- package/src/managers/GuildScheduledEventManager.js +296 -0
- package/src/managers/GuildSettingManager.js +148 -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 +393 -0
- package/src/managers/PermissionOverwriteManager.js +166 -0
- package/src/managers/PresenceManager.js +58 -0
- package/src/managers/ReactionManager.js +67 -0
- package/src/managers/ReactionUserManager.js +71 -0
- package/src/managers/RelationshipManager.js +258 -0
- package/src/managers/RoleManager.js +352 -0
- package/src/managers/SessionManager.js +57 -0
- package/src/managers/StageInstanceManager.js +162 -0
- package/src/managers/ThreadManager.js +207 -0
- package/src/managers/ThreadMemberManager.js +186 -0
- package/src/managers/UserManager.js +150 -0
- package/src/managers/VoiceStateManager.js +37 -0
- package/src/rest/APIRequest.js +136 -0
- package/src/rest/APIRouter.js +53 -0
- package/src/rest/CaptchaSolver.js +78 -0
- package/src/rest/DiscordAPIError.js +103 -0
- package/src/rest/HTTPError.js +62 -0
- package/src/rest/RESTManager.js +81 -0
- package/src/rest/RateLimitError.js +55 -0
- package/src/rest/RequestHandler.js +446 -0
- package/src/sharding/Shard.js +443 -0
- package/src/sharding/ShardClientUtil.js +275 -0
- package/src/sharding/ShardingManager.js +318 -0
- package/src/structures/AnonymousGuild.js +98 -0
- package/src/structures/ApplicationCommand.js +1028 -0
- package/src/structures/ApplicationRoleConnectionMetadata.js +45 -0
- package/src/structures/AutoModerationActionExecution.js +89 -0
- package/src/structures/AutoModerationRule.js +294 -0
- package/src/structures/AutocompleteInteraction.js +106 -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 +193 -0
- package/src/structures/BaseGuildVoiceChannel.js +243 -0
- package/src/structures/BaseMessageComponent.js +114 -0
- package/src/structures/ButtonInteraction.js +11 -0
- package/src/structures/Call.js +58 -0
- package/src/structures/CategoryChannel.js +83 -0
- package/src/structures/Channel.js +271 -0
- package/src/structures/ClientApplication.js +204 -0
- package/src/structures/ClientPresence.js +84 -0
- package/src/structures/ClientUser.js +624 -0
- package/src/structures/CommandInteraction.js +41 -0
- package/src/structures/CommandInteractionOptionResolver.js +276 -0
- package/src/structures/ContextMenuInteraction.js +65 -0
- package/src/structures/DMChannel.js +280 -0
- package/src/structures/DeveloperPortalApplication.js +520 -0
- package/src/structures/DirectoryChannel.js +20 -0
- package/src/structures/Emoji.js +148 -0
- package/src/structures/ForumChannel.js +271 -0
- package/src/structures/Guild.js +1744 -0
- package/src/structures/GuildAuditLogs.js +734 -0
- package/src/structures/GuildBan.js +59 -0
- package/src/structures/GuildBoost.js +108 -0
- package/src/structures/GuildChannel.js +454 -0
- package/src/structures/GuildEmoji.js +161 -0
- package/src/structures/GuildFolder.js +75 -0
- package/src/structures/GuildMember.js +686 -0
- package/src/structures/GuildPreview.js +191 -0
- package/src/structures/GuildPreviewEmoji.js +27 -0
- package/src/structures/GuildScheduledEvent.js +441 -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 +351 -0
- package/src/structures/InteractionCollector.js +248 -0
- package/src/structures/InteractionResponse.js +114 -0
- package/src/structures/InteractionWebhook.js +43 -0
- package/src/structures/Invite.js +375 -0
- package/src/structures/InviteGuild.js +23 -0
- package/src/structures/InviteStageInstance.js +86 -0
- package/src/structures/Message.js +1188 -0
- package/src/structures/MessageActionRow.js +103 -0
- package/src/structures/MessageAttachment.js +193 -0
- package/src/structures/MessageButton.js +231 -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 +586 -0
- package/src/structures/MessageMentions.js +272 -0
- package/src/structures/MessagePayload.js +358 -0
- package/src/structures/MessageReaction.js +171 -0
- package/src/structures/MessageSelectMenu.js +391 -0
- package/src/structures/Modal.js +279 -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/PartialGroupDMChannel.js +430 -0
- package/src/structures/PermissionOverwrites.js +196 -0
- package/src/structures/Presence.js +441 -0
- package/src/structures/ReactionCollector.js +229 -0
- package/src/structures/ReactionEmoji.js +31 -0
- package/src/structures/RichPresence.js +722 -0
- package/src/structures/Role.js +515 -0
- package/src/structures/SelectMenuInteraction.js +170 -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 +167 -0
- package/src/structures/TeamMember.js +71 -0
- package/src/structures/TextChannel.js +33 -0
- package/src/structures/TextInputComponent.js +201 -0
- package/src/structures/ThreadChannel.js +626 -0
- package/src/structures/ThreadMember.js +105 -0
- package/src/structures/Typing.js +74 -0
- package/src/structures/User.js +697 -0
- package/src/structures/UserContextMenuInteraction.js +29 -0
- package/src/structures/VoiceChannel.js +110 -0
- package/src/structures/VoiceRegion.js +53 -0
- package/src/structures/VoiceState.js +306 -0
- package/src/structures/WebEmbed.js +401 -0
- package/src/structures/Webhook.js +461 -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 +190 -0
- package/src/structures/interfaces/Collector.js +300 -0
- package/src/structures/interfaces/InteractionResponses.js +313 -0
- package/src/structures/interfaces/TextBasedChannel.js +566 -0
- package/src/util/ActivityFlags.js +44 -0
- package/src/util/ApplicationFlags.js +74 -0
- package/src/util/BitField.js +170 -0
- package/src/util/ChannelFlags.js +45 -0
- package/src/util/Constants.js +1917 -0
- package/src/util/DataResolver.js +145 -0
- package/src/util/Formatters.js +214 -0
- package/src/util/GuildMemberFlags.js +43 -0
- package/src/util/Intents.js +74 -0
- package/src/util/LimitedCollection.js +131 -0
- package/src/util/MessageFlags.js +54 -0
- package/src/util/Options.js +360 -0
- package/src/util/Permissions.js +187 -0
- package/src/util/PremiumUsageFlags.js +31 -0
- package/src/util/PurchasedFlags.js +31 -0
- package/src/util/RemoteAuth.js +522 -0
- package/src/util/SnowflakeUtil.js +92 -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 +741 -0
- package/src/util/Voice.js +1456 -0
- package/src/util/arRPC/index.js +229 -0
- package/src/util/arRPC/process/detectable.json +1 -0
- package/src/util/arRPC/process/index.js +102 -0
- package/src/util/arRPC/process/native/index.js +5 -0
- package/src/util/arRPC/process/native/linux.js +37 -0
- package/src/util/arRPC/process/native/win32.js +25 -0
- package/src/util/arRPC/transports/ipc.js +281 -0
- package/src/util/arRPC/transports/websocket.js +128 -0
- package/typings/enums.d.ts +346 -0
- package/typings/index.d.ts +7725 -0
- package/typings/index.test-d.ts +0 -0
- package/typings/rawDataTypes.d.ts +283 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Represents a RateLimit error from a request.
|
5
|
+
* @extends Error
|
6
|
+
*/
|
7
|
+
class RateLimitError extends Error {
|
8
|
+
constructor({ timeout, limit, method, path, route, global }) {
|
9
|
+
super(`A ${global ? 'global ' : ''}rate limit was hit on route ${route}`);
|
10
|
+
|
11
|
+
/**
|
12
|
+
* The name of the error
|
13
|
+
* @type {string}
|
14
|
+
*/
|
15
|
+
this.name = 'RateLimitError';
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Time until this rate limit ends, in milliseconds
|
19
|
+
* @type {number}
|
20
|
+
*/
|
21
|
+
this.timeout = timeout;
|
22
|
+
|
23
|
+
/**
|
24
|
+
* The HTTP method used for the request
|
25
|
+
* @type {string}
|
26
|
+
*/
|
27
|
+
this.method = method;
|
28
|
+
|
29
|
+
/**
|
30
|
+
* The path of the request relative to the HTTP endpoint
|
31
|
+
* @type {string}
|
32
|
+
*/
|
33
|
+
this.path = path;
|
34
|
+
|
35
|
+
/**
|
36
|
+
* The route of the request relative to the HTTP endpoint
|
37
|
+
* @type {string}
|
38
|
+
*/
|
39
|
+
this.route = route;
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Whether this rate limit is global
|
43
|
+
* @type {boolean}
|
44
|
+
*/
|
45
|
+
this.global = global;
|
46
|
+
|
47
|
+
/**
|
48
|
+
* The maximum amount of requests of this endpoint
|
49
|
+
* @type {number}
|
50
|
+
*/
|
51
|
+
this.limit = limit;
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
module.exports = RateLimitError;
|
@@ -0,0 +1,446 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const { setTimeout } = require('node:timers');
|
4
|
+
const { setTimeout: sleep } = require('node:timers/promises');
|
5
|
+
const { inspect } = require('util');
|
6
|
+
const { AsyncQueue } = require('@sapphire/async-queue');
|
7
|
+
const parseCookie = require('set-cookie-parser');
|
8
|
+
const DiscordAPIError = require('./DiscordAPIError');
|
9
|
+
const HTTPError = require('./HTTPError');
|
10
|
+
const RateLimitError = require('./RateLimitError');
|
11
|
+
const {
|
12
|
+
Events: { DEBUG, RATE_LIMIT, INVALID_REQUEST_WARNING, API_RESPONSE, API_REQUEST, CAPTCHA_REQUIRED },
|
13
|
+
} = require('../util/Constants');
|
14
|
+
|
15
|
+
const captchaMessage = [
|
16
|
+
'incorrect-captcha',
|
17
|
+
'response-already-used',
|
18
|
+
'captcha-required',
|
19
|
+
'invalid-input-response',
|
20
|
+
'invalid-response',
|
21
|
+
'You need to update your app',
|
22
|
+
];
|
23
|
+
|
24
|
+
function parseResponse(res) {
|
25
|
+
if (res.headers.get('content-type')?.startsWith('application/json')) return res.json();
|
26
|
+
return res.arrayBuffer(); // Cre: TheDevYellowy
|
27
|
+
}
|
28
|
+
|
29
|
+
function getAPIOffset(serverDate) {
|
30
|
+
return new Date(serverDate).getTime() - Date.now();
|
31
|
+
}
|
32
|
+
|
33
|
+
function calculateReset(reset, resetAfter, serverDate) {
|
34
|
+
// Use direct reset time when available, server date becomes irrelevant in this case
|
35
|
+
if (resetAfter) {
|
36
|
+
return Date.now() + Number(resetAfter) * 1_000;
|
37
|
+
}
|
38
|
+
return new Date(Number(reset) * 1_000).getTime() - getAPIOffset(serverDate);
|
39
|
+
}
|
40
|
+
|
41
|
+
/* Invalid request limiting is done on a per-IP basis, not a per-token basis.
|
42
|
+
* The best we can do is track invalid counts process-wide (on the theory that
|
43
|
+
* users could have multiple bots run from one process) rather than per-bot.
|
44
|
+
* Therefore, store these at file scope here rather than in the client's
|
45
|
+
* RESTManager object.
|
46
|
+
*/
|
47
|
+
let invalidCount = 0;
|
48
|
+
let invalidCountResetTime = null;
|
49
|
+
|
50
|
+
class RequestHandler {
|
51
|
+
constructor(manager) {
|
52
|
+
this.manager = manager;
|
53
|
+
this.queue = new AsyncQueue();
|
54
|
+
this.reset = -1;
|
55
|
+
this.remaining = -1;
|
56
|
+
this.limit = -1;
|
57
|
+
}
|
58
|
+
|
59
|
+
async push(request) {
|
60
|
+
await this.queue.wait();
|
61
|
+
try {
|
62
|
+
return await this.execute(request);
|
63
|
+
} finally {
|
64
|
+
this.queue.shift();
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
get globalLimited() {
|
69
|
+
return this.manager.globalRemaining <= 0 && Date.now() < this.manager.globalReset;
|
70
|
+
}
|
71
|
+
|
72
|
+
get localLimited() {
|
73
|
+
return this.remaining <= 0 && Date.now() < this.reset;
|
74
|
+
}
|
75
|
+
|
76
|
+
get limited() {
|
77
|
+
return this.globalLimited || this.localLimited;
|
78
|
+
}
|
79
|
+
|
80
|
+
get _inactive() {
|
81
|
+
return this.queue.remaining === 0 && !this.limited;
|
82
|
+
}
|
83
|
+
|
84
|
+
globalDelayFor(ms) {
|
85
|
+
return new Promise(resolve => {
|
86
|
+
setTimeout(() => {
|
87
|
+
this.manager.globalDelay = null;
|
88
|
+
resolve();
|
89
|
+
}, ms).unref();
|
90
|
+
});
|
91
|
+
}
|
92
|
+
|
93
|
+
/*
|
94
|
+
* Determines whether the request should be queued or whether a RateLimitError should be thrown
|
95
|
+
*/
|
96
|
+
async onRateLimit(request, limit, timeout, isGlobal) {
|
97
|
+
const { options } = this.manager.client;
|
98
|
+
if (!options.rejectOnRateLimit) return;
|
99
|
+
|
100
|
+
const rateLimitData = {
|
101
|
+
timeout,
|
102
|
+
limit,
|
103
|
+
method: request.method,
|
104
|
+
path: request.path,
|
105
|
+
route: request.route,
|
106
|
+
global: isGlobal,
|
107
|
+
};
|
108
|
+
const shouldThrow =
|
109
|
+
typeof options.rejectOnRateLimit === 'function'
|
110
|
+
? await options.rejectOnRateLimit(rateLimitData)
|
111
|
+
: options.rejectOnRateLimit.some(route => rateLimitData.route.startsWith(route.toLowerCase()));
|
112
|
+
if (shouldThrow) {
|
113
|
+
throw new RateLimitError(rateLimitData);
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
async execute(request, captchaKey, captchaToken) {
|
118
|
+
/*
|
119
|
+
* After calculations have been done, pre-emptively stop further requests
|
120
|
+
* Potentially loop until this task can run if e.g. the global rate limit is hit twice
|
121
|
+
*/
|
122
|
+
while (this.limited) {
|
123
|
+
const isGlobal = this.globalLimited;
|
124
|
+
let limit, timeout, delayPromise;
|
125
|
+
|
126
|
+
if (isGlobal) {
|
127
|
+
// Set the variables based on the global rate limit
|
128
|
+
limit = this.manager.globalLimit;
|
129
|
+
timeout = this.manager.globalReset + this.manager.client.options.restTimeOffset - Date.now();
|
130
|
+
} else {
|
131
|
+
// Set the variables based on the route-specific rate limit
|
132
|
+
limit = this.limit;
|
133
|
+
timeout = this.reset + this.manager.client.options.restTimeOffset - Date.now();
|
134
|
+
}
|
135
|
+
|
136
|
+
if (this.manager.client.listenerCount(RATE_LIMIT)) {
|
137
|
+
/**
|
138
|
+
* Emitted when the client hits a rate limit while making a request
|
139
|
+
* @event BaseClient#rateLimit
|
140
|
+
* @param {RateLimitData} rateLimitData Object containing the rate limit info
|
141
|
+
*/
|
142
|
+
this.manager.client.emit(RATE_LIMIT, {
|
143
|
+
timeout,
|
144
|
+
limit,
|
145
|
+
method: request.method,
|
146
|
+
path: request.path,
|
147
|
+
route: request.route,
|
148
|
+
global: isGlobal,
|
149
|
+
});
|
150
|
+
}
|
151
|
+
|
152
|
+
if (isGlobal) {
|
153
|
+
// If this is the first task to reach the global timeout, set the global delay
|
154
|
+
if (!this.manager.globalDelay) {
|
155
|
+
// The global delay function should clear the global delay state when it is resolved
|
156
|
+
this.manager.globalDelay = this.globalDelayFor(timeout);
|
157
|
+
}
|
158
|
+
delayPromise = this.manager.globalDelay;
|
159
|
+
} else {
|
160
|
+
delayPromise = sleep(timeout);
|
161
|
+
}
|
162
|
+
|
163
|
+
// Determine whether a RateLimitError should be thrown
|
164
|
+
await this.onRateLimit(request, limit, timeout, isGlobal); // eslint-disable-line no-await-in-loop
|
165
|
+
|
166
|
+
// Wait for the timeout to expire in order to avoid an actual 429
|
167
|
+
await delayPromise; // eslint-disable-line no-await-in-loop
|
168
|
+
}
|
169
|
+
|
170
|
+
// As the request goes out, update the global usage information
|
171
|
+
if (!this.manager.globalReset || this.manager.globalReset < Date.now()) {
|
172
|
+
this.manager.globalReset = Date.now() + 1_000;
|
173
|
+
this.manager.globalRemaining = this.manager.globalLimit;
|
174
|
+
}
|
175
|
+
this.manager.globalRemaining--;
|
176
|
+
|
177
|
+
/**
|
178
|
+
* Represents a request that will or has been made to the Discord API
|
179
|
+
* @typedef {Object} APIRequest
|
180
|
+
* @property {HTTPMethod} method The HTTP method used in this request
|
181
|
+
* @property {string} path The full path used to make the request
|
182
|
+
* @property {string} route The API route identifying the rate limit for this request
|
183
|
+
* @property {Object} options Additional options for this request
|
184
|
+
* @property {number} retries The number of times this request has been attempted
|
185
|
+
*/
|
186
|
+
|
187
|
+
if (this.manager.client.listenerCount(API_REQUEST)) {
|
188
|
+
/**
|
189
|
+
* Emitted before every API request.
|
190
|
+
* This event can emit several times for the same request, e.g. when hitting a rate limit.
|
191
|
+
* <info>This is an informational event that is emitted quite frequently,
|
192
|
+
* it is highly recommended to check `request.path` to filter the data.</info>
|
193
|
+
* @event BaseClient#apiRequest
|
194
|
+
* @param {APIRequest} request The request that is about to be sent
|
195
|
+
*/
|
196
|
+
this.manager.client.emit(API_REQUEST, {
|
197
|
+
method: request.method,
|
198
|
+
path: request.path,
|
199
|
+
route: request.route,
|
200
|
+
options: request.options,
|
201
|
+
retries: request.retries,
|
202
|
+
});
|
203
|
+
}
|
204
|
+
|
205
|
+
// Perform the request
|
206
|
+
let res;
|
207
|
+
try {
|
208
|
+
res = await request.make(captchaKey, captchaToken);
|
209
|
+
} catch (error) {
|
210
|
+
// Retry the specified number of times for request abortions
|
211
|
+
if (request.retries === this.manager.client.options.retryLimit) {
|
212
|
+
throw new HTTPError(error.message, error.constructor.name, error.status, request);
|
213
|
+
}
|
214
|
+
|
215
|
+
request.retries++;
|
216
|
+
return this.execute(request);
|
217
|
+
}
|
218
|
+
|
219
|
+
if (this.manager.client.listenerCount(API_RESPONSE)) {
|
220
|
+
/**
|
221
|
+
* Emitted after every API request has received a response.
|
222
|
+
* This event does not necessarily correlate to completion of the request, e.g. when hitting a rate limit.
|
223
|
+
* <info>This is an informational event that is emitted quite frequently,
|
224
|
+
* it is highly recommended to check `request.path` to filter the data.</info>
|
225
|
+
* @event BaseClient#apiResponse
|
226
|
+
* @param {APIRequest} request The request that triggered this response
|
227
|
+
* @param {Response} response The response received from the Discord API
|
228
|
+
*/
|
229
|
+
this.manager.client.emit(
|
230
|
+
API_RESPONSE,
|
231
|
+
{
|
232
|
+
method: request.method,
|
233
|
+
path: request.path,
|
234
|
+
route: request.route,
|
235
|
+
options: request.options,
|
236
|
+
retries: request.retries,
|
237
|
+
},
|
238
|
+
res.clone(),
|
239
|
+
);
|
240
|
+
}
|
241
|
+
|
242
|
+
let sublimitTimeout;
|
243
|
+
if (res.headers) {
|
244
|
+
const cookie = res.headers.raw()['set-cookie'];
|
245
|
+
if (cookie && Array.isArray(cookie)) {
|
246
|
+
const oldCookie = parseCookie((this.manager.client.options.http.headers.Cookie || '').split('; '), {
|
247
|
+
map: true,
|
248
|
+
});
|
249
|
+
const parse = parseCookie(cookie, {
|
250
|
+
map: true,
|
251
|
+
});
|
252
|
+
for (const key in parse) {
|
253
|
+
oldCookie[key] = parse[key];
|
254
|
+
}
|
255
|
+
this.manager.client.options.http.headers.Cookie = Object.entries(oldCookie)
|
256
|
+
.map(([key, value]) => `${key}=${value.value}`)
|
257
|
+
.join('; ');
|
258
|
+
this.manager.client.emit('debug', `[REST] Set new cookie: ${this.manager.client.options.http.headers.Cookie}`);
|
259
|
+
}
|
260
|
+
const serverDate = res.headers.get('date');
|
261
|
+
const limit = res.headers.get('x-ratelimit-limit');
|
262
|
+
const remaining = res.headers.get('x-ratelimit-remaining');
|
263
|
+
const reset = res.headers.get('x-ratelimit-reset');
|
264
|
+
const resetAfter = res.headers.get('x-ratelimit-reset-after');
|
265
|
+
this.limit = limit ? Number(limit) : Infinity;
|
266
|
+
this.remaining = remaining ? Number(remaining) : 1;
|
267
|
+
|
268
|
+
this.reset = reset || resetAfter ? calculateReset(reset, resetAfter, serverDate) : Date.now();
|
269
|
+
|
270
|
+
// https://github.com/discord/discord-api-docs/issues/182
|
271
|
+
if (!resetAfter && request.route.includes('reactions')) {
|
272
|
+
this.reset = new Date(serverDate).getTime() - getAPIOffset(serverDate) + 250;
|
273
|
+
}
|
274
|
+
|
275
|
+
// Handle retryAfter, which means we have actually hit a rate limit
|
276
|
+
let retryAfter = res.headers.get('retry-after');
|
277
|
+
retryAfter = retryAfter ? Number(retryAfter) * 1_000 : -1;
|
278
|
+
if (retryAfter > 0) {
|
279
|
+
// If the global rate limit header is set, that means we hit the global rate limit
|
280
|
+
if (res.headers.get('x-ratelimit-global')) {
|
281
|
+
this.manager.globalRemaining = 0;
|
282
|
+
this.manager.globalReset = Date.now() + retryAfter;
|
283
|
+
} else if (!this.localLimited) {
|
284
|
+
/*
|
285
|
+
* This is a sublimit (e.g. 2 channel name changes/10 minutes) since the headers don't indicate a
|
286
|
+
* route-wide rate limit. Don't update remaining or reset to avoid rate limiting the whole
|
287
|
+
* endpoint, just set a reset time on the request itself to avoid retrying too soon.
|
288
|
+
*/
|
289
|
+
sublimitTimeout = retryAfter;
|
290
|
+
}
|
291
|
+
}
|
292
|
+
}
|
293
|
+
|
294
|
+
// Count the invalid requests
|
295
|
+
if (res.status === 401 || res.status === 403 || res.status === 429) {
|
296
|
+
if (!invalidCountResetTime || invalidCountResetTime < Date.now()) {
|
297
|
+
invalidCountResetTime = Date.now() + 1_000 * 60 * 10;
|
298
|
+
invalidCount = 0;
|
299
|
+
}
|
300
|
+
invalidCount++;
|
301
|
+
|
302
|
+
const emitInvalid =
|
303
|
+
this.manager.client.listenerCount(INVALID_REQUEST_WARNING) &&
|
304
|
+
this.manager.client.options.invalidRequestWarningInterval > 0 &&
|
305
|
+
invalidCount % this.manager.client.options.invalidRequestWarningInterval === 0;
|
306
|
+
if (emitInvalid) {
|
307
|
+
/**
|
308
|
+
* @typedef {Object} InvalidRequestWarningData
|
309
|
+
* @property {number} count Number of invalid requests that have been made in the window
|
310
|
+
* @property {number} remainingTime Time in milliseconds remaining before the count resets
|
311
|
+
*/
|
312
|
+
|
313
|
+
/**
|
314
|
+
* Emitted periodically when the process sends invalid requests to let users avoid the
|
315
|
+
* 10k invalid requests in 10 minutes threshold that causes a ban
|
316
|
+
* @event BaseClient#invalidRequestWarning
|
317
|
+
* @param {InvalidRequestWarningData} invalidRequestWarningData Object containing the invalid request info
|
318
|
+
*/
|
319
|
+
this.manager.client.emit(INVALID_REQUEST_WARNING, {
|
320
|
+
count: invalidCount,
|
321
|
+
remainingTime: invalidCountResetTime - Date.now(),
|
322
|
+
});
|
323
|
+
}
|
324
|
+
}
|
325
|
+
|
326
|
+
// Handle 2xx and 3xx responses
|
327
|
+
if (res.ok) {
|
328
|
+
// Nothing wrong with the request, proceed with the next one
|
329
|
+
return parseResponse(res);
|
330
|
+
}
|
331
|
+
|
332
|
+
// Handle 4xx responses
|
333
|
+
if (res.status >= 400 && res.status < 500) {
|
334
|
+
// Handle ratelimited requests
|
335
|
+
if (res.status === 429) {
|
336
|
+
const isGlobal = this.globalLimited;
|
337
|
+
let limit, timeout;
|
338
|
+
if (isGlobal) {
|
339
|
+
// Set the variables based on the global rate limit
|
340
|
+
limit = this.manager.globalLimit;
|
341
|
+
timeout = this.manager.globalReset + this.manager.client.options.restTimeOffset - Date.now();
|
342
|
+
} else {
|
343
|
+
// Set the variables based on the route-specific rate limit
|
344
|
+
limit = this.limit;
|
345
|
+
timeout = this.reset + this.manager.client.options.restTimeOffset - Date.now();
|
346
|
+
}
|
347
|
+
|
348
|
+
this.manager.client.emit(
|
349
|
+
DEBUG,
|
350
|
+
`Hit a 429 while executing a request.
|
351
|
+
Global : ${isGlobal}
|
352
|
+
Method : ${request.method}
|
353
|
+
Path : ${request.path}
|
354
|
+
Route : ${request.route}
|
355
|
+
Limit : ${limit}
|
356
|
+
Timeout : ${timeout}ms
|
357
|
+
Sublimit: ${sublimitTimeout ? `${sublimitTimeout}ms` : 'None'}`,
|
358
|
+
);
|
359
|
+
|
360
|
+
await this.onRateLimit(request, limit, timeout, isGlobal);
|
361
|
+
|
362
|
+
// If caused by a sublimit, wait it out here so other requests on the route can be handled
|
363
|
+
if (sublimitTimeout) {
|
364
|
+
await sleep(sublimitTimeout);
|
365
|
+
}
|
366
|
+
return this.execute(request);
|
367
|
+
}
|
368
|
+
|
369
|
+
// Handle possible malformed requests
|
370
|
+
let data;
|
371
|
+
try {
|
372
|
+
data = await parseResponse(res);
|
373
|
+
if (data?.captcha_service) {
|
374
|
+
/**
|
375
|
+
* Emitted when a request is blocked by a captcha
|
376
|
+
* @event Client#captchaRequired
|
377
|
+
* @param {Request} request The request that was blocked
|
378
|
+
* @param {Captcha} data The data returned by Discord
|
379
|
+
*/
|
380
|
+
this.manager.client.emit(CAPTCHA_REQUIRED, request, data);
|
381
|
+
}
|
382
|
+
if (
|
383
|
+
data?.captcha_service &&
|
384
|
+
this.manager.client.options.captchaService &&
|
385
|
+
request.retries < this.manager.client.options.captchaRetryLimit &&
|
386
|
+
captchaMessage.some(s => data.captcha_key[0].includes(s))
|
387
|
+
) {
|
388
|
+
// Retry the request after a captcha is solved
|
389
|
+
this.manager.client.emit(
|
390
|
+
DEBUG,
|
391
|
+
`Hit a captcha while executing a request. Solving captcha ...
|
392
|
+
Method : ${request.method}
|
393
|
+
Path : ${request.path}
|
394
|
+
Route : ${request.route}
|
395
|
+
Info : ${inspect(data, { depth: null })}`,
|
396
|
+
);
|
397
|
+
const captcha = await this.manager.captchaService.solve(
|
398
|
+
data,
|
399
|
+
this.manager.client.options.http.headers['User-Agent'],
|
400
|
+
);
|
401
|
+
// Sleep: await this.manager.client.sleep(5_000);
|
402
|
+
this.manager.client.emit(
|
403
|
+
DEBUG,
|
404
|
+
`Captcha details:
|
405
|
+
Method : ${request.method}
|
406
|
+
Path : ${request.path}
|
407
|
+
Route : ${request.route}
|
408
|
+
Key : ${captcha ? `${captcha.slice(0, 30)}...` : '[Captcha not solved]'}
|
409
|
+
rqToken : ${data.captcha_rqtoken}`,
|
410
|
+
);
|
411
|
+
request.retries++;
|
412
|
+
return this.execute(request, captcha, data.captcha_rqtoken);
|
413
|
+
}
|
414
|
+
} catch (err) {
|
415
|
+
throw new HTTPError(err.message, err.constructor.name, err.status, request);
|
416
|
+
}
|
417
|
+
throw new DiscordAPIError(data, res.status, request);
|
418
|
+
}
|
419
|
+
|
420
|
+
// Handle 5xx responses
|
421
|
+
if (res.status >= 500 && res.status < 600) {
|
422
|
+
// Retry the specified number of times for possible serverside issues
|
423
|
+
if (request.retries === this.manager.client.options.retryLimit) {
|
424
|
+
throw new HTTPError(res.statusText, res.constructor.name, res.status, request);
|
425
|
+
}
|
426
|
+
|
427
|
+
request.retries++;
|
428
|
+
return this.execute(request);
|
429
|
+
}
|
430
|
+
|
431
|
+
// Fallback in the rare case a status code outside the range 200..=599 is returned
|
432
|
+
return null;
|
433
|
+
}
|
434
|
+
}
|
435
|
+
|
436
|
+
module.exports = RequestHandler;
|
437
|
+
|
438
|
+
/**
|
439
|
+
* @external HTTPMethod
|
440
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods}
|
441
|
+
*/
|
442
|
+
|
443
|
+
/**
|
444
|
+
* @external Response
|
445
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Response}
|
446
|
+
*/
|