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,522 @@
|
|
1
|
+
'use strict';
|
2
|
+
const { Buffer } = require('buffer');
|
3
|
+
const crypto = require('crypto');
|
4
|
+
const EventEmitter = require('node:events');
|
5
|
+
const { setTimeout } = require('node:timers');
|
6
|
+
const { StringDecoder } = require('string_decoder');
|
7
|
+
const axios = require('axios');
|
8
|
+
const chalk = require('chalk');
|
9
|
+
const { encode: urlsafe_b64encode } = require('safe-base64');
|
10
|
+
const WebSocket = require('ws');
|
11
|
+
const { defaultUA } = require('./Constants');
|
12
|
+
const Options = require('./Options');
|
13
|
+
|
14
|
+
const defaultClientOptions = Options.createDefault();
|
15
|
+
|
16
|
+
const baseURL = 'https://discord.com/ra/';
|
17
|
+
|
18
|
+
const wsURL = 'wss://remote-auth-gateway.discord.gg/?v=2';
|
19
|
+
|
20
|
+
const receiveEvent = {
|
21
|
+
HELLO: 'hello',
|
22
|
+
NONCE_PROOF: 'nonce_proof',
|
23
|
+
PENDING_REMOTE_INIT: 'pending_remote_init',
|
24
|
+
HEARTBEAT_ACK: 'heartbeat_ack',
|
25
|
+
PENDING_LOGIN: 'pending_ticket',
|
26
|
+
CANCEL: 'cancel',
|
27
|
+
SUCCESS: 'pending_login',
|
28
|
+
};
|
29
|
+
|
30
|
+
const sendEvent = {
|
31
|
+
INIT: 'init',
|
32
|
+
NONCE_PROOF: 'nonce_proof',
|
33
|
+
HEARTBEAT: 'heartbeat',
|
34
|
+
};
|
35
|
+
|
36
|
+
const Event = {
|
37
|
+
READY: 'ready',
|
38
|
+
ERROR: 'error',
|
39
|
+
CANCEL: 'cancel',
|
40
|
+
WAIT: 'pending',
|
41
|
+
SUCCESS: 'success',
|
42
|
+
FINISH: 'finish',
|
43
|
+
CLOSED: 'closed',
|
44
|
+
};
|
45
|
+
|
46
|
+
/**
|
47
|
+
* @typedef {Object} DiscordAuthWebsocketOptions
|
48
|
+
* @property {?boolean} [debug=false] Log debug info
|
49
|
+
* @property {?boolean} [hiddenLog=false] Hide log ?
|
50
|
+
* @property {?boolean} [autoLogin=false] Automatically login (DiscordJS.Client Login) ?
|
51
|
+
* @property {?boolean} [failIfError=true] Throw error ?
|
52
|
+
* @property {?boolean} [generateQR=true] Create QR Code ?
|
53
|
+
* @property {?number} [apiVersion=9] API Version
|
54
|
+
* @property {?string} [userAgent] User Agent
|
55
|
+
* @property {?Object.<string,string>} [wsProperties] Web Socket Properties
|
56
|
+
*/
|
57
|
+
|
58
|
+
/**
|
59
|
+
* Discord Auth QR (Discord.RemoteAuth will be removed in the future, v13.9.0 release)
|
60
|
+
* @extends {EventEmitter}
|
61
|
+
* @abstract
|
62
|
+
*/
|
63
|
+
class DiscordAuthWebsocket extends EventEmitter {
|
64
|
+
/**
|
65
|
+
* Creates a new DiscordAuthWebsocket instance.
|
66
|
+
* @param {?DiscordAuthWebsocketOptions} options Options
|
67
|
+
*/
|
68
|
+
constructor(options) {
|
69
|
+
super();
|
70
|
+
/**
|
71
|
+
* WebSocket
|
72
|
+
* @type {?WebSocket}
|
73
|
+
*/
|
74
|
+
this.ws = null;
|
75
|
+
/**
|
76
|
+
* Heartbeat Interval
|
77
|
+
* @type {?number}
|
78
|
+
*/
|
79
|
+
this.heartbeatInterval = NaN;
|
80
|
+
this._expire = NaN;
|
81
|
+
this.key = null;
|
82
|
+
/**
|
83
|
+
* User (Scan QR Code)
|
84
|
+
* @type {?Object}
|
85
|
+
*/
|
86
|
+
this.user = null;
|
87
|
+
/**
|
88
|
+
* Temporary Token (Scan QR Code)
|
89
|
+
* @type {?string}
|
90
|
+
*/
|
91
|
+
this.token = undefined;
|
92
|
+
/**
|
93
|
+
* Real Token (Login)
|
94
|
+
* @type {?string}
|
95
|
+
*/
|
96
|
+
this.realToken = undefined;
|
97
|
+
/**
|
98
|
+
* Fingerprint (QR Code)
|
99
|
+
* @type {?string}
|
100
|
+
*/
|
101
|
+
this.fingerprint = null;
|
102
|
+
|
103
|
+
/**
|
104
|
+
* Captcha Handler
|
105
|
+
* @type {Function}
|
106
|
+
* @param {Captcha} data hcaptcha data
|
107
|
+
* @returns {Promise<string>} Captcha token
|
108
|
+
*/
|
109
|
+
// eslint-disable-next-line no-unused-vars
|
110
|
+
this.captchaSolver = data =>
|
111
|
+
new Promise((resolve, reject) => {
|
112
|
+
reject(
|
113
|
+
new Error(`
|
114
|
+
Captcha Handler not found - Please set captchaSolver option
|
115
|
+
Example captchaSolver function:
|
116
|
+
|
117
|
+
new DiscordAuthWebsocket({
|
118
|
+
captchaSolver: async (data) => {
|
119
|
+
const token = await hcaptchaSolver(data.captcha_sitekey, 'discord.com');
|
120
|
+
return token;
|
121
|
+
}
|
122
|
+
});
|
123
|
+
|
124
|
+
`),
|
125
|
+
);
|
126
|
+
});
|
127
|
+
|
128
|
+
/**
|
129
|
+
* Captcha Cache
|
130
|
+
* @type {?Captcha}
|
131
|
+
*/
|
132
|
+
this.captchaCache = null;
|
133
|
+
|
134
|
+
this._validateOptions(options);
|
135
|
+
|
136
|
+
this.callFindRealTokenCount = 0;
|
137
|
+
}
|
138
|
+
/**
|
139
|
+
* Get expire time
|
140
|
+
* @type {string} Expire time
|
141
|
+
* @readonly
|
142
|
+
*/
|
143
|
+
get exprireTime() {
|
144
|
+
return this._expire.toLocaleString('en-US');
|
145
|
+
}
|
146
|
+
_validateOptions(options = {}) {
|
147
|
+
/**
|
148
|
+
* Options
|
149
|
+
* @type {?DiscordAuthWebsocketOptions}
|
150
|
+
*/
|
151
|
+
this.options = {
|
152
|
+
debug: false,
|
153
|
+
hiddenLog: false,
|
154
|
+
autoLogin: false,
|
155
|
+
failIfError: true,
|
156
|
+
generateQR: true,
|
157
|
+
apiVersion: 9,
|
158
|
+
userAgent: defaultUA,
|
159
|
+
wsProperties: defaultClientOptions.ws.properties,
|
160
|
+
captchaSolver: () => new Error('Captcha Handler not found. Please set captchaSolver option.'),
|
161
|
+
};
|
162
|
+
if (typeof options == 'object') {
|
163
|
+
if (typeof options.debug == 'boolean') this.options.debug = options.debug;
|
164
|
+
if (typeof options.hiddenLog == 'boolean') this.options.hiddenLog = options.hiddenLog;
|
165
|
+
if (typeof options.autoLogin == 'boolean') this.options.autoLogin = options.autoLogin;
|
166
|
+
if (typeof options.failIfError == 'boolean') this.options.failIfError = options.failIfError;
|
167
|
+
if (typeof options.generateQR == 'boolean') this.options.generateQR = options.generateQR;
|
168
|
+
if (typeof options.apiVersion == 'number') this.options.apiVersion = options.apiVersion;
|
169
|
+
if (typeof options.userAgent == 'string') this.options.userAgent = options.userAgent;
|
170
|
+
if (typeof options.wsProperties == 'object') this.options.wsProperties = options.wsProperties;
|
171
|
+
if (typeof options.captchaSolver == 'function') this.captchaSolver = options.captchaSolver;
|
172
|
+
}
|
173
|
+
}
|
174
|
+
_createWebSocket(url) {
|
175
|
+
this.ws = new WebSocket(url, {
|
176
|
+
headers: {
|
177
|
+
Origin: 'https://discord.com',
|
178
|
+
'User-Agent': this.options.userAgent,
|
179
|
+
},
|
180
|
+
});
|
181
|
+
this._handleWebSocket();
|
182
|
+
}
|
183
|
+
_handleWebSocket() {
|
184
|
+
this.ws.on('error', error => {
|
185
|
+
this._logger('error', error);
|
186
|
+
});
|
187
|
+
this.ws.on('open', () => {
|
188
|
+
this._logger('debug', 'Client Connected');
|
189
|
+
});
|
190
|
+
this.ws.on('close', () => {
|
191
|
+
this._logger('debug', 'Connection closed.');
|
192
|
+
});
|
193
|
+
this.ws.on('message', message => {
|
194
|
+
this._handleMessage(JSON.parse(message));
|
195
|
+
});
|
196
|
+
}
|
197
|
+
_handleMessage(message) {
|
198
|
+
switch (message.op) {
|
199
|
+
case receiveEvent.HELLO: {
|
200
|
+
this._ready(message);
|
201
|
+
break;
|
202
|
+
}
|
203
|
+
case receiveEvent.NONCE_PROOF: {
|
204
|
+
this._receiveNonceProof(message);
|
205
|
+
break;
|
206
|
+
}
|
207
|
+
case receiveEvent.PENDING_REMOTE_INIT: {
|
208
|
+
this._pendingRemoteInit(message);
|
209
|
+
break;
|
210
|
+
}
|
211
|
+
case receiveEvent.HEARTBEAT_ACK: {
|
212
|
+
this._logger('debug', 'Heartbeat acknowledged.');
|
213
|
+
this._heartbeatAck();
|
214
|
+
break;
|
215
|
+
}
|
216
|
+
case receiveEvent.PENDING_LOGIN: {
|
217
|
+
this._pendingLogin(message);
|
218
|
+
break;
|
219
|
+
}
|
220
|
+
case receiveEvent.CANCEL: {
|
221
|
+
this._logger('debug', 'Cancel login.');
|
222
|
+
/**
|
223
|
+
* Emitted whenever a user cancels the login process.
|
224
|
+
* @event DiscordAuthWebsocket#cancel
|
225
|
+
* @param {object} user User (Raw)
|
226
|
+
*/
|
227
|
+
this.emit(Event.CANCEL, this.user);
|
228
|
+
this.destroy();
|
229
|
+
break;
|
230
|
+
}
|
231
|
+
case receiveEvent.SUCCESS: {
|
232
|
+
this._logger('debug', 'Receive Token - Login Success.', message.ticket);
|
233
|
+
/**
|
234
|
+
* Emitted whenever a token is created. (Fake token)
|
235
|
+
* @event DiscordAuthWebsocket#success
|
236
|
+
* @param {object} user Discord User
|
237
|
+
* @param {string} token Discord Token (Fake)
|
238
|
+
*/
|
239
|
+
this.emit(Event.SUCCESS, this.user, message.ticket);
|
240
|
+
this.token = message.ticket;
|
241
|
+
this._findRealToken();
|
242
|
+
this._logger('default', 'Get token success.');
|
243
|
+
break;
|
244
|
+
}
|
245
|
+
default: {
|
246
|
+
this._logger('debug', `Unknown op: ${message.op}`, message);
|
247
|
+
}
|
248
|
+
}
|
249
|
+
}
|
250
|
+
_logger(type = 'default', ...message) {
|
251
|
+
if (this.options.hiddenLog) return;
|
252
|
+
switch (type.toLowerCase()) {
|
253
|
+
case 'error': {
|
254
|
+
// eslint-disable-next-line no-unused-expressions
|
255
|
+
this.options.failIfError
|
256
|
+
? this._throwError(new Error(message[0]))
|
257
|
+
: console.error(chalk.red(`[DiscordRemoteAuth] ERROR`), ...message);
|
258
|
+
break;
|
259
|
+
}
|
260
|
+
case 'default': {
|
261
|
+
console.log(chalk.green(`[DiscordRemoteAuth]`), ...message);
|
262
|
+
break;
|
263
|
+
}
|
264
|
+
case 'debug': {
|
265
|
+
if (this.options.debug) console.log(chalk.yellow(`[DiscordRemoteAuth] DEBUG`), ...message);
|
266
|
+
break;
|
267
|
+
}
|
268
|
+
}
|
269
|
+
}
|
270
|
+
_throwError(error) {
|
271
|
+
if (error.request) {
|
272
|
+
// Axios error
|
273
|
+
console.log(chalk.red(`[DiscordRemoteAuth] ERROR`), error.message, error.response);
|
274
|
+
throw new Error(`Request failed with status code ${error.response.status}`);
|
275
|
+
} else {
|
276
|
+
throw error;
|
277
|
+
}
|
278
|
+
}
|
279
|
+
_send(op, data) {
|
280
|
+
if (!this.ws) this._throwError(new Error('WebSocket is not connected.'));
|
281
|
+
let payload = { op: op };
|
282
|
+
if (data !== null) payload = { ...payload, ...data };
|
283
|
+
this._logger('debug', `Send Data:`, payload);
|
284
|
+
this.ws.send(JSON.stringify(payload));
|
285
|
+
}
|
286
|
+
_heartbeat() {
|
287
|
+
this._send(sendEvent.HEARTBEAT);
|
288
|
+
}
|
289
|
+
_heartbeatAck() {
|
290
|
+
setTimeout(() => {
|
291
|
+
this._heartbeat();
|
292
|
+
}, this.heartbeatInterval).unref();
|
293
|
+
}
|
294
|
+
_ready(data) {
|
295
|
+
this._logger('debug', 'Attempting server handshake...');
|
296
|
+
this._expire = new Date(Date.now() + data.timeout_ms);
|
297
|
+
this.heartbeatInterval = data.heartbeat_interval;
|
298
|
+
this._createKey();
|
299
|
+
this._heartbeatAck();
|
300
|
+
this._init();
|
301
|
+
}
|
302
|
+
_createKey() {
|
303
|
+
if (this.key) this._throwError(new Error('Key is already created.'));
|
304
|
+
this.key = crypto.generateKeyPairSync('rsa', {
|
305
|
+
modulusLength: 2048,
|
306
|
+
publicKeyEncoding: {
|
307
|
+
type: 'spki',
|
308
|
+
format: 'pem',
|
309
|
+
},
|
310
|
+
privateKeyEncoding: {
|
311
|
+
type: 'pkcs1',
|
312
|
+
format: 'pem',
|
313
|
+
},
|
314
|
+
});
|
315
|
+
}
|
316
|
+
_createPublicKey() {
|
317
|
+
if (!this.key) this._throwError(new Error('Key is not created.'));
|
318
|
+
this._logger('debug', 'Generating public key...');
|
319
|
+
const decoder = new StringDecoder('utf-8');
|
320
|
+
let pub_key = decoder.write(this.key.publicKey);
|
321
|
+
pub_key = pub_key.split('\n').slice(1, -2).join('');
|
322
|
+
this._logger('debug', 'Public key generated.', pub_key);
|
323
|
+
return pub_key;
|
324
|
+
}
|
325
|
+
_init() {
|
326
|
+
const public_key = this._createPublicKey();
|
327
|
+
this._send(sendEvent.INIT, { encoded_public_key: public_key });
|
328
|
+
}
|
329
|
+
_receiveNonceProof(data) {
|
330
|
+
const nonce = data.encrypted_nonce;
|
331
|
+
const decrypted_nonce = this._decryptPayload(nonce);
|
332
|
+
let proof = crypto.createHash('sha256').update(decrypted_nonce).digest();
|
333
|
+
proof = urlsafe_b64encode(proof);
|
334
|
+
proof = proof.replace(/\s+$/, '');
|
335
|
+
this._send(sendEvent.NONCE_PROOF, { proof: proof });
|
336
|
+
this._logger('debug', `Nonce proof decrypted:`, proof);
|
337
|
+
}
|
338
|
+
_decryptPayload(encrypted_payload) {
|
339
|
+
if (!this.key) this._throwError(new Error('Key is not created.'));
|
340
|
+
const payload = Buffer.from(encrypted_payload, 'base64');
|
341
|
+
this._logger('debug', `Encrypted Payload (Buffer):`, payload);
|
342
|
+
const decoder = new StringDecoder('utf-8');
|
343
|
+
const private_key = decoder.write(this.key.privateKey);
|
344
|
+
const data = crypto.privateDecrypt(
|
345
|
+
{
|
346
|
+
key: private_key,
|
347
|
+
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
|
348
|
+
oaepHash: 'sha256',
|
349
|
+
},
|
350
|
+
payload,
|
351
|
+
);
|
352
|
+
this._logger('debug', `Decrypted Payload:`, data.toString());
|
353
|
+
return data;
|
354
|
+
}
|
355
|
+
_pendingLogin(data) {
|
356
|
+
const user_data = this._decryptPayload(data.encrypted_user_payload);
|
357
|
+
const user = new User(user_data.toString());
|
358
|
+
this.user = user;
|
359
|
+
/**
|
360
|
+
* Emitted whenever a user is scan QR Code.
|
361
|
+
* @event DiscordAuthWebsocket#pending
|
362
|
+
* @param {object} user Discord User Raw
|
363
|
+
*/
|
364
|
+
this.emit(Event.WAIT, user);
|
365
|
+
this._logger('debug', 'Waiting for user to finish login...');
|
366
|
+
this.user.prettyPrint(this);
|
367
|
+
this._logger('default', 'Please check your phone again to confirm login.');
|
368
|
+
}
|
369
|
+
_pendingRemoteInit(data) {
|
370
|
+
this._logger('debug', `Pending Remote Init:`, data);
|
371
|
+
/**
|
372
|
+
* Emitted whenever a url is created.
|
373
|
+
* @event DiscordAuthWebsocket#ready
|
374
|
+
* @param {string} fingerprint Fingerprint
|
375
|
+
* @param {string} url DiscordAuthWebsocket
|
376
|
+
*/
|
377
|
+
this.emit(Event.READY, data.fingerprint, `${baseURL}${data.fingerprint}`);
|
378
|
+
this.fingerprint = data.fingerprint;
|
379
|
+
if (this.options.generateQR) this.generateQR();
|
380
|
+
}
|
381
|
+
_awaitLogin(client) {
|
382
|
+
this.once(Event.FINISH, (user, token) => {
|
383
|
+
this._logger('debug', 'Create login state...', user, token);
|
384
|
+
client.login(token);
|
385
|
+
});
|
386
|
+
}
|
387
|
+
/**
|
388
|
+
* Connect to DiscordAuthWebsocket.
|
389
|
+
* @param {?Client} client Using only for auto login.
|
390
|
+
* @returns {undefined}
|
391
|
+
*/
|
392
|
+
connect(client) {
|
393
|
+
this._createWebSocket(wsURL);
|
394
|
+
if (client && this.options.autoLogin) this._awaitLogin(client);
|
395
|
+
}
|
396
|
+
/**
|
397
|
+
* Disconnect from DiscordAuthWebsocket.
|
398
|
+
* @returns {undefined}
|
399
|
+
*/
|
400
|
+
destroy() {
|
401
|
+
if (!this.ws) this._throwError(new Error('WebSocket is not connected.'));
|
402
|
+
this.ws.close();
|
403
|
+
/**
|
404
|
+
* Emitted whenever a connection is closed.
|
405
|
+
* @event DiscordAuthWebsocket#closed
|
406
|
+
* @param {boolean} loginState Login state
|
407
|
+
*/
|
408
|
+
this.emit(Event.CLOSED, this.token);
|
409
|
+
this._logger('debug', 'WebSocket closed.');
|
410
|
+
}
|
411
|
+
/**
|
412
|
+
* Generate QR code for user to scan (Terminal)
|
413
|
+
* @returns {undefined}
|
414
|
+
*/
|
415
|
+
generateQR() {
|
416
|
+
if (!this.fingerprint) this._throwError(new Error('Fingerprint is not created.'));
|
417
|
+
require('@aikochan2k6/qrcode-terminal').generate(`${baseURL}${this.fingerprint}`, {
|
418
|
+
small: true,
|
419
|
+
});
|
420
|
+
this._logger('default', `Please scan the QR code to continue.\nQR Code will expire in ${this.exprireTime}`);
|
421
|
+
}
|
422
|
+
|
423
|
+
async _findRealToken(captchaSolveData) {
|
424
|
+
this.callFindRealTokenCount++;
|
425
|
+
if (!this.token) return this._throwError(new Error('Token is not created.'));
|
426
|
+
if (!captchaSolveData && this.captchaCache) return this._throwError(new Error('Captcha is not solved.'));
|
427
|
+
if (this.callFindRealTokenCount > 5) {
|
428
|
+
return this._throwError(
|
429
|
+
new Error(
|
430
|
+
`Failed to find real token (${this.callFindRealTokenCount} times) ${this.captchaCache ? '[Captcha]' : ''}`,
|
431
|
+
),
|
432
|
+
);
|
433
|
+
}
|
434
|
+
this._logger('debug', 'Find real token...');
|
435
|
+
const res = await axios
|
436
|
+
.post(
|
437
|
+
`https://discord.com/api/v${this.options.apiVersion}/users/@me/remote-auth/login`,
|
438
|
+
captchaSolveData
|
439
|
+
? {
|
440
|
+
ticket: this.token,
|
441
|
+
captcha_rqtoken: this.captchaCache.captcha_rqtoken,
|
442
|
+
captcha_key: captchaSolveData,
|
443
|
+
}
|
444
|
+
: {
|
445
|
+
ticket: this.token,
|
446
|
+
},
|
447
|
+
{
|
448
|
+
headers: {
|
449
|
+
Accept: '*/*',
|
450
|
+
'Accept-Language': 'en-US',
|
451
|
+
'Content-Type': 'application/json',
|
452
|
+
'Sec-Fetch-Dest': 'empty',
|
453
|
+
'Sec-Fetch-Mode': 'cors',
|
454
|
+
'Sec-Fetch-Site': 'same-origin',
|
455
|
+
'X-Debug-Options': 'bugReporterEnabled',
|
456
|
+
'X-Super-Properties': `${Buffer.from(JSON.stringify(this.options.wsProperties), 'ascii').toString(
|
457
|
+
'base64',
|
458
|
+
)}`,
|
459
|
+
'X-Discord-Locale': 'en-US',
|
460
|
+
'User-Agent': this.options.userAgent,
|
461
|
+
Referer: 'https://discord.com/channels/@me',
|
462
|
+
Connection: 'keep-alive',
|
463
|
+
Origin: 'https://discord.com',
|
464
|
+
},
|
465
|
+
},
|
466
|
+
)
|
467
|
+
.catch(e => {
|
468
|
+
if (e.response.data?.captcha_key) {
|
469
|
+
this.captchaCache = e.response.data;
|
470
|
+
} else {
|
471
|
+
this._throwError(e);
|
472
|
+
this.captchaCache = null;
|
473
|
+
}
|
474
|
+
});
|
475
|
+
if (!res && this.captchaCache) {
|
476
|
+
this._logger('default', 'Captcha is detected. Please solve the captcha to continue.');
|
477
|
+
this._logger('debug', 'Try call captchaSolver()', this.captchaCache);
|
478
|
+
const token = await this.options.captchaSolver(this.captchaCache);
|
479
|
+
return this._findRealToken(token);
|
480
|
+
}
|
481
|
+
this.realToken = this._decryptPayload(res.data.encrypted_token).toString();
|
482
|
+
/**
|
483
|
+
* Emitted whenever a real token is found.
|
484
|
+
* @event DiscordAuthWebsocket#finish
|
485
|
+
* @param {object} user User
|
486
|
+
* @param {string} token Real token
|
487
|
+
*/
|
488
|
+
this.emit(Event.FINISH, this.user, this.realToken);
|
489
|
+
return this;
|
490
|
+
}
|
491
|
+
}
|
492
|
+
|
493
|
+
class User {
|
494
|
+
constructor(payload) {
|
495
|
+
const values = payload.split(':');
|
496
|
+
this.id = values[0];
|
497
|
+
this.username = values[3];
|
498
|
+
this.discriminator = values[1];
|
499
|
+
this.avatar = values[2];
|
500
|
+
return this;
|
501
|
+
}
|
502
|
+
get avatarURL() {
|
503
|
+
return `https://cdn.discordapp.com/avatars/${this.id}/${this.avatar}.${
|
504
|
+
this.avatar.startsWith('a_') ? 'gif' : 'png'
|
505
|
+
}`;
|
506
|
+
}
|
507
|
+
get tag() {
|
508
|
+
return `${this.username}#${this.discriminator}`;
|
509
|
+
}
|
510
|
+
prettyPrint(RemoteAuth) {
|
511
|
+
let string = `\n`;
|
512
|
+
string += ` ${chalk.bgBlue('User:')} `;
|
513
|
+
string += `${this.tag} (${this.id})\n`;
|
514
|
+
string += ` ${chalk.bgGreen('Avatar URL:')} `;
|
515
|
+
string += chalk.cyan(`${this.avatarURL}\n`);
|
516
|
+
string += ` ${chalk.bgMagenta('Token:')} `;
|
517
|
+
string += chalk.red(`${this.token ? this.token : 'Unknown'}`);
|
518
|
+
RemoteAuth._logger('default', string);
|
519
|
+
}
|
520
|
+
}
|
521
|
+
|
522
|
+
module.exports = DiscordAuthWebsocket;
|
@@ -0,0 +1,92 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
// Discord epoch (2015-01-01T00:00:00.000Z)
|
4
|
+
const EPOCH = 1_420_070_400_000;
|
5
|
+
let INCREMENT = BigInt(0);
|
6
|
+
|
7
|
+
/**
|
8
|
+
* A container for useful snowflake-related methods.
|
9
|
+
*/
|
10
|
+
class SnowflakeUtil extends null {
|
11
|
+
/**
|
12
|
+
* A {@link https://developer.twitter.com/en/docs/twitter-ids Twitter snowflake},
|
13
|
+
* except the epoch is 2015-01-01T00:00:00.000Z.
|
14
|
+
*
|
15
|
+
* If we have a snowflake '266241948824764416' we can represent it as binary:
|
16
|
+
* ```
|
17
|
+
* 64 22 17 12 0
|
18
|
+
* 000000111011000111100001101001000101000000 00001 00000 000000000000
|
19
|
+
* number of milliseconds since Discord epoch worker pid increment
|
20
|
+
* ```
|
21
|
+
* @typedef {string} Snowflake
|
22
|
+
*/
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Generates a Discord snowflake.
|
26
|
+
* <info>This hardcodes the worker's id as 1 and the process's id as 0.</info>
|
27
|
+
* @param {number|Date} [timestamp=Date.now()] Timestamp or date of the snowflake to generate
|
28
|
+
* @returns {Snowflake} The generated snowflake
|
29
|
+
*/
|
30
|
+
static generate(timestamp = Date.now()) {
|
31
|
+
if (timestamp instanceof Date) timestamp = timestamp.getTime();
|
32
|
+
if (typeof timestamp !== 'number' || isNaN(timestamp)) {
|
33
|
+
throw new TypeError(
|
34
|
+
`"timestamp" argument must be a number (received ${isNaN(timestamp) ? 'NaN' : typeof timestamp})`,
|
35
|
+
);
|
36
|
+
}
|
37
|
+
if (INCREMENT >= 4095n) INCREMENT = BigInt(0);
|
38
|
+
|
39
|
+
// Assign WorkerId as 1 and ProcessId as 0:
|
40
|
+
return ((BigInt(timestamp - EPOCH) << 22n) | (1n << 17n) | INCREMENT++).toString();
|
41
|
+
}
|
42
|
+
|
43
|
+
/**
|
44
|
+
* A deconstructed snowflake.
|
45
|
+
* @typedef {Object} DeconstructedSnowflake
|
46
|
+
* @property {number} timestamp Timestamp the snowflake was created
|
47
|
+
* @property {Date} date Date the snowflake was created
|
48
|
+
* @property {number} workerId The worker's id in the snowflake
|
49
|
+
* @property {number} processId The process's id in the snowflake
|
50
|
+
* @property {number} increment Increment in the snowflake
|
51
|
+
* @property {string} binary Binary representation of the snowflake
|
52
|
+
*/
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Deconstructs a Discord snowflake.
|
56
|
+
* @param {Snowflake} snowflake Snowflake to deconstruct
|
57
|
+
* @returns {DeconstructedSnowflake}
|
58
|
+
*/
|
59
|
+
static deconstruct(snowflake) {
|
60
|
+
const bigIntSnowflake = BigInt(snowflake);
|
61
|
+
return {
|
62
|
+
timestamp: Number(bigIntSnowflake >> 22n) + EPOCH,
|
63
|
+
get date() {
|
64
|
+
return new Date(this.timestamp);
|
65
|
+
},
|
66
|
+
workerId: Number((bigIntSnowflake >> 17n) & 0b11111n),
|
67
|
+
processId: Number((bigIntSnowflake >> 12n) & 0b11111n),
|
68
|
+
increment: Number(bigIntSnowflake & 0b111111111111n),
|
69
|
+
binary: bigIntSnowflake.toString(2).padStart(64, '0'),
|
70
|
+
};
|
71
|
+
}
|
72
|
+
|
73
|
+
/**
|
74
|
+
* Retrieves the timestamp field's value from a Discord snowflake.
|
75
|
+
* @param {Snowflake} snowflake Snowflake to get the timestamp value from
|
76
|
+
* @returns {number}
|
77
|
+
*/
|
78
|
+
static timestampFrom(snowflake) {
|
79
|
+
return Number(BigInt(snowflake) >> 22n) + EPOCH;
|
80
|
+
}
|
81
|
+
|
82
|
+
/**
|
83
|
+
* Discord's epoch value (2015-01-01T00:00:00.000Z).
|
84
|
+
* @type {number}
|
85
|
+
* @readonly
|
86
|
+
*/
|
87
|
+
static get EPOCH() {
|
88
|
+
return EPOCH;
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
module.exports = SnowflakeUtil;
|