diff --git a/README.md b/README.md index 3466d46..540be9d 100644 --- a/README.md +++ b/README.md @@ -40,12 +40,10 @@ that you should not make software that does things it is not supposed to do. ### Example bot (TS/JS) ```js -import { GatewayIntents, Session } from "@oasisjs/biscuit"; - -const token = "your token goes here"; +import Biscuit, { GatewayIntents } from "@oasisjs/biscuit"; const intents = GatewayIntents.MessageContent | GatewayIntents.Guilds | GatewayIntents.GuildMessages; -const session = new Session({ token, intents }); +const session = new Biscuit({ token: "your token", intents }); session.on("ready", ({ user }) => { console.log("Logged in as:", user.username); diff --git a/biscuit.js b/biscuit.js new file mode 100644 index 0000000..bfdffe9 --- /dev/null +++ b/biscuit.js @@ -0,0 +1,6319 @@ +// deno-fmt-ignore-file +// deno-lint-ignore-file +// This code was bundled using `deno bundle` and it's not recommended to edit it manually + +function calculateTotalShards(gateway) { + if (gateway.manager.totalShards < 100) return gateway.manager.totalShards; + return Math.ceil(gateway.manager.totalShards / (gateway.gatewayBot.sessionStartLimit.maxConcurrency === 1 ? 16 : gateway.gatewayBot.sessionStartLimit.maxConcurrency)) * gateway.gatewayBot.sessionStartLimit.maxConcurrency; +} +function calculateWorkerId(manager, shardId) { + let workerId = Math.floor(shardId / manager.shardsPerWorker); + if (workerId >= manager.totalWorkers) { + workerId = manager.totalWorkers - 1; + } + return workerId; +} +function spawnShards(gateway) { + gateway.prepareBuckets(); + gateway.buckets.forEach((bucket, bucketId)=>{ + for (const worker of bucket.workers){ + for (const shardId of worker.queue){ + gateway.tellWorkerToIdentify(worker.id, shardId, bucketId).catch(console.error); + } + } + }); +} +function delay(ms) { + return new Promise((res)=>setTimeout(()=>{ + res(); + }, ms)); +} +function createLeakyBucket({ max , refillInterval , refillAmount , tokens , waiting , ...rest }) { + return { + max, + refillInterval, + refillAmount: refillAmount > max ? max : refillAmount, + lastRefill: performance.now(), + allowAcquire: true, + nextRefill: function() { + return nextRefill(this); + }, + tokens: function() { + return updateTokens(this); + }, + acquire: async function(amount, highPriority) { + return await acquire(this, amount, highPriority); + }, + tokensState: tokens ?? max, + waiting: waiting ?? [], + ...rest + }; +} +function updateTokens(bucket) { + const timePassed = performance.now() - bucket.lastRefill; + const missedRefills = Math.floor(timePassed / bucket.refillInterval); + bucket.tokensState = Math.min(bucket.tokensState + bucket.refillAmount * missedRefills, bucket.max); + bucket.lastRefill += bucket.refillInterval * missedRefills; + return bucket.tokensState; +} +function nextRefill(bucket) { + updateTokens(bucket); + return performance.now() - bucket.lastRefill + bucket.refillInterval; +} +async function acquire(bucket, amount, highPriority = false) { + if (!bucket.allowAcquire) { + await new Promise((resolve)=>{ + if (highPriority) { + bucket.waiting.unshift(resolve); + } else { + bucket.waiting.push(resolve); + } + }); + if (!bucket.allowAcquire) { + return await acquire(bucket, amount); + } + } + bucket.allowAcquire = false; + let currentTokens = updateTokens(bucket); + if (currentTokens < amount) { + const tokensNeeded = amount - currentTokens; + let refillsNeeded = Math.ceil(tokensNeeded / bucket.refillAmount); + const waitTime = bucket.refillInterval * refillsNeeded; + await delay(waitTime); + updateTokens(bucket); + } + const toSubtract = amount % bucket.refillAmount || amount; + bucket.tokensState -= toSubtract; + bucket.allowAcquire = true; + bucket.waiting.shift()?.(); +} +function prepareBuckets(gateway) { + for(let i = 0; i < gateway.gatewayBot.sessionStartLimit.maxConcurrency; ++i){ + gateway.buckets.set(i, { + workers: [], + leak: createLeakyBucket({ + max: 1, + refillAmount: 1, + refillInterval: gateway.spawnShardDelay + }) + }); + } + for(let shardId = gateway.firstShardId; shardId <= gateway.lastShardId; ++shardId){ + if (shardId >= gateway.manager.totalShards) { + throw new Error(`Shard (id: ${shardId}) is bigger or equal to the used amount of used shards which is ${gateway.manager.totalShards}`); + } + const bucketId = shardId % gateway.gatewayBot.sessionStartLimit.maxConcurrency; + const bucket = gateway.buckets.get(bucketId); + if (!bucket) { + throw new Error(`Shard (id: ${shardId}) got assigned to an illegal bucket id: ${bucketId}, expected a bucket id between 0 and ${gateway.gatewayBot.sessionStartLimit.maxConcurrency - 1}`); + } + const workerId = gateway.calculateWorkerId(shardId); + const worker = bucket.workers.find((w)=>w.id === workerId); + if (worker) { + worker.queue.push(shardId); + } else { + bucket.workers.push({ + id: workerId, + queue: [ + shardId + ] + }); + } + } +} +async function tellWorkerToIdentify(gateway, _workerId, shardId, _bucketId) { + return await gateway.manager.identify(shardId); +} +var PremiumTypes; +(function(PremiumTypes) { + PremiumTypes[PremiumTypes["None"] = 0] = "None"; + PremiumTypes[PremiumTypes["NitroClassic"] = 1] = "NitroClassic"; + PremiumTypes[PremiumTypes["Nitro"] = 2] = "Nitro"; +})(PremiumTypes || (PremiumTypes = {})); +var UserFlags; +(function(UserFlags) { + UserFlags[UserFlags["DiscordEmployee"] = 1] = "DiscordEmployee"; + UserFlags[UserFlags["PartneredServerOwner"] = 2] = "PartneredServerOwner"; + UserFlags[UserFlags["HypeSquadEventsMember"] = 4] = "HypeSquadEventsMember"; + UserFlags[UserFlags["BugHunterLevel1"] = 8] = "BugHunterLevel1"; + UserFlags[UserFlags["HouseBravery"] = 64] = "HouseBravery"; + UserFlags[UserFlags["HouseBrilliance"] = 128] = "HouseBrilliance"; + UserFlags[UserFlags["HouseBalance"] = 256] = "HouseBalance"; + UserFlags[UserFlags["EarlySupporter"] = 512] = "EarlySupporter"; + UserFlags[UserFlags["TeamUser"] = 1024] = "TeamUser"; + UserFlags[UserFlags["BugHunterLevel2"] = 16384] = "BugHunterLevel2"; + UserFlags[UserFlags["VerifiedBot"] = 65536] = "VerifiedBot"; + UserFlags[UserFlags["EarlyVerifiedBotDeveloper"] = 131072] = "EarlyVerifiedBotDeveloper"; + UserFlags[UserFlags["DiscordCertifiedModerator"] = 262144] = "DiscordCertifiedModerator"; + UserFlags[UserFlags["BotHttpInteractions"] = 524288] = "BotHttpInteractions"; +})(UserFlags || (UserFlags = {})); +var ChannelFlags; +(function(ChannelFlags) { + ChannelFlags[ChannelFlags["None"] = 0] = "None"; + ChannelFlags[ChannelFlags["Pinned"] = 2] = "Pinned"; +})(ChannelFlags || (ChannelFlags = {})); +var IntegrationExpireBehaviors; +(function(IntegrationExpireBehaviors) { + IntegrationExpireBehaviors[IntegrationExpireBehaviors["RemoveRole"] = 0] = "RemoveRole"; + IntegrationExpireBehaviors[IntegrationExpireBehaviors["Kick"] = 1] = "Kick"; +})(IntegrationExpireBehaviors || (IntegrationExpireBehaviors = {})); +var VisibilityTypes; +(function(VisibilityTypes) { + VisibilityTypes[VisibilityTypes["None"] = 0] = "None"; + VisibilityTypes[VisibilityTypes["Everyone"] = 1] = "Everyone"; +})(VisibilityTypes || (VisibilityTypes = {})); +var TeamMembershipStates; +(function(TeamMembershipStates) { + TeamMembershipStates[TeamMembershipStates["Invited"] = 1] = "Invited"; + TeamMembershipStates[TeamMembershipStates["Accepted"] = 2] = "Accepted"; +})(TeamMembershipStates || (TeamMembershipStates = {})); +var ApplicationFlags; +(function(ApplicationFlags) { + ApplicationFlags[ApplicationFlags["GatewayPresence"] = 4096] = "GatewayPresence"; + ApplicationFlags[ApplicationFlags["GatewayPresenceLimited"] = 8192] = "GatewayPresenceLimited"; + ApplicationFlags[ApplicationFlags["GatewayGuildMembers"] = 16384] = "GatewayGuildMembers"; + ApplicationFlags[ApplicationFlags["GatewayGuildMembersLimited"] = 32768] = "GatewayGuildMembersLimited"; + ApplicationFlags[ApplicationFlags["VerificationPendingGuildLimit"] = 65536] = "VerificationPendingGuildLimit"; + ApplicationFlags[ApplicationFlags["Embedded"] = 131072] = "Embedded"; + ApplicationFlags[ApplicationFlags["GatewayMessageCount"] = 262144] = "GatewayMessageCount"; + ApplicationFlags[ApplicationFlags["GatewayMessageContentLimited"] = 524288] = "GatewayMessageContentLimited"; +})(ApplicationFlags || (ApplicationFlags = {})); +var MessageComponentTypes; +(function(MessageComponentTypes) { + MessageComponentTypes[MessageComponentTypes["ActionRow"] = 1] = "ActionRow"; + MessageComponentTypes[MessageComponentTypes["Button"] = 2] = "Button"; + MessageComponentTypes[MessageComponentTypes["SelectMenu"] = 3] = "SelectMenu"; + MessageComponentTypes[MessageComponentTypes["InputText"] = 4] = "InputText"; +})(MessageComponentTypes || (MessageComponentTypes = {})); +var TextStyles; +(function(TextStyles) { + TextStyles[TextStyles["Short"] = 1] = "Short"; + TextStyles[TextStyles["Paragraph"] = 2] = "Paragraph"; +})(TextStyles || (TextStyles = {})); +var ButtonStyles; +(function(ButtonStyles) { + ButtonStyles[ButtonStyles["Primary"] = 1] = "Primary"; + ButtonStyles[ButtonStyles["Secondary"] = 2] = "Secondary"; + ButtonStyles[ButtonStyles["Success"] = 3] = "Success"; + ButtonStyles[ButtonStyles["Danger"] = 4] = "Danger"; + ButtonStyles[ButtonStyles["Link"] = 5] = "Link"; +})(ButtonStyles || (ButtonStyles = {})); +var AllowedMentionsTypes; +(function(AllowedMentionsTypes) { + AllowedMentionsTypes["RoleMentions"] = "roles"; + AllowedMentionsTypes["UserMentions"] = "users"; + AllowedMentionsTypes["EveryoneMentions"] = "everyone"; +})(AllowedMentionsTypes || (AllowedMentionsTypes = {})); +var WebhookTypes; +(function(WebhookTypes) { + WebhookTypes[WebhookTypes["Incoming"] = 1] = "Incoming"; + WebhookTypes[WebhookTypes["ChannelFollower"] = 2] = "ChannelFollower"; + WebhookTypes[WebhookTypes["Application"] = 3] = "Application"; +})(WebhookTypes || (WebhookTypes = {})); +var DefaultMessageNotificationLevels; +(function(DefaultMessageNotificationLevels) { + DefaultMessageNotificationLevels[DefaultMessageNotificationLevels["AllMessages"] = 0] = "AllMessages"; + DefaultMessageNotificationLevels[DefaultMessageNotificationLevels["OnlyMentions"] = 1] = "OnlyMentions"; +})(DefaultMessageNotificationLevels || (DefaultMessageNotificationLevels = {})); +var ExplicitContentFilterLevels; +(function(ExplicitContentFilterLevels) { + ExplicitContentFilterLevels[ExplicitContentFilterLevels["Disabled"] = 0] = "Disabled"; + ExplicitContentFilterLevels[ExplicitContentFilterLevels["MembersWithoutRoles"] = 1] = "MembersWithoutRoles"; + ExplicitContentFilterLevels[ExplicitContentFilterLevels["AllMembers"] = 2] = "AllMembers"; +})(ExplicitContentFilterLevels || (ExplicitContentFilterLevels = {})); +var VerificationLevels; +(function(VerificationLevels) { + VerificationLevels[VerificationLevels["None"] = 0] = "None"; + VerificationLevels[VerificationLevels["Low"] = 1] = "Low"; + VerificationLevels[VerificationLevels["Medium"] = 2] = "Medium"; + VerificationLevels[VerificationLevels["High"] = 3] = "High"; + VerificationLevels[VerificationLevels["VeryHigh"] = 4] = "VeryHigh"; +})(VerificationLevels || (VerificationLevels = {})); +var GuildFeatures; +(function(GuildFeatures) { + GuildFeatures["InviteSplash"] = "INVITE_SPLASH"; + GuildFeatures["VipRegions"] = "VIP_REGIONS"; + GuildFeatures["VanityUrl"] = "VANITY_URL"; + GuildFeatures["Verified"] = "VERIFIED"; + GuildFeatures["Partnered"] = "PARTNERED"; + GuildFeatures["Community"] = "COMMUNITY"; + GuildFeatures["Commerce"] = "COMMERCE"; + GuildFeatures["News"] = "NEWS"; + GuildFeatures["Discoverable"] = "DISCOVERABLE"; + GuildFeatures["DiscoverableDisabled"] = "DISCOVERABLE_DISABLED"; + GuildFeatures["Feature"] = "FEATURABLE"; + GuildFeatures["AnimatedIcon"] = "ANIMATED_ICON"; + GuildFeatures["Banner"] = "BANNER"; + GuildFeatures["WelcomeScreenEnabled"] = "WELCOME_SCREEN_ENABLED"; + GuildFeatures["MemberVerificationGateEnabled"] = "MEMBER_VERIFICATION_GATE_ENABLED"; + GuildFeatures["PreviewEnabled"] = "PREVIEW_ENABLED"; + GuildFeatures["TicketedEventsEnabled"] = "TICKETED_EVENTS_ENABLED"; + GuildFeatures["MonetizationEnabled"] = "MONETIZATION_ENABLED"; + GuildFeatures["MoreStickers"] = "MORE_STICKERS"; + GuildFeatures["PrivateThreads"] = "PRIVATE_THREADS"; + GuildFeatures["RoleIcons"] = "ROLE_ICONS"; + GuildFeatures["AutoModeration"] = "AUTO_MODERATION"; +})(GuildFeatures || (GuildFeatures = {})); +var MfaLevels; +(function(MfaLevels) { + MfaLevels[MfaLevels["None"] = 0] = "None"; + MfaLevels[MfaLevels["Elevated"] = 1] = "Elevated"; +})(MfaLevels || (MfaLevels = {})); +var SystemChannelFlags; +(function(SystemChannelFlags) { + SystemChannelFlags[SystemChannelFlags["SuppressJoinNotifications"] = 1] = "SuppressJoinNotifications"; + SystemChannelFlags[SystemChannelFlags["SuppressPremiumSubscriptions"] = 2] = "SuppressPremiumSubscriptions"; + SystemChannelFlags[SystemChannelFlags["SuppressGuildReminderNotifications"] = 4] = "SuppressGuildReminderNotifications"; + SystemChannelFlags[SystemChannelFlags["SuppressJoinNotificationReplies"] = 8] = "SuppressJoinNotificationReplies"; +})(SystemChannelFlags || (SystemChannelFlags = {})); +var PremiumTiers; +(function(PremiumTiers) { + PremiumTiers[PremiumTiers["None"] = 0] = "None"; + PremiumTiers[PremiumTiers["Tier1"] = 1] = "Tier1"; + PremiumTiers[PremiumTiers["Tier2"] = 2] = "Tier2"; + PremiumTiers[PremiumTiers["Tier3"] = 3] = "Tier3"; +})(PremiumTiers || (PremiumTiers = {})); +var GuildNsfwLevel; +(function(GuildNsfwLevel) { + GuildNsfwLevel[GuildNsfwLevel["Default"] = 0] = "Default"; + GuildNsfwLevel[GuildNsfwLevel["Explicit"] = 1] = "Explicit"; + GuildNsfwLevel[GuildNsfwLevel["Safe"] = 2] = "Safe"; + GuildNsfwLevel[GuildNsfwLevel["AgeRestricted"] = 3] = "AgeRestricted"; +})(GuildNsfwLevel || (GuildNsfwLevel = {})); +var ChannelTypes; +(function(ChannelTypes) { + ChannelTypes[ChannelTypes["GuildText"] = 0] = "GuildText"; + ChannelTypes[ChannelTypes["DM"] = 1] = "DM"; + ChannelTypes[ChannelTypes["GuildVoice"] = 2] = "GuildVoice"; + ChannelTypes[ChannelTypes["GroupDm"] = 3] = "GroupDm"; + ChannelTypes[ChannelTypes["GuildCategory"] = 4] = "GuildCategory"; + ChannelTypes[ChannelTypes["GuildNews"] = 5] = "GuildNews"; + ChannelTypes[ChannelTypes["GuildNewsThread"] = 10] = "GuildNewsThread"; + ChannelTypes[ChannelTypes["GuildPublicThread"] = 11] = "GuildPublicThread"; + ChannelTypes[ChannelTypes["GuildPrivateThread"] = 12] = "GuildPrivateThread"; + ChannelTypes[ChannelTypes["GuildStageVoice"] = 13] = "GuildStageVoice"; + ChannelTypes[ChannelTypes["GuildDirectory"] = 14] = "GuildDirectory"; + ChannelTypes[ChannelTypes["GuildForum"] = 15] = "GuildForum"; +})(ChannelTypes || (ChannelTypes = {})); +var OverwriteTypes; +(function(OverwriteTypes) { + OverwriteTypes[OverwriteTypes["Role"] = 0] = "Role"; + OverwriteTypes[OverwriteTypes["Member"] = 1] = "Member"; +})(OverwriteTypes || (OverwriteTypes = {})); +var VideoQualityModes; +(function(VideoQualityModes) { + VideoQualityModes[VideoQualityModes["Auto"] = 1] = "Auto"; + VideoQualityModes[VideoQualityModes["Full"] = 2] = "Full"; +})(VideoQualityModes || (VideoQualityModes = {})); +var ActivityTypes; +(function(ActivityTypes) { + ActivityTypes[ActivityTypes["Game"] = 0] = "Game"; + ActivityTypes[ActivityTypes["Streaming"] = 1] = "Streaming"; + ActivityTypes[ActivityTypes["Listening"] = 2] = "Listening"; + ActivityTypes[ActivityTypes["Watching"] = 3] = "Watching"; + ActivityTypes[ActivityTypes["Custom"] = 4] = "Custom"; + ActivityTypes[ActivityTypes["Competing"] = 5] = "Competing"; +})(ActivityTypes || (ActivityTypes = {})); +var MessageTypes; +(function(MessageTypes) { + MessageTypes[MessageTypes["Default"] = 0] = "Default"; + MessageTypes[MessageTypes["RecipientAdd"] = 1] = "RecipientAdd"; + MessageTypes[MessageTypes["RecipientRemove"] = 2] = "RecipientRemove"; + MessageTypes[MessageTypes["Call"] = 3] = "Call"; + MessageTypes[MessageTypes["ChannelNameChange"] = 4] = "ChannelNameChange"; + MessageTypes[MessageTypes["ChannelIconChange"] = 5] = "ChannelIconChange"; + MessageTypes[MessageTypes["ChannelPinnedMessage"] = 6] = "ChannelPinnedMessage"; + MessageTypes[MessageTypes["GuildMemberJoin"] = 7] = "GuildMemberJoin"; + MessageTypes[MessageTypes["UserPremiumGuildSubscription"] = 8] = "UserPremiumGuildSubscription"; + MessageTypes[MessageTypes["UserPremiumGuildSubscriptionTier1"] = 9] = "UserPremiumGuildSubscriptionTier1"; + MessageTypes[MessageTypes["UserPremiumGuildSubscriptionTier2"] = 10] = "UserPremiumGuildSubscriptionTier2"; + MessageTypes[MessageTypes["UserPremiumGuildSubscriptionTier3"] = 11] = "UserPremiumGuildSubscriptionTier3"; + MessageTypes[MessageTypes["ChannelFollowAdd"] = 12] = "ChannelFollowAdd"; + MessageTypes[MessageTypes["GuildDiscoveryDisqualified"] = 14] = "GuildDiscoveryDisqualified"; + MessageTypes[MessageTypes["GuildDiscoveryRequalified"] = 15] = "GuildDiscoveryRequalified"; + MessageTypes[MessageTypes["GuildDiscoveryGracePeriodInitialWarning"] = 16] = "GuildDiscoveryGracePeriodInitialWarning"; + MessageTypes[MessageTypes["GuildDiscoveryGracePeriodFinalWarning"] = 17] = "GuildDiscoveryGracePeriodFinalWarning"; + MessageTypes[MessageTypes["ThreadCreated"] = 18] = "ThreadCreated"; + MessageTypes[MessageTypes["Reply"] = 19] = "Reply"; + MessageTypes[MessageTypes["ChatInputCommand"] = 20] = "ChatInputCommand"; + MessageTypes[MessageTypes["ThreadStarterMessage"] = 21] = "ThreadStarterMessage"; + MessageTypes[MessageTypes["GuildInviteReminder"] = 22] = "GuildInviteReminder"; + MessageTypes[MessageTypes["ContextMenuCommand"] = 23] = "ContextMenuCommand"; + MessageTypes[MessageTypes["AutoModerationAction"] = 24] = "AutoModerationAction"; +})(MessageTypes || (MessageTypes = {})); +var MessageActivityTypes; +(function(MessageActivityTypes) { + MessageActivityTypes[MessageActivityTypes["Join"] = 1] = "Join"; + MessageActivityTypes[MessageActivityTypes["Spectate"] = 2] = "Spectate"; + MessageActivityTypes[MessageActivityTypes["Listen"] = 3] = "Listen"; + MessageActivityTypes[MessageActivityTypes["JoinRequest"] = 4] = "JoinRequest"; +})(MessageActivityTypes || (MessageActivityTypes = {})); +var StickerTypes; +(function(StickerTypes) { + StickerTypes[StickerTypes["Standard"] = 1] = "Standard"; + StickerTypes[StickerTypes["Guild"] = 2] = "Guild"; +})(StickerTypes || (StickerTypes = {})); +var StickerFormatTypes; +(function(StickerFormatTypes) { + StickerFormatTypes[StickerFormatTypes["Png"] = 1] = "Png"; + StickerFormatTypes[StickerFormatTypes["APng"] = 2] = "APng"; + StickerFormatTypes[StickerFormatTypes["Lottie"] = 3] = "Lottie"; +})(StickerFormatTypes || (StickerFormatTypes = {})); +var InteractionTypes; +(function(InteractionTypes) { + InteractionTypes[InteractionTypes["Ping"] = 1] = "Ping"; + InteractionTypes[InteractionTypes["ApplicationCommand"] = 2] = "ApplicationCommand"; + InteractionTypes[InteractionTypes["MessageComponent"] = 3] = "MessageComponent"; + InteractionTypes[InteractionTypes["ApplicationCommandAutocomplete"] = 4] = "ApplicationCommandAutocomplete"; + InteractionTypes[InteractionTypes["ModalSubmit"] = 5] = "ModalSubmit"; +})(InteractionTypes || (InteractionTypes = {})); +var ApplicationCommandOptionTypes; +(function(ApplicationCommandOptionTypes) { + ApplicationCommandOptionTypes[ApplicationCommandOptionTypes["SubCommand"] = 1] = "SubCommand"; + ApplicationCommandOptionTypes[ApplicationCommandOptionTypes["SubCommandGroup"] = 2] = "SubCommandGroup"; + ApplicationCommandOptionTypes[ApplicationCommandOptionTypes["String"] = 3] = "String"; + ApplicationCommandOptionTypes[ApplicationCommandOptionTypes["Integer"] = 4] = "Integer"; + ApplicationCommandOptionTypes[ApplicationCommandOptionTypes["Boolean"] = 5] = "Boolean"; + ApplicationCommandOptionTypes[ApplicationCommandOptionTypes["User"] = 6] = "User"; + ApplicationCommandOptionTypes[ApplicationCommandOptionTypes["Channel"] = 7] = "Channel"; + ApplicationCommandOptionTypes[ApplicationCommandOptionTypes["Role"] = 8] = "Role"; + ApplicationCommandOptionTypes[ApplicationCommandOptionTypes["Mentionable"] = 9] = "Mentionable"; + ApplicationCommandOptionTypes[ApplicationCommandOptionTypes["Number"] = 10] = "Number"; + ApplicationCommandOptionTypes[ApplicationCommandOptionTypes["Attachment"] = 11] = "Attachment"; +})(ApplicationCommandOptionTypes || (ApplicationCommandOptionTypes = {})); +var AuditLogEvents; +(function(AuditLogEvents) { + AuditLogEvents[AuditLogEvents["GuildUpdate"] = 1] = "GuildUpdate"; + AuditLogEvents[AuditLogEvents["ChannelCreate"] = 10] = "ChannelCreate"; + AuditLogEvents[AuditLogEvents["ChannelUpdate"] = 11] = "ChannelUpdate"; + AuditLogEvents[AuditLogEvents["ChannelDelete"] = 12] = "ChannelDelete"; + AuditLogEvents[AuditLogEvents["ChannelOverwriteCreate"] = 13] = "ChannelOverwriteCreate"; + AuditLogEvents[AuditLogEvents["ChannelOverwriteUpdate"] = 14] = "ChannelOverwriteUpdate"; + AuditLogEvents[AuditLogEvents["ChannelOverwriteDelete"] = 15] = "ChannelOverwriteDelete"; + AuditLogEvents[AuditLogEvents["MemberKick"] = 20] = "MemberKick"; + AuditLogEvents[AuditLogEvents["MemberPrune"] = 21] = "MemberPrune"; + AuditLogEvents[AuditLogEvents["MemberBanAdd"] = 22] = "MemberBanAdd"; + AuditLogEvents[AuditLogEvents["MemberBanRemove"] = 23] = "MemberBanRemove"; + AuditLogEvents[AuditLogEvents["MemberUpdate"] = 24] = "MemberUpdate"; + AuditLogEvents[AuditLogEvents["MemberRoleUpdate"] = 25] = "MemberRoleUpdate"; + AuditLogEvents[AuditLogEvents["MemberMove"] = 26] = "MemberMove"; + AuditLogEvents[AuditLogEvents["MemberDisconnect"] = 27] = "MemberDisconnect"; + AuditLogEvents[AuditLogEvents["BotAdd"] = 28] = "BotAdd"; + AuditLogEvents[AuditLogEvents["RoleCreate"] = 30] = "RoleCreate"; + AuditLogEvents[AuditLogEvents["RoleUpdate"] = 31] = "RoleUpdate"; + AuditLogEvents[AuditLogEvents["RoleDelete"] = 32] = "RoleDelete"; + AuditLogEvents[AuditLogEvents["InviteCreate"] = 40] = "InviteCreate"; + AuditLogEvents[AuditLogEvents["InviteUpdate"] = 41] = "InviteUpdate"; + AuditLogEvents[AuditLogEvents["InviteDelete"] = 42] = "InviteDelete"; + AuditLogEvents[AuditLogEvents["WebhookCreate"] = 50] = "WebhookCreate"; + AuditLogEvents[AuditLogEvents["WebhookUpdate"] = 51] = "WebhookUpdate"; + AuditLogEvents[AuditLogEvents["WebhookDelete"] = 52] = "WebhookDelete"; + AuditLogEvents[AuditLogEvents["EmojiCreate"] = 60] = "EmojiCreate"; + AuditLogEvents[AuditLogEvents["EmojiUpdate"] = 61] = "EmojiUpdate"; + AuditLogEvents[AuditLogEvents["EmojiDelete"] = 62] = "EmojiDelete"; + AuditLogEvents[AuditLogEvents["MessageDelete"] = 72] = "MessageDelete"; + AuditLogEvents[AuditLogEvents["MessageBulkDelete"] = 73] = "MessageBulkDelete"; + AuditLogEvents[AuditLogEvents["MessagePin"] = 74] = "MessagePin"; + AuditLogEvents[AuditLogEvents["MessageUnpin"] = 75] = "MessageUnpin"; + AuditLogEvents[AuditLogEvents["IntegrationCreate"] = 80] = "IntegrationCreate"; + AuditLogEvents[AuditLogEvents["IntegrationUpdate"] = 81] = "IntegrationUpdate"; + AuditLogEvents[AuditLogEvents["IntegrationDelete"] = 82] = "IntegrationDelete"; + AuditLogEvents[AuditLogEvents["StageInstanceCreate"] = 83] = "StageInstanceCreate"; + AuditLogEvents[AuditLogEvents["StageInstanceUpdate"] = 84] = "StageInstanceUpdate"; + AuditLogEvents[AuditLogEvents["StageInstanceDelete"] = 85] = "StageInstanceDelete"; + AuditLogEvents[AuditLogEvents["StickerCreate"] = 90] = "StickerCreate"; + AuditLogEvents[AuditLogEvents["StickerUpdate"] = 91] = "StickerUpdate"; + AuditLogEvents[AuditLogEvents["StickerDelete"] = 92] = "StickerDelete"; + AuditLogEvents[AuditLogEvents["GuildScheduledEventCreate"] = 100] = "GuildScheduledEventCreate"; + AuditLogEvents[AuditLogEvents["GuildScheduledEventUpdate"] = 101] = "GuildScheduledEventUpdate"; + AuditLogEvents[AuditLogEvents["GuildScheduledEventDelete"] = 102] = "GuildScheduledEventDelete"; + AuditLogEvents[AuditLogEvents["ThreadCreate"] = 110] = "ThreadCreate"; + AuditLogEvents[AuditLogEvents["ThreadUpdate"] = 111] = "ThreadUpdate"; + AuditLogEvents[AuditLogEvents["ThreadDelete"] = 112] = "ThreadDelete"; + AuditLogEvents[AuditLogEvents["ApplicationCommandPermissionUpdate"] = 121] = "ApplicationCommandPermissionUpdate"; + AuditLogEvents[AuditLogEvents["AutoModerationRuleCreate"] = 140] = "AutoModerationRuleCreate"; + AuditLogEvents[AuditLogEvents["AutoModerationRuleUpdate"] = 141] = "AutoModerationRuleUpdate"; + AuditLogEvents[AuditLogEvents["AutoModerationRuleDelete"] = 142] = "AutoModerationRuleDelete"; + AuditLogEvents[AuditLogEvents["AutoModerationBlockMessage"] = 143] = "AutoModerationBlockMessage"; +})(AuditLogEvents || (AuditLogEvents = {})); +var ScheduledEventPrivacyLevel; +(function(ScheduledEventPrivacyLevel) { + ScheduledEventPrivacyLevel[ScheduledEventPrivacyLevel["GuildOnly"] = 2] = "GuildOnly"; +})(ScheduledEventPrivacyLevel || (ScheduledEventPrivacyLevel = {})); +var ScheduledEventEntityType; +(function(ScheduledEventEntityType) { + ScheduledEventEntityType[ScheduledEventEntityType["StageInstance"] = 1] = "StageInstance"; + ScheduledEventEntityType[ScheduledEventEntityType["Voice"] = 2] = "Voice"; + ScheduledEventEntityType[ScheduledEventEntityType["External"] = 3] = "External"; +})(ScheduledEventEntityType || (ScheduledEventEntityType = {})); +var ScheduledEventStatus; +(function(ScheduledEventStatus) { + ScheduledEventStatus[ScheduledEventStatus["Scheduled"] = 1] = "Scheduled"; + ScheduledEventStatus[ScheduledEventStatus["Active"] = 2] = "Active"; + ScheduledEventStatus[ScheduledEventStatus["Completed"] = 3] = "Completed"; + ScheduledEventStatus[ScheduledEventStatus["Canceled"] = 4] = "Canceled"; +})(ScheduledEventStatus || (ScheduledEventStatus = {})); +var TargetTypes; +(function(TargetTypes) { + TargetTypes[TargetTypes["Stream"] = 1] = "Stream"; + TargetTypes[TargetTypes["EmbeddedApplication"] = 2] = "EmbeddedApplication"; +})(TargetTypes || (TargetTypes = {})); +var ApplicationCommandTypes; +(function(ApplicationCommandTypes) { + ApplicationCommandTypes[ApplicationCommandTypes["ChatInput"] = 1] = "ChatInput"; + ApplicationCommandTypes[ApplicationCommandTypes["User"] = 2] = "User"; + ApplicationCommandTypes[ApplicationCommandTypes["Message"] = 3] = "Message"; +})(ApplicationCommandTypes || (ApplicationCommandTypes = {})); +var ApplicationCommandPermissionTypes; +(function(ApplicationCommandPermissionTypes) { + ApplicationCommandPermissionTypes[ApplicationCommandPermissionTypes["Role"] = 1] = "Role"; + ApplicationCommandPermissionTypes[ApplicationCommandPermissionTypes["User"] = 2] = "User"; + ApplicationCommandPermissionTypes[ApplicationCommandPermissionTypes["Channel"] = 3] = "Channel"; +})(ApplicationCommandPermissionTypes || (ApplicationCommandPermissionTypes = {})); +var ActivityFlags; +(function(ActivityFlags) { + ActivityFlags[ActivityFlags["Instance"] = 1] = "Instance"; + ActivityFlags[ActivityFlags["Join"] = 2] = "Join"; + ActivityFlags[ActivityFlags["Spectate"] = 4] = "Spectate"; + ActivityFlags[ActivityFlags["JoinRequest"] = 8] = "JoinRequest"; + ActivityFlags[ActivityFlags["Sync"] = 16] = "Sync"; + ActivityFlags[ActivityFlags["Play"] = 32] = "Play"; + ActivityFlags[ActivityFlags["PartyPrivacyFriends"] = 64] = "PartyPrivacyFriends"; + ActivityFlags[ActivityFlags["PartyPrivacyVoiceChannel"] = 128] = "PartyPrivacyVoiceChannel"; + ActivityFlags[ActivityFlags["Embedded"] = 256] = "Embedded"; +})(ActivityFlags || (ActivityFlags = {})); +var BitwisePermissionFlags; +(function(BitwisePermissionFlags) { + BitwisePermissionFlags[BitwisePermissionFlags["CREATE_INSTANT_INVITE"] = 0x0000000000000001] = "CREATE_INSTANT_INVITE"; + BitwisePermissionFlags[BitwisePermissionFlags["KICK_MEMBERS"] = 0x0000000000000002] = "KICK_MEMBERS"; + BitwisePermissionFlags[BitwisePermissionFlags["BAN_MEMBERS"] = 0x0000000000000004] = "BAN_MEMBERS"; + BitwisePermissionFlags[BitwisePermissionFlags["ADMINISTRATOR"] = 0x0000000000000008] = "ADMINISTRATOR"; + BitwisePermissionFlags[BitwisePermissionFlags["MANAGE_CHANNELS"] = 0x0000000000000010] = "MANAGE_CHANNELS"; + BitwisePermissionFlags[BitwisePermissionFlags["MANAGE_GUILD"] = 0x0000000000000020] = "MANAGE_GUILD"; + BitwisePermissionFlags[BitwisePermissionFlags["ADD_REACTIONS"] = 0x0000000000000040] = "ADD_REACTIONS"; + BitwisePermissionFlags[BitwisePermissionFlags["VIEW_AUDIT_LOG"] = 0x0000000000000080] = "VIEW_AUDIT_LOG"; + BitwisePermissionFlags[BitwisePermissionFlags["PRIORITY_SPEAKER"] = 0x0000000000000100] = "PRIORITY_SPEAKER"; + BitwisePermissionFlags[BitwisePermissionFlags["STREAM"] = 0x0000000000000200] = "STREAM"; + BitwisePermissionFlags[BitwisePermissionFlags["VIEW_CHANNEL"] = 0x0000000000000400] = "VIEW_CHANNEL"; + BitwisePermissionFlags[BitwisePermissionFlags["SEND_MESSAGES"] = 0x0000000000000800] = "SEND_MESSAGES"; + BitwisePermissionFlags[BitwisePermissionFlags["SEND_TTS_MESSAGES"] = 0x0000000000001000] = "SEND_TTS_MESSAGES"; + BitwisePermissionFlags[BitwisePermissionFlags["MANAGE_MESSAGES"] = 0x0000000000002000] = "MANAGE_MESSAGES"; + BitwisePermissionFlags[BitwisePermissionFlags["EMBED_LINKS"] = 0x0000000000004000] = "EMBED_LINKS"; + BitwisePermissionFlags[BitwisePermissionFlags["ATTACH_FILES"] = 0x0000000000008000] = "ATTACH_FILES"; + BitwisePermissionFlags[BitwisePermissionFlags["READ_MESSAGE_HISTORY"] = 0x0000000000010000] = "READ_MESSAGE_HISTORY"; + BitwisePermissionFlags[BitwisePermissionFlags["MENTION_EVERYONE"] = 0x0000000000020000] = "MENTION_EVERYONE"; + BitwisePermissionFlags[BitwisePermissionFlags["USE_EXTERNAL_EMOJIS"] = 0x0000000000040000] = "USE_EXTERNAL_EMOJIS"; + BitwisePermissionFlags[BitwisePermissionFlags["VIEW_GUILD_INSIGHTS"] = 0x0000000000080000] = "VIEW_GUILD_INSIGHTS"; + BitwisePermissionFlags[BitwisePermissionFlags["CONNECT"] = 0x0000000000100000] = "CONNECT"; + BitwisePermissionFlags[BitwisePermissionFlags["SPEAK"] = 0x0000000000200000] = "SPEAK"; + BitwisePermissionFlags[BitwisePermissionFlags["MUTE_MEMBERS"] = 0x0000000000400000] = "MUTE_MEMBERS"; + BitwisePermissionFlags[BitwisePermissionFlags["DEAFEN_MEMBERS"] = 0x0000000000800000] = "DEAFEN_MEMBERS"; + BitwisePermissionFlags[BitwisePermissionFlags["MOVE_MEMBERS"] = 0x0000000001000000] = "MOVE_MEMBERS"; + BitwisePermissionFlags[BitwisePermissionFlags["USE_VAD"] = 0x0000000002000000] = "USE_VAD"; + BitwisePermissionFlags[BitwisePermissionFlags["CHANGE_NICKNAME"] = 0x0000000004000000] = "CHANGE_NICKNAME"; + BitwisePermissionFlags[BitwisePermissionFlags["MANAGE_NICKNAMES"] = 0x0000000008000000] = "MANAGE_NICKNAMES"; + BitwisePermissionFlags[BitwisePermissionFlags["MANAGE_ROLES"] = 0x0000000010000000] = "MANAGE_ROLES"; + BitwisePermissionFlags[BitwisePermissionFlags["MANAGE_WEBHOOKS"] = 0x0000000020000000] = "MANAGE_WEBHOOKS"; + BitwisePermissionFlags[BitwisePermissionFlags["MANAGE_EMOJIS"] = 0x0000000040000000] = "MANAGE_EMOJIS"; + BitwisePermissionFlags[BitwisePermissionFlags["USE_SLASH_COMMANDS"] = 0x0000000080000000] = "USE_SLASH_COMMANDS"; + BitwisePermissionFlags[BitwisePermissionFlags["REQUEST_TO_SPEAK"] = 0x0000000100000000] = "REQUEST_TO_SPEAK"; + BitwisePermissionFlags[BitwisePermissionFlags["MANAGE_EVENTS"] = 0x0000000200000000] = "MANAGE_EVENTS"; + BitwisePermissionFlags[BitwisePermissionFlags["MANAGE_THREADS"] = 0x0000000400000000] = "MANAGE_THREADS"; + BitwisePermissionFlags[BitwisePermissionFlags["CREATE_PUBLIC_THREADS"] = 0x0000000800000000] = "CREATE_PUBLIC_THREADS"; + BitwisePermissionFlags[BitwisePermissionFlags["CREATE_PRIVATE_THREADS"] = 0x0000001000000000] = "CREATE_PRIVATE_THREADS"; + BitwisePermissionFlags[BitwisePermissionFlags["USE_EXTERNAL_STICKERS"] = 0x0000002000000000] = "USE_EXTERNAL_STICKERS"; + BitwisePermissionFlags[BitwisePermissionFlags["SEND_MESSAGES_IN_THREADS"] = 0x0000004000000000] = "SEND_MESSAGES_IN_THREADS"; + BitwisePermissionFlags[BitwisePermissionFlags["USE_EMBEDDED_ACTIVITIES"] = 0x0000008000000000] = "USE_EMBEDDED_ACTIVITIES"; + BitwisePermissionFlags[BitwisePermissionFlags["MODERATE_MEMBERS"] = 0x0000010000000000] = "MODERATE_MEMBERS"; +})(BitwisePermissionFlags || (BitwisePermissionFlags = {})); +var VoiceOpcodes; +(function(VoiceOpcodes) { + VoiceOpcodes[VoiceOpcodes["Identify"] = 0] = "Identify"; + VoiceOpcodes[VoiceOpcodes["SelectProtocol"] = 1] = "SelectProtocol"; + VoiceOpcodes[VoiceOpcodes["Ready"] = 2] = "Ready"; + VoiceOpcodes[VoiceOpcodes["Heartbeat"] = 3] = "Heartbeat"; + VoiceOpcodes[VoiceOpcodes["SessionDescription"] = 4] = "SessionDescription"; + VoiceOpcodes[VoiceOpcodes["Speaking"] = 5] = "Speaking"; + VoiceOpcodes[VoiceOpcodes["HeartbeatACK"] = 6] = "HeartbeatACK"; + VoiceOpcodes[VoiceOpcodes["Resume"] = 7] = "Resume"; + VoiceOpcodes[VoiceOpcodes["Hello"] = 8] = "Hello"; + VoiceOpcodes[VoiceOpcodes["Resumed"] = 9] = "Resumed"; + VoiceOpcodes[VoiceOpcodes["ClientDisconnect"] = 13] = "ClientDisconnect"; +})(VoiceOpcodes || (VoiceOpcodes = {})); +var VoiceCloseEventCodes; +(function(VoiceCloseEventCodes) { + VoiceCloseEventCodes[VoiceCloseEventCodes["UnknownOpcode"] = 4001] = "UnknownOpcode"; + VoiceCloseEventCodes[VoiceCloseEventCodes["FailedToDecodePayload"] = 4002] = "FailedToDecodePayload"; + VoiceCloseEventCodes[VoiceCloseEventCodes["NotAuthenticated"] = 4003] = "NotAuthenticated"; + VoiceCloseEventCodes[VoiceCloseEventCodes["AuthenticationFailed"] = 4004] = "AuthenticationFailed"; + VoiceCloseEventCodes[VoiceCloseEventCodes["AlreadyAuthenticated"] = 4005] = "AlreadyAuthenticated"; + VoiceCloseEventCodes[VoiceCloseEventCodes["SessionNoLongerValid"] = 4006] = "SessionNoLongerValid"; + VoiceCloseEventCodes[VoiceCloseEventCodes["SessionTimedOut"] = 4009] = "SessionTimedOut"; + VoiceCloseEventCodes[VoiceCloseEventCodes["ServerNotFound"] = 4011] = "ServerNotFound"; + VoiceCloseEventCodes[VoiceCloseEventCodes["UnknownProtocol"] = 4012] = "UnknownProtocol"; + VoiceCloseEventCodes[VoiceCloseEventCodes["Disconnect"] = 4014] = "Disconnect"; + VoiceCloseEventCodes[VoiceCloseEventCodes["VoiceServerCrashed"] = 4015] = "VoiceServerCrashed"; + VoiceCloseEventCodes[VoiceCloseEventCodes["UnknownEncryptionMode"] = 4016] = "UnknownEncryptionMode"; +})(VoiceCloseEventCodes || (VoiceCloseEventCodes = {})); +var RpcErrorCodes; +(function(RpcErrorCodes) { + RpcErrorCodes[RpcErrorCodes["UnknownError"] = 1000] = "UnknownError"; + RpcErrorCodes[RpcErrorCodes["InvalidPayload"] = 4000] = "InvalidPayload"; + RpcErrorCodes[RpcErrorCodes["InvalidCommand"] = 4002] = "InvalidCommand"; + RpcErrorCodes[RpcErrorCodes["InvalidGuild"] = 4003] = "InvalidGuild"; + RpcErrorCodes[RpcErrorCodes["InvalidEvent"] = 4004] = "InvalidEvent"; + RpcErrorCodes[RpcErrorCodes["InvalidChannel"] = 4005] = "InvalidChannel"; + RpcErrorCodes[RpcErrorCodes["InvalidPermissions"] = 4006] = "InvalidPermissions"; + RpcErrorCodes[RpcErrorCodes["InvalidClientId"] = 4007] = "InvalidClientId"; + RpcErrorCodes[RpcErrorCodes["InvalidOrigin"] = 4008] = "InvalidOrigin"; + RpcErrorCodes[RpcErrorCodes["InvalidToken"] = 4009] = "InvalidToken"; + RpcErrorCodes[RpcErrorCodes["InvalidUser"] = 4010] = "InvalidUser"; + RpcErrorCodes[RpcErrorCodes["OAuth2Error"] = 5000] = "OAuth2Error"; + RpcErrorCodes[RpcErrorCodes["SelectChannelTimedOut"] = 5001] = "SelectChannelTimedOut"; + RpcErrorCodes[RpcErrorCodes["GetGuildTimedOut"] = 5002] = "GetGuildTimedOut"; + RpcErrorCodes[RpcErrorCodes["SelectVoiceForceRequired"] = 5003] = "SelectVoiceForceRequired"; + RpcErrorCodes[RpcErrorCodes["CaptureShortcutAlreadyListening"] = 5004] = "CaptureShortcutAlreadyListening"; +})(RpcErrorCodes || (RpcErrorCodes = {})); +var RpcCloseEventCodes; +(function(RpcCloseEventCodes) { + RpcCloseEventCodes[RpcCloseEventCodes["InvalidClientId"] = 4000] = "InvalidClientId"; + RpcCloseEventCodes[RpcCloseEventCodes["InvalidOrigin"] = 4001] = "InvalidOrigin"; + RpcCloseEventCodes[RpcCloseEventCodes["RateLimited"] = 4002] = "RateLimited"; + RpcCloseEventCodes[RpcCloseEventCodes["TokenRevoked"] = 4003] = "TokenRevoked"; + RpcCloseEventCodes[RpcCloseEventCodes["InvalidVersion"] = 4004] = "InvalidVersion"; + RpcCloseEventCodes[RpcCloseEventCodes["InvalidEncoding"] = 4005] = "InvalidEncoding"; +})(RpcCloseEventCodes || (RpcCloseEventCodes = {})); +var HTTPResponseCodes; +(function(HTTPResponseCodes) { + HTTPResponseCodes[HTTPResponseCodes["Ok"] = 200] = "Ok"; + HTTPResponseCodes[HTTPResponseCodes["Created"] = 201] = "Created"; + HTTPResponseCodes[HTTPResponseCodes["NoContent"] = 204] = "NoContent"; + HTTPResponseCodes[HTTPResponseCodes["NotModified"] = 304] = "NotModified"; + HTTPResponseCodes[HTTPResponseCodes["BadRequest"] = 400] = "BadRequest"; + HTTPResponseCodes[HTTPResponseCodes["Unauthorized"] = 401] = "Unauthorized"; + HTTPResponseCodes[HTTPResponseCodes["Forbidden"] = 403] = "Forbidden"; + HTTPResponseCodes[HTTPResponseCodes["NotFound"] = 404] = "NotFound"; + HTTPResponseCodes[HTTPResponseCodes["MethodNotAllowed"] = 405] = "MethodNotAllowed"; + HTTPResponseCodes[HTTPResponseCodes["TooManyRequests"] = 429] = "TooManyRequests"; + HTTPResponseCodes[HTTPResponseCodes["GatewayUnavailable"] = 502] = "GatewayUnavailable"; +})(HTTPResponseCodes || (HTTPResponseCodes = {})); +var GatewayCloseEventCodes; +(function(GatewayCloseEventCodes) { + GatewayCloseEventCodes[GatewayCloseEventCodes["NormalClosure"] = 1000] = "NormalClosure"; + GatewayCloseEventCodes[GatewayCloseEventCodes["UnknownError"] = 4000] = "UnknownError"; + GatewayCloseEventCodes[GatewayCloseEventCodes["UnknownOpcode"] = 4001] = "UnknownOpcode"; + GatewayCloseEventCodes[GatewayCloseEventCodes["DecodeError"] = 4002] = "DecodeError"; + GatewayCloseEventCodes[GatewayCloseEventCodes["NotAuthenticated"] = 4003] = "NotAuthenticated"; + GatewayCloseEventCodes[GatewayCloseEventCodes["AuthenticationFailed"] = 4004] = "AuthenticationFailed"; + GatewayCloseEventCodes[GatewayCloseEventCodes["AlreadyAuthenticated"] = 4005] = "AlreadyAuthenticated"; + GatewayCloseEventCodes[GatewayCloseEventCodes["InvalidSeq"] = 4007] = "InvalidSeq"; + GatewayCloseEventCodes[GatewayCloseEventCodes["RateLimited"] = 4008] = "RateLimited"; + GatewayCloseEventCodes[GatewayCloseEventCodes["SessionTimedOut"] = 4009] = "SessionTimedOut"; + GatewayCloseEventCodes[GatewayCloseEventCodes["InvalidShard"] = 4010] = "InvalidShard"; + GatewayCloseEventCodes[GatewayCloseEventCodes["ShardingRequired"] = 4011] = "ShardingRequired"; + GatewayCloseEventCodes[GatewayCloseEventCodes["InvalidApiVersion"] = 4012] = "InvalidApiVersion"; + GatewayCloseEventCodes[GatewayCloseEventCodes["InvalidIntents"] = 4013] = "InvalidIntents"; + GatewayCloseEventCodes[GatewayCloseEventCodes["DisallowedIntents"] = 4014] = "DisallowedIntents"; +})(GatewayCloseEventCodes || (GatewayCloseEventCodes = {})); +var InviteTargetTypes; +(function(InviteTargetTypes) { + InviteTargetTypes[InviteTargetTypes["Stream"] = 1] = "Stream"; + InviteTargetTypes[InviteTargetTypes["EmbeddedApplication"] = 2] = "EmbeddedApplication"; +})(InviteTargetTypes || (InviteTargetTypes = {})); +var GatewayOpcodes; +(function(GatewayOpcodes) { + GatewayOpcodes[GatewayOpcodes["Dispatch"] = 0] = "Dispatch"; + GatewayOpcodes[GatewayOpcodes["Heartbeat"] = 1] = "Heartbeat"; + GatewayOpcodes[GatewayOpcodes["Identify"] = 2] = "Identify"; + GatewayOpcodes[GatewayOpcodes["PresenceUpdate"] = 3] = "PresenceUpdate"; + GatewayOpcodes[GatewayOpcodes["VoiceStateUpdate"] = 4] = "VoiceStateUpdate"; + GatewayOpcodes[GatewayOpcodes["Resume"] = 6] = "Resume"; + GatewayOpcodes[GatewayOpcodes["Reconnect"] = 7] = "Reconnect"; + GatewayOpcodes[GatewayOpcodes["RequestGuildMembers"] = 8] = "RequestGuildMembers"; + GatewayOpcodes[GatewayOpcodes["InvalidSession"] = 9] = "InvalidSession"; + GatewayOpcodes[GatewayOpcodes["Hello"] = 10] = "Hello"; + GatewayOpcodes[GatewayOpcodes["HeartbeatACK"] = 11] = "HeartbeatACK"; +})(GatewayOpcodes || (GatewayOpcodes = {})); +var GatewayIntents; +(function(GatewayIntents) { + GatewayIntents[GatewayIntents["Guilds"] = 1] = "Guilds"; + GatewayIntents[GatewayIntents["GuildMembers"] = 2] = "GuildMembers"; + GatewayIntents[GatewayIntents["GuildBans"] = 4] = "GuildBans"; + GatewayIntents[GatewayIntents["GuildEmojis"] = 8] = "GuildEmojis"; + GatewayIntents[GatewayIntents["GuildIntegrations"] = 16] = "GuildIntegrations"; + GatewayIntents[GatewayIntents["GuildWebhooks"] = 32] = "GuildWebhooks"; + GatewayIntents[GatewayIntents["GuildInvites"] = 64] = "GuildInvites"; + GatewayIntents[GatewayIntents["GuildVoiceStates"] = 128] = "GuildVoiceStates"; + GatewayIntents[GatewayIntents["GuildPresences"] = 256] = "GuildPresences"; + GatewayIntents[GatewayIntents["GuildMessages"] = 512] = "GuildMessages"; + GatewayIntents[GatewayIntents["GuildMessageReactions"] = 1024] = "GuildMessageReactions"; + GatewayIntents[GatewayIntents["GuildMessageTyping"] = 2048] = "GuildMessageTyping"; + GatewayIntents[GatewayIntents["DirectMessages"] = 4096] = "DirectMessages"; + GatewayIntents[GatewayIntents["DirectMessageReactions"] = 8192] = "DirectMessageReactions"; + GatewayIntents[GatewayIntents["DirectMessageTyping"] = 16384] = "DirectMessageTyping"; + GatewayIntents[GatewayIntents["MessageContent"] = 32768] = "MessageContent"; + GatewayIntents[GatewayIntents["GuildScheduledEvents"] = 65536] = "GuildScheduledEvents"; + GatewayIntents[GatewayIntents["AutoModerationConfiguration"] = 1048576] = "AutoModerationConfiguration"; + GatewayIntents[GatewayIntents["AutoModerationExecution"] = 2097152] = "AutoModerationExecution"; +})(GatewayIntents || (GatewayIntents = {})); +var InteractionResponseTypes; +(function(InteractionResponseTypes) { + InteractionResponseTypes[InteractionResponseTypes["Pong"] = 1] = "Pong"; + InteractionResponseTypes[InteractionResponseTypes["ChannelMessageWithSource"] = 4] = "ChannelMessageWithSource"; + InteractionResponseTypes[InteractionResponseTypes["DeferredChannelMessageWithSource"] = 5] = "DeferredChannelMessageWithSource"; + InteractionResponseTypes[InteractionResponseTypes["DeferredUpdateMessage"] = 6] = "DeferredUpdateMessage"; + InteractionResponseTypes[InteractionResponseTypes["UpdateMessage"] = 7] = "UpdateMessage"; + InteractionResponseTypes[InteractionResponseTypes["ApplicationCommandAutocompleteResult"] = 8] = "ApplicationCommandAutocompleteResult"; + InteractionResponseTypes[InteractionResponseTypes["Modal"] = 9] = "Modal"; +})(InteractionResponseTypes || (InteractionResponseTypes = {})); +var Errors; +(function(Errors) { + Errors["BOTS_HIGHEST_ROLE_TOO_LOW"] = "BOTS_HIGHEST_ROLE_TOO_LOW"; + Errors["CHANNEL_NOT_FOUND"] = "CHANNEL_NOT_FOUND"; + Errors["CHANNEL_NOT_IN_GUILD"] = "CHANNEL_NOT_IN_GUILD"; + Errors["CHANNEL_NOT_TEXT_BASED"] = "CHANNEL_NOT_TEXT_BASED"; + Errors["CHANNEL_NOT_STAGE_VOICE"] = "CHANNEL_NOT_STAGE_VOICE"; + Errors["MESSAGE_MAX_LENGTH"] = "MESSAGE_MAX_LENGTH"; + Errors["RULES_CHANNEL_CANNOT_BE_DELETED"] = "RULES_CHANNEL_CANNOT_BE_DELETED"; + Errors["UPDATES_CHANNEL_CANNOT_BE_DELETED"] = "UPDATES_CHANNEL_CANNOT_BE_DELETED"; + Errors["INVALID_TOPIC_LENGTH"] = "INVALID_TOPIC_LENGTH"; + Errors["GUILD_NOT_DISCOVERABLE"] = "GUILD_NOT_DISCOVERABLE"; + Errors["GUILD_WIDGET_NOT_ENABLED"] = "GUILD_WIDGET_NOT_ENABLED"; + Errors["GUILD_NOT_FOUND"] = "GUILD_NOT_FOUND"; + Errors["MEMBER_NOT_FOUND"] = "MEMBER_NOT_FOUND"; + Errors["MEMBER_NOT_IN_VOICE_CHANNEL"] = "MEMBER_NOT_IN_VOICE_CHANNEL"; + Errors["MEMBER_SEARCH_LIMIT_TOO_HIGH"] = "MEMBER_SEARCH_LIMIT_TOO_HIGH"; + Errors["MEMBER_SEARCH_LIMIT_TOO_LOW"] = "MEMBER_SEARCH_LIMIT_TOO_LOW"; + Errors["PRUNE_MAX_DAYS"] = "PRUNE_MAX_DAYS"; + Errors["ROLE_NOT_FOUND"] = "ROLE_NOT_FOUND"; + Errors["INVALID_THREAD_PARENT_CHANNEL_TYPE"] = "INVALID_THREAD_PARENT_CHANNEL_TYPE"; + Errors["GUILD_NEWS_CHANNEL_ONLY_SUPPORT_PUBLIC_THREADS"] = "GUILD_NEWS_CHANNEL_ONLY_SUPPORT_PUBLIC_THREADS"; + Errors["NOT_A_THREAD_CHANNEL"] = "NOT_A_THREAD_CHANNEL"; + Errors["MISSING_MANAGE_THREADS_AND_NOT_MEMBER"] = "MISSING_MANAGE_THREADS_AND_NOT_MEMBER"; + Errors["CANNOT_GET_MEMBERS_OF_AN_UNJOINED_PRIVATE_THREAD"] = "CANNOT_GET_MEMBERS_OF_AN_UNJOINED_PRIVATE_THREAD"; + Errors["HAVE_TO_BE_THE_CREATOR_OF_THE_THREAD_OR_HAVE_MANAGE_THREADS_TO_REMOVE_MEMBERS"] = "HAVE_TO_BE_THE_CREATOR_OF_THE_THREAD_OR_HAVE_MANAGE_THREADS_TO_REMOVE_MEMBERS"; + Errors["INVALID_GET_MESSAGES_LIMIT"] = "INVALID_GET_MESSAGES_LIMIT"; + Errors["DELETE_MESSAGES_MIN"] = "DELETE_MESSAGES_MIN"; + Errors["PRUNE_MIN_DAYS"] = "PRUNE_MIN_DAYS"; + Errors["INVALID_SLASH_DESCRIPTION"] = "INVALID_SLASH_DESCRIPTION"; + Errors["INVALID_SLASH_NAME"] = "INVALID_SLASH_NAME"; + Errors["INVALID_SLASH_OPTIONS"] = "INVALID_SLASH_OPTIONS"; + Errors["INVALID_SLASH_OPTIONS_CHOICES"] = "INVALID_SLASH_OPTIONS_CHOICES"; + Errors["TOO_MANY_SLASH_OPTIONS"] = "TOO_MANY_SLASH_OPTIONS"; + Errors["INVALID_SLASH_OPTION_CHOICE_NAME"] = "INVALID_SLASH_OPTION_CHOICE_NAME"; + Errors["INVALID_SLASH_OPTIONS_CHOICE_VALUE_TYPE"] = "INVALID_SLASH_OPTIONS_CHOICE_VALUE_TYPE"; + Errors["TOO_MANY_SLASH_OPTION_CHOICES"] = "TOO_MANY_SLASH_OPTION_CHOICES"; + Errors["ONLY_STRING_OR_INTEGER_OPTIONS_CAN_HAVE_CHOICES"] = "ONLY_STRING_OR_INTEGER_OPTIONS_CAN_HAVE_CHOICES"; + Errors["INVALID_SLASH_OPTION_NAME"] = "INVALID_SLASH_OPTION_NAME"; + Errors["INVALID_SLASH_OPTION_DESCRIPTION"] = "INVALID_SLASH_OPTION_DESCRIPTION"; + Errors["INVALID_CONTEXT_MENU_COMMAND_NAME"] = "INVALID_CONTEXT_MENU_COMMAND_NAME"; + Errors["INVALID_CONTEXT_MENU_COMMAND_DESCRIPTION"] = "INVALID_CONTEXT_MENU_COMMAND_DESCRIPTION"; + Errors["INVALID_WEBHOOK_NAME"] = "INVALID_WEBHOOK_NAME"; + Errors["INVALID_WEBHOOK_OPTIONS"] = "INVALID_WEBHOOK_OPTIONS"; + Errors["MISSING_ADD_REACTIONS"] = "MISSING_ADD_REACTIONS"; + Errors["MISSING_ADMINISTRATOR"] = "MISSING_ADMINISTRATOR"; + Errors["MISSING_ATTACH_FILES"] = "MISSING_ATTACH_FILES"; + Errors["MISSING_BAN_MEMBERS"] = "MISSING_BAN_MEMBERS"; + Errors["MISSING_CHANGE_NICKNAME"] = "MISSING_CHANGE_NICKNAME"; + Errors["MISSING_CONNECT"] = "MISSING_CONNECT"; + Errors["MISSING_CREATE_INSTANT_INVITE"] = "MISSING_CREATE_INSTANT_INVITE"; + Errors["MISSING_DEAFEN_MEMBERS"] = "MISSING_DEAFEN_MEMBERS"; + Errors["MISSING_EMBED_LINKS"] = "MISSING_EMBED_LINKS"; + Errors["MISSING_INTENT_GUILD_MEMBERS"] = "MISSING_INTENT_GUILD_MEMBERS"; + Errors["MISSING_KICK_MEMBERS"] = "MISSING_KICK_MEMBERS"; + Errors["MISSING_MANAGE_CHANNELS"] = "MISSING_MANAGE_CHANNELS"; + Errors["MISSING_MANAGE_EMOJIS"] = "MISSING_MANAGE_EMOJIS"; + Errors["MISSING_MANAGE_GUILD"] = "MISSING_MANAGE_GUILD"; + Errors["MISSING_MANAGE_MESSAGES"] = "MISSING_MANAGE_MESSAGES"; + Errors["MISSING_MANAGE_NICKNAMES"] = "MISSING_MANAGE_NICKNAMES"; + Errors["MISSING_MANAGE_ROLES"] = "MISSING_MANAGE_ROLES"; + Errors["MISSING_MANAGE_WEBHOOKS"] = "MISSING_MANAGE_WEBHOOKS"; + Errors["MISSING_MENTION_EVERYONE"] = "MISSING_MENTION_EVERYONE"; + Errors["MISSING_MOVE_MEMBERS"] = "MISSING_MOVE_MEMBERS"; + Errors["MISSING_MUTE_MEMBERS"] = "MISSING_MUTE_MEMBERS"; + Errors["MISSING_PRIORITY_SPEAKER"] = "MISSING_PRIORITY_SPEAKER"; + Errors["MISSING_READ_MESSAGE_HISTORY"] = "MISSING_READ_MESSAGE_HISTORY"; + Errors["MISSING_SEND_MESSAGES"] = "MISSING_SEND_MESSAGES"; + Errors["MISSING_SEND_TTS_MESSAGES"] = "MISSING_SEND_TTS_MESSAGES"; + Errors["MISSING_SPEAK"] = "MISSING_SPEAK"; + Errors["MISSING_STREAM"] = "MISSING_STREAM"; + Errors["MISSING_USE_VAD"] = "MISSING_USE_VAD"; + Errors["MISSING_USE_EXTERNAL_EMOJIS"] = "MISSING_USE_EXTERNAL_EMOJIS"; + Errors["MISSING_VIEW_AUDIT_LOG"] = "MISSING_VIEW_AUDIT_LOG"; + Errors["MISSING_VIEW_CHANNEL"] = "MISSING_VIEW_CHANNEL"; + Errors["MISSING_VIEW_GUILD_INSIGHTS"] = "MISSING_VIEW_GUILD_INSIGHTS"; + Errors["NICKNAMES_MAX_LENGTH"] = "NICKNAMES_MAX_LENGTH"; + Errors["USERNAME_INVALID_CHARACTER"] = "USERNAME_INVALID_CHARACTER"; + Errors["USERNAME_INVALID_USERNAME"] = "USERNAME_INVALID_USERNAME"; + Errors["USERNAME_MAX_LENGTH"] = "USERNAME_MAX_LENGTH"; + Errors["USERNAME_MIN_LENGTH"] = "USERNAME_MIN_LENGTH"; + Errors["NONCE_TOO_LONG"] = "NONCE_TOO_LONG"; + Errors["INVITE_MAX_AGE_INVALID"] = "INVITE_MAX_AGE_INVALID"; + Errors["INVITE_MAX_USES_INVALID"] = "INVITE_MAX_USES_INVALID"; + Errors["RATE_LIMIT_RETRY_MAXED"] = "RATE_LIMIT_RETRY_MAXED"; + Errors["REQUEST_CLIENT_ERROR"] = "REQUEST_CLIENT_ERROR"; + Errors["REQUEST_SERVER_ERROR"] = "REQUEST_SERVER_ERROR"; + Errors["REQUEST_UNKNOWN_ERROR"] = "REQUEST_UNKNOWN_ERROR"; + Errors["TOO_MANY_COMPONENTS"] = "TOO_MANY_COMPONENTS"; + Errors["TOO_MANY_ACTION_ROWS"] = "TOO_MANY_ACTION_ROWS"; + Errors["LINK_BUTTON_CANNOT_HAVE_CUSTOM_ID"] = "LINK_BUTTON_CANNOT_HAVE_CUSTOM_ID"; + Errors["COMPONENT_LABEL_TOO_BIG"] = "COMPONENT_LABEL_TOO_BIG"; + Errors["COMPONENT_CUSTOM_ID_TOO_BIG"] = "COMPONENT_CUSTOM_ID_TOO_BIG"; + Errors["BUTTON_REQUIRES_CUSTOM_ID"] = "BUTTON_REQUIRES_CUSTOM_ID"; + Errors["COMPONENT_SELECT_MUST_BE_ALONE"] = "COMPONENT_SELECT_MUST_BE_ALONE"; + Errors["COMPONENT_PLACEHOLDER_TOO_BIG"] = "COMPONENT_PLACEHOLDER_TOO_BIG"; + Errors["COMPONENT_SELECT_MIN_VALUE_TOO_LOW"] = "COMPONENT_SELECT_MIN_VALUE_TOO_LOW"; + Errors["COMPONENT_SELECT_MIN_VALUE_TOO_MANY"] = "COMPONENT_SELECT_MIN_VALUE_TOO_MANY"; + Errors["COMPONENT_SELECT_MAX_VALUE_TOO_LOW"] = "COMPONENT_SELECT_MAX_VALUE_TOO_LOW"; + Errors["COMPONENT_SELECT_MAX_VALUE_TOO_MANY"] = "COMPONENT_SELECT_MAX_VALUE_TOO_MANY"; + Errors["COMPONENT_SELECT_OPTIONS_TOO_LOW"] = "COMPONENT_SELECT_OPTIONS_TOO_LOW"; + Errors["COMPONENT_SELECT_OPTIONS_TOO_MANY"] = "COMPONENT_SELECT_OPTIONS_TOO_MANY"; + Errors["SELECT_OPTION_LABEL_TOO_BIG"] = "SELECT_OPTION_LABEL_TOO_BIG"; + Errors["SELECT_OPTION_VALUE_TOO_BIG"] = "SELECT_OPTION_VALUE_TOO_BIG"; + Errors["SELECT_OPTION_TOO_MANY_DEFAULTS"] = "SELECT_OPTION_TOO_MANY_DEFAULTS"; + Errors["COMPONENT_SELECT_MIN_HIGHER_THAN_MAX"] = "COMPONENT_SELECT_MIN_HIGHER_THAN_MAX"; + Errors["CANNOT_ADD_USER_TO_ARCHIVED_THREADS"] = "CANNOT_ADD_USER_TO_ARCHIVED_THREADS"; + Errors["CANNOT_LEAVE_ARCHIVED_THREAD"] = "CANNOT_LEAVE_ARCHIVED_THREAD"; + Errors["CANNOT_REMOVE_FROM_ARCHIVED_THREAD"] = "CANNOT_REMOVE_FROM_ARCHIVED_THREAD"; + Errors["YOU_CAN_NOT_DM_THE_BOT_ITSELF"] = "YOU_CAN_NOT_DM_THE_BOT_ITSELF"; +})(Errors || (Errors = {})); +var Locales; +(function(Locales) { + Locales["Danish"] = "da"; + Locales["German"] = "de"; + Locales["EnglishUk"] = "en-GB"; + Locales["EnglishUs"] = "en-US"; + Locales["Spanish"] = "es-ES"; + Locales["French"] = "fr"; + Locales["Croatian"] = "hr"; + Locales["Italian"] = "it"; + Locales["Lithuanian"] = "lt"; + Locales["Hungarian"] = "hu"; + Locales["Dutch"] = "nl"; + Locales["Norwegian"] = "no"; + Locales["Polish"] = "pl"; + Locales["PortugueseBrazilian"] = "pt-BR"; + Locales["RomanianRomania"] = "ro"; + Locales["Finnish"] = "fi"; + Locales["Swedish"] = "sv-SE"; + Locales["Vietnamese"] = "vi"; + Locales["Turkish"] = "tr"; + Locales["Czech"] = "cs"; + Locales["Greek"] = "el"; + Locales["Bulgarian"] = "bg"; + Locales["Russian"] = "ru"; + Locales["Ukrainian"] = "uk"; + Locales["Hindi"] = "hi"; + Locales["Thai"] = "th"; + Locales["ChineseChina"] = "zh-CN"; + Locales["Japanese"] = "ja"; + Locales["ChineseTaiwan"] = "zh-TW"; + Locales["Korean"] = "ko"; +})(Locales || (Locales = {})); +const GATEWAY_RATE_LIMIT_RESET_INTERVAL = 60_000; +var ShardState; +(function(ShardState) { + ShardState[ShardState["Connected"] = 0] = "Connected"; + ShardState[ShardState["Connecting"] = 1] = "Connecting"; + ShardState[ShardState["Disconnected"] = 2] = "Disconnected"; + ShardState[ShardState["Unidentified"] = 3] = "Unidentified"; + ShardState[ShardState["Identifying"] = 4] = "Identifying"; + ShardState[ShardState["Resuming"] = 5] = "Resuming"; + ShardState[ShardState["Offline"] = 6] = "Offline"; +})(ShardState || (ShardState = {})); +var ShardSocketCloseCodes; +(function(ShardSocketCloseCodes) { + ShardSocketCloseCodes[ShardSocketCloseCodes["Shutdown"] = 3000] = "Shutdown"; + ShardSocketCloseCodes[ShardSocketCloseCodes["ResumeClosingOldConnection"] = 3024] = "ResumeClosingOldConnection"; + ShardSocketCloseCodes[ShardSocketCloseCodes["ZombiedConnection"] = 3010] = "ZombiedConnection"; + ShardSocketCloseCodes[ShardSocketCloseCodes["TestingFinished"] = 3064] = "TestingFinished"; + ShardSocketCloseCodes[ShardSocketCloseCodes["Resharded"] = 3065] = "Resharded"; + ShardSocketCloseCodes[ShardSocketCloseCodes["ReIdentifying"] = 3066] = "ReIdentifying"; +})(ShardSocketCloseCodes || (ShardSocketCloseCodes = {})); +async function identify(shard) { + if (shard.state === ShardState.Connected) { + shard.close(ShardSocketCloseCodes.ReIdentifying, "Re-identifying closure of old connection."); + } + shard.state = ShardState.Identifying; + shard.events.identifying?.(shard); + if (!shard.isOpen()) { + await shard.connect(); + } + await shard.requestIdentify(); + shard.send({ + op: GatewayOpcodes.Identify, + d: { + token: `Bot ${shard.gatewayConfig.token}`, + compress: shard.gatewayConfig.compress, + properties: shard.gatewayConfig.properties, + intents: shard.gatewayConfig.intents, + shard: [ + shard.id, + shard.totalShards + ], + presence: await shard.makePresence?.(shard.id) + } + }, true); + return new Promise((resolve)=>{ + shard.resolves.set("READY", ()=>{ + shard.events.identified?.(shard); + resolve(); + }); + shard.resolves.set("INVALID_SESSION", ()=>{ + shard.resolves.delete("READY"); + resolve(); + }); + }); +} +const BTYPE = Object.freeze({ + UNCOMPRESSED: 0, + FIXED: 1, + DYNAMIC: 2 +}); +const LENGTH_EXTRA_BIT_LEN = [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 2, + 2, + 2, + 2, + 3, + 3, + 3, + 3, + 4, + 4, + 4, + 4, + 5, + 5, + 5, + 5, + 0, +]; +const LENGTH_EXTRA_BIT_BASE = [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 13, + 15, + 17, + 19, + 23, + 27, + 31, + 35, + 43, + 51, + 59, + 67, + 83, + 99, + 115, + 131, + 163, + 195, + 227, + 258, +]; +const DISTANCE_EXTRA_BIT_BASE = [ + 1, + 2, + 3, + 4, + 5, + 7, + 9, + 13, + 17, + 25, + 33, + 49, + 65, + 97, + 129, + 193, + 257, + 385, + 513, + 769, + 1025, + 1537, + 2049, + 3073, + 4097, + 6145, + 8193, + 12289, + 16385, + 24577, +]; +const DISTANCE_EXTRA_BIT_LEN = [ + 0, + 0, + 0, + 0, + 1, + 1, + 2, + 2, + 3, + 3, + 4, + 4, + 5, + 5, + 6, + 6, + 7, + 7, + 8, + 8, + 9, + 9, + 10, + 10, + 11, + 11, + 12, + 12, + 13, + 13, +]; +const CODELEN_VALUES = [ + 16, + 17, + 18, + 0, + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, +]; +function generateHuffmanTable(codelenValues) { + const codelens = Object.keys(codelenValues); + let codelen = 0; + let codelenMax = 0; + let codelenMin = Number.MAX_SAFE_INTEGER; + codelens.forEach((key)=>{ + codelen = Number(key); + if (codelenMax < codelen) codelenMax = codelen; + if (codelenMin > codelen) codelenMin = codelen; + }); + let code = 0; + let values; + const bitlenTables = {}; + for(let bitlen = codelenMin; bitlen <= codelenMax; bitlen++){ + values = codelenValues[bitlen]; + if (values === undefined) values = []; + values.sort((a, b)=>{ + if (a < b) return -1; + if (a > b) return 1; + return 0; + }); + const table = {}; + values.forEach((value)=>{ + table[code] = value; + code++; + }); + bitlenTables[bitlen] = table; + code <<= 1; + } + return bitlenTables; +} +function makeFixedHuffmanCodelenValues() { + const codelenValues = {}; + codelenValues[7] = []; + codelenValues[8] = []; + codelenValues[9] = []; + for(let i = 0; i <= 287; i++){ + i <= 143 ? codelenValues[8].push(i) : i <= 255 ? codelenValues[9].push(i) : i <= 279 ? codelenValues[7].push(i) : codelenValues[8].push(i); + } + return codelenValues; +} +class BitReadStream { + buffer; + bufferIndex; + nowBits; + nowBitsLength = 0; + isEnd = false; + constructor(buffer, offset = 0){ + this.buffer = buffer; + this.bufferIndex = offset; + this.nowBits = buffer[offset]; + this.nowBitsLength = 8; + } + read() { + if (this.isEnd) throw new Error("Lack of data length"); + const bit = this.nowBits & 1; + if (this.nowBitsLength > 1) { + this.nowBitsLength--; + this.nowBits >>= 1; + } else { + this.bufferIndex++; + if (this.bufferIndex < this.buffer.length) { + this.nowBits = this.buffer[this.bufferIndex]; + this.nowBitsLength = 8; + } else { + this.nowBitsLength = 0; + this.isEnd = true; + } + } + return bit; + } + readRange(length) { + while(this.nowBitsLength <= length){ + this.nowBits |= this.buffer[++this.bufferIndex] << this.nowBitsLength; + this.nowBitsLength += 8; + } + const bits = this.nowBits & (1 << length) - 1; + this.nowBits >>>= length; + this.nowBitsLength -= length; + return bits; + } + readRangeCoded(length) { + let bits = 0; + for(let i = 0; i < length; i++){ + bits <<= 1; + bits |= this.read(); + } + return bits; + } +} +class Uint8WriteStream { + index = 0; + buffer; + length; + _extendedSize; + constructor(extendedSize){ + this.buffer = new Uint8Array(extendedSize); + this.length = extendedSize; + this._extendedSize = extendedSize; + } + write(value) { + if (this.length <= this.index) { + this.length += this._extendedSize; + const newBuffer = new Uint8Array(this.length); + const nowSize = this.buffer.length; + for(let i = 0; i < nowSize; i++){ + newBuffer[i] = this.buffer[i]; + } + this.buffer = newBuffer; + } + this.buffer[this.index] = value; + this.index++; + } +} +const FIXED_HUFFMAN_TABLE = generateHuffmanTable(makeFixedHuffmanCodelenValues()); +function inflate(input, offset = 0) { + const buffer = new Uint8WriteStream(input.length * 10); + const stream = new BitReadStream(input, offset); + let bFinal = 0; + let bType = 0; + while(bFinal !== 1){ + bFinal = stream.readRange(1); + bType = stream.readRange(2); + if (bType === BTYPE.UNCOMPRESSED) { + inflateUncompressedBlock(stream, buffer); + } else if (bType === BTYPE.FIXED) { + inflateFixedBlock(stream, buffer); + } else if (bType === BTYPE.DYNAMIC) { + inflateDynamicBlock(stream, buffer); + } else { + throw new Error("Not supported BTYPE : " + bType); + } + if (bFinal === 0 && stream.isEnd) { + throw new Error("Data length is insufficient"); + } + } + return buffer.buffer.subarray(0, buffer.index); +} +function inflateUncompressedBlock(stream, buffer) { + if (stream.nowBitsLength < 8) { + stream.readRange(stream.nowBitsLength); + } + const LEN = stream.readRange(8) | stream.readRange(8) << 8; + const NLEN = stream.readRange(8) | stream.readRange(8) << 8; + if (LEN + NLEN !== 65535) { + throw new Error("Data is corrupted"); + } + for(let i = 0; i < LEN; i++){ + buffer.write(stream.readRange(8)); + } +} +function inflateFixedBlock(stream, buffer) { + const tables = FIXED_HUFFMAN_TABLE; + const codelens = Object.keys(tables); + let codelen = 0; + let codelenMax = 0; + let codelenMin = Number.MAX_SAFE_INTEGER; + codelens.forEach((key)=>{ + codelen = Number(key); + if (codelenMax < codelen) codelenMax = codelen; + if (codelenMin > codelen) codelenMin = codelen; + }); + let code = 0; + let value; + let repeatLengthCode; + let repeatLengthValue; + let repeatLengthExt; + let repeatDistanceCode; + let repeatDistanceValue; + let repeatDistanceExt; + let repeatStartIndex; + while(!stream.isEnd){ + value = undefined; + codelen = codelenMin; + code = stream.readRangeCoded(codelenMin); + while(true){ + value = tables[codelen][code]; + if (value !== undefined) { + break; + } + if (codelenMax <= codelen) { + throw new Error("Data is corrupted"); + } + codelen++; + code <<= 1; + code |= stream.read(); + } + if (value < 256) { + buffer.write(value); + continue; + } + if (value === 256) { + break; + } + repeatLengthCode = value - 257; + repeatLengthValue = LENGTH_EXTRA_BIT_BASE[repeatLengthCode]; + repeatLengthExt = LENGTH_EXTRA_BIT_LEN[repeatLengthCode]; + if (0 < repeatLengthExt) { + repeatLengthValue += stream.readRange(repeatLengthExt); + } + repeatDistanceCode = stream.readRangeCoded(5); + repeatDistanceValue = DISTANCE_EXTRA_BIT_BASE[repeatDistanceCode]; + repeatDistanceExt = DISTANCE_EXTRA_BIT_LEN[repeatDistanceCode]; + if (0 < repeatDistanceExt) { + repeatDistanceValue += stream.readRange(repeatDistanceExt); + } + repeatStartIndex = buffer.index - repeatDistanceValue; + for(let i = 0; i < repeatLengthValue; i++){ + buffer.write(buffer.buffer[repeatStartIndex + i]); + } + } +} +function inflateDynamicBlock(stream, buffer) { + const HLIT = stream.readRange(5) + 257; + const HDIST = stream.readRange(5) + 1; + const HCLEN = stream.readRange(4) + 4; + let codelenCodelen = 0; + const codelenCodelenValues = {}; + for(let i = 0; i < HCLEN; i++){ + codelenCodelen = stream.readRange(3); + if (codelenCodelen === 0) { + continue; + } + if (!codelenCodelenValues[codelenCodelen]) { + codelenCodelenValues[codelenCodelen] = []; + } + codelenCodelenValues[codelenCodelen].push(CODELEN_VALUES[i]); + } + const codelenHuffmanTables = generateHuffmanTable(codelenCodelenValues); + const codelenCodelens = Object.keys(codelenHuffmanTables); + let codelenCodelenMax = 0; + let codelenCodelenMin = Number.MAX_SAFE_INTEGER; + codelenCodelens.forEach((key)=>{ + codelenCodelen = Number(key); + if (codelenCodelenMax < codelenCodelen) codelenCodelenMax = codelenCodelen; + if (codelenCodelenMin > codelenCodelen) codelenCodelenMin = codelenCodelen; + }); + const dataCodelenValues = {}; + const distanceCodelenValues = {}; + let codelenCode = 0; + let runlengthCode; + let repeat = 0; + let codelen = 0; + const codesNumber = HLIT + HDIST; + for(let i1 = 0; i1 < codesNumber;){ + runlengthCode = undefined; + codelenCodelen = codelenCodelenMin; + codelenCode = stream.readRangeCoded(codelenCodelenMin); + while(true){ + runlengthCode = codelenHuffmanTables[codelenCodelen][codelenCode]; + if (runlengthCode !== undefined) { + break; + } + if (codelenCodelenMax <= codelenCodelen) { + throw new Error("Data is corrupted"); + } + codelenCodelen++; + codelenCode <<= 1; + codelenCode |= stream.read(); + } + if (runlengthCode === 16) { + repeat = 3 + stream.readRange(2); + } else if (runlengthCode === 17) { + repeat = 3 + stream.readRange(3); + codelen = 0; + } else if (runlengthCode === 18) { + repeat = 11 + stream.readRange(7); + codelen = 0; + } else { + repeat = 1; + codelen = runlengthCode; + } + if (codelen <= 0) { + i1 += repeat; + } else { + while(repeat){ + if (i1 < HLIT) { + if (!dataCodelenValues[codelen]) { + dataCodelenValues[codelen] = []; + } + dataCodelenValues[codelen].push(i1++); + } else { + if (!distanceCodelenValues[codelen]) { + distanceCodelenValues[codelen] = []; + } + distanceCodelenValues[codelen].push((i1++) - HLIT); + } + repeat--; + } + } + } + const dataHuffmanTables = generateHuffmanTable(dataCodelenValues); + const distanceHuffmanTables = generateHuffmanTable(distanceCodelenValues); + const dataCodelens = Object.keys(dataHuffmanTables); + let dataCodelen = 0; + let dataCodelenMax = 0; + let dataCodelenMin = Number.MAX_SAFE_INTEGER; + dataCodelens.forEach((key)=>{ + dataCodelen = Number(key); + if (dataCodelenMax < dataCodelen) dataCodelenMax = dataCodelen; + if (dataCodelenMin > dataCodelen) dataCodelenMin = dataCodelen; + }); + const distanceCodelens = Object.keys(distanceHuffmanTables); + let distanceCodelen = 0; + let distanceCodelenMax = 0; + let distanceCodelenMin = Number.MAX_SAFE_INTEGER; + distanceCodelens.forEach((key)=>{ + distanceCodelen = Number(key); + if (distanceCodelenMax < distanceCodelen) { + distanceCodelenMax = distanceCodelen; + } + if (distanceCodelenMin > distanceCodelen) { + distanceCodelenMin = distanceCodelen; + } + }); + let dataCode = 0; + let data; + let repeatLengthCode; + let repeatLengthValue; + let repeatLengthExt; + let repeatDistanceCode; + let repeatDistanceValue; + let repeatDistanceExt; + let repeatDistanceCodeCodelen; + let repeatDistanceCodeCode; + let repeatStartIndex; + while(!stream.isEnd){ + data = undefined; + dataCodelen = dataCodelenMin; + dataCode = stream.readRangeCoded(dataCodelenMin); + while(true){ + data = dataHuffmanTables[dataCodelen][dataCode]; + if (data !== undefined) { + break; + } + if (dataCodelenMax <= dataCodelen) { + throw new Error("Data is corrupted"); + } + dataCodelen++; + dataCode <<= 1; + dataCode |= stream.read(); + } + if (data < 256) { + buffer.write(data); + continue; + } + if (data === 256) { + break; + } + repeatLengthCode = data - 257; + repeatLengthValue = LENGTH_EXTRA_BIT_BASE[repeatLengthCode]; + repeatLengthExt = LENGTH_EXTRA_BIT_LEN[repeatLengthCode]; + if (0 < repeatLengthExt) { + repeatLengthValue += stream.readRange(repeatLengthExt); + } + repeatDistanceCode = undefined; + repeatDistanceCodeCodelen = distanceCodelenMin; + repeatDistanceCodeCode = stream.readRangeCoded(distanceCodelenMin); + while(true){ + repeatDistanceCode = distanceHuffmanTables[repeatDistanceCodeCodelen][repeatDistanceCodeCode]; + if (repeatDistanceCode !== undefined) { + break; + } + if (distanceCodelenMax <= repeatDistanceCodeCodelen) { + throw new Error("Data is corrupted"); + } + repeatDistanceCodeCodelen++; + repeatDistanceCodeCode <<= 1; + repeatDistanceCodeCode |= stream.read(); + } + repeatDistanceValue = DISTANCE_EXTRA_BIT_BASE[repeatDistanceCode]; + repeatDistanceExt = DISTANCE_EXTRA_BIT_LEN[repeatDistanceCode]; + if (0 < repeatDistanceExt) { + repeatDistanceValue += stream.readRange(repeatDistanceExt); + } + repeatStartIndex = buffer.index - repeatDistanceValue; + for(let i2 = 0; i2 < repeatLengthValue; i2++){ + buffer.write(buffer.buffer[repeatStartIndex + i2]); + } + } +} +function inflate1(input) { + const stream = new BitReadStream(input); + const CM = stream.readRange(4); + if (CM !== 8) { + throw new Error("Not compressed by deflate"); + } + stream.readRange(4); + stream.readRange(5); + stream.readRange(1); + stream.readRange(2); + return inflate(input, 2); +} +const decoder = new TextDecoder(); +async function handleMessage(shard, message_) { + let message = message_.data; + if (shard.gatewayConfig.compress && message instanceof Blob) { + message = decoder.decode(inflate1(new Uint8Array(await message.arrayBuffer()))); + } + if (typeof message !== "string") return; + const messageData = JSON.parse(message); + switch(messageData.op){ + case GatewayOpcodes.Heartbeat: + { + if (!shard.isOpen()) return; + shard.heart.lastBeat = Date.now(); + shard.socket?.send(JSON.stringify({ + op: GatewayOpcodes.Heartbeat, + d: shard.previousSequenceNumber + })); + shard.events.heartbeat?.(shard); + break; + } + case GatewayOpcodes.Hello: + { + const interval = messageData.d.heartbeat_interval; + shard.startHeartbeating(interval); + if (shard.state !== ShardState.Resuming) { + shard.bucket = createLeakyBucket({ + max: shard.calculateSafeRequests(), + refillInterval: GATEWAY_RATE_LIMIT_RESET_INTERVAL, + refillAmount: shard.calculateSafeRequests(), + waiting: shard.bucket.waiting + }); + } + shard.events.hello?.(shard); + break; + } + case GatewayOpcodes.HeartbeatACK: + { + shard.heart.acknowledged = true; + shard.heart.lastAck = Date.now(); + if (shard.heart.lastBeat) { + shard.heart.rtt = shard.heart.lastAck - shard.heart.lastBeat; + } + shard.events.heartbeatAck?.(shard); + break; + } + case GatewayOpcodes.Reconnect: + { + shard.events.requestedReconnect?.(shard); + await shard.resume(); + break; + } + case GatewayOpcodes.InvalidSession: + { + const resumable = messageData.d; + shard.events.invalidSession?.(shard, resumable); + await delay(Math.floor((Math.random() * 4 + 1) * 1000)); + shard.resolves.get("INVALID_SESSION")?.(messageData); + shard.resolves.delete("INVALID_SESSION"); + if (!resumable) { + await shard.identify(); + break; + } + await shard.resume(); + break; + } + } + if (messageData.t === "RESUMED") { + shard.state = ShardState.Connected; + shard.events.resumed?.(shard); + shard.offlineSendQueue.map((resolve)=>resolve()); + shard.resolves.get("RESUMED")?.(messageData); + shard.resolves.delete("RESUMED"); + } else if (messageData.t === "READY") { + const payload = messageData.d; + shard.sessionId = payload.session_id; + shard.state = ShardState.Connected; + shard.offlineSendQueue.map((resolve)=>resolve()); + shard.resolves.get("READY")?.(messageData); + shard.resolves.delete("READY"); + } + if (messageData.s !== null) { + shard.previousSequenceNumber = messageData.s; + } + shard.events.message?.(shard, messageData); +} +function startHeartbeating(shard, interval) { + shard.heart.interval = interval; + if ([ + ShardState.Disconnected, + ShardState.Offline + ].includes(shard.state)) { + shard.state = ShardState.Unidentified; + } + const jitter = Math.ceil(shard.heart.interval * (Math.random() || 0.5)); + shard.heart.timeoutId = setTimeout(()=>{ + shard.socket?.send(JSON.stringify({ + op: GatewayOpcodes.Heartbeat, + d: shard.previousSequenceNumber + })); + shard.heart.lastBeat = Date.now(); + shard.heart.acknowledged = false; + shard.heart.intervalId = setInterval(async ()=>{ + if (!shard.heart.acknowledged) { + shard.close(ShardSocketCloseCodes.ZombiedConnection, "Zombied connection, did not receive an heartbeat ACK in time."); + return await shard.identify(); + } + shard.heart.acknowledged = false; + shard.socket?.send(JSON.stringify({ + op: GatewayOpcodes.Heartbeat, + d: shard.previousSequenceNumber + })); + shard.heart.lastBeat = Date.now(); + shard.events.heartbeat?.(shard); + }, shard.heart.interval); + }, jitter); +} +function stopHeartbeating(shard) { + clearInterval(shard.heart.intervalId); + clearTimeout(shard.heart.timeoutId); +} +async function resume(shard) { + if (shard.isOpen()) { + shard.close(ShardSocketCloseCodes.ResumeClosingOldConnection, "Reconnecting the shard, closing old connection."); + } + if (!shard.sessionId) { + return await shard.identify(); + } + shard.state = ShardState.Resuming; + await shard.connect(); + shard.send({ + op: GatewayOpcodes.Resume, + d: { + token: `Bot ${shard.gatewayConfig.token}`, + session_id: shard.sessionId, + seq: shard.previousSequenceNumber ?? 0 + } + }, true); + return new Promise((resolve)=>{ + shard.resolves.set("RESUMED", ()=>resolve()); + shard.resolves.set("INVALID_SESSION", ()=>{ + shard.resolves.delete("RESUMED"); + resolve(); + }); + }); +} +function calculateSafeRequests(shard) { + const safeRequests = shard.maxRequestsPerRateLimitTick - Math.ceil(shard.rateLimitResetInterval / shard.heart.interval) * 2; + return safeRequests < 0 ? 0 : safeRequests; +} +async function checkOffline(shard, highPriority) { + if (!shard.isOpen()) { + await new Promise((resolve)=>{ + if (highPriority) { + shard.offlineSendQueue.unshift(resolve); + } else { + shard.offlineSendQueue.push(resolve); + } + }); + } +} +async function send(shard, message, highPriority) { + await checkOffline(shard, highPriority); + await shard.bucket.acquire(1, highPriority); + await checkOffline(shard, highPriority); + shard.socket?.send(JSON.stringify(message)); +} +async function handleClose(shard, close) { + shard.stopHeartbeating(); + switch(close.code){ + case ShardSocketCloseCodes.TestingFinished: + { + shard.state = ShardState.Offline; + shard.events.disconnected?.(shard); + return; + } + case ShardSocketCloseCodes.Shutdown: + case ShardSocketCloseCodes.ReIdentifying: + case ShardSocketCloseCodes.Resharded: + case ShardSocketCloseCodes.ResumeClosingOldConnection: + case ShardSocketCloseCodes.ZombiedConnection: + { + shard.state = ShardState.Disconnected; + shard.events.disconnected?.(shard); + return; + } + case GatewayCloseEventCodes.UnknownOpcode: + case GatewayCloseEventCodes.NotAuthenticated: + case GatewayCloseEventCodes.InvalidSeq: + case GatewayCloseEventCodes.RateLimited: + case GatewayCloseEventCodes.SessionTimedOut: + { + shard.state = ShardState.Identifying; + shard.events.disconnected?.(shard); + return await shard.identify(); + } + case GatewayCloseEventCodes.AuthenticationFailed: + case GatewayCloseEventCodes.InvalidShard: + case GatewayCloseEventCodes.ShardingRequired: + case GatewayCloseEventCodes.InvalidApiVersion: + case GatewayCloseEventCodes.InvalidIntents: + case GatewayCloseEventCodes.DisallowedIntents: + { + shard.state = ShardState.Offline; + shard.events.disconnected?.(shard); + throw new Error(close.reason || "Discord gave no reason! GG! You broke Discord!"); + } + case GatewayCloseEventCodes.UnknownError: + case GatewayCloseEventCodes.DecodeError: + case GatewayCloseEventCodes.AlreadyAuthenticated: + default: + { + shard.state = ShardState.Resuming; + shard.events.disconnected?.(shard); + return await shard.resume(); + } + } +} +async function connect(shard) { + let gotHello = false; + if (![ + ShardState.Identifying, + ShardState.Resuming + ].includes(shard.state)) { + shard.state = ShardState.Connecting; + } + shard.events.connecting?.(shard); + const socket = new WebSocket(`${shard.gatewayConfig.url}/?v=${shard.gatewayConfig.version}&encoding=json`); + shard.socket = socket; + socket.onerror = (event)=>console.log({ + error: event + }); + socket.onclose = (event)=>shard.handleClose(event); + socket.onmessage = (message)=>{ + gotHello = true; + shard.handleMessage(message); + }; + return new Promise((resolve)=>{ + socket.onopen = ()=>{ + setTimeout(()=>{ + if (!gotHello) { + shard.handleMessage({ + data: JSON.stringify({ + t: null, + s: null, + op: 10, + d: { + heartbeat_interval: 41250 + } + }) + }); + } + }, 250); + if (![ + ShardState.Identifying, + ShardState.Resuming + ].includes(shard.state)) { + shard.state = ShardState.Unidentified; + } + shard.events.connected?.(shard); + resolve(); + }; + }); +} +function close(shard, code, reason) { + if (shard.socket?.readyState !== WebSocket.OPEN) return; + return shard.socket?.close(code, reason); +} +async function shutdown(shard) { + shard.close(ShardSocketCloseCodes.Shutdown, "Shard shutting down."); + shard.state = ShardState.Offline; +} +function isOpen(shard) { + return shard.socket?.readyState === WebSocket.OPEN; +} +const BASE_URL = "https://discord.com/api"; +const DISCORDENO_VERSION = "13.0.0-rc45"; +const USER_AGENT = `DiscordBot (https://github.com/discordeno/discordeno, v${DISCORDENO_VERSION})`; +const IMAGE_BASE_URL = "https://cdn.discordapp.com"; +const baseEndpoints = { + BASE_URL: `${BASE_URL}/v${10}`, + CDN_URL: IMAGE_BASE_URL +}; +function createShard(options) { + const calculateSafeRequestsOverwritten = options.calculateSafeRequests ?? calculateSafeRequests; + const closeOverwritten = options.close ?? close; + const connectOverwritten = options.connect ?? connect; + const identifyOverwritten = options.identify ?? identify; + const sendOverwritten = options.send ?? send; + const shutdownOverwritten = options.shutdown ?? shutdown; + const resumeOverwritten = options.resume ?? resume; + const handleCloseOverwritten = options.handleClose ?? handleClose; + const handleMessageOverwritten = options.handleMessage ?? handleMessage; + const isOpenOverwritten = options.isOpen ?? isOpen; + const startHeartbeatingOverwritten = options.startHeartbeating ?? startHeartbeating; + const stopHeartbeatingOverwritten = options.stopHeartbeating ?? stopHeartbeating; + return { + gatewayConfig: { + compress: options.gatewayConfig.compress ?? false, + intents: options.gatewayConfig.intents ?? 0, + properties: { + os: options.gatewayConfig?.properties?.os ?? "linux", + browser: options.gatewayConfig?.properties?.browser ?? "Discordeno", + device: options.gatewayConfig?.properties?.device ?? "Discordeno" + }, + token: options.gatewayConfig.token, + url: options.gatewayConfig.url ?? "wss://gateway.discord.gg", + version: options.gatewayConfig.version ?? 10 + }, + heart: { + acknowledged: false, + interval: 45000 + }, + id: options.id, + maxRequestsPerRateLimitTick: 120, + previousSequenceNumber: options.previousSequenceNumber || null, + rateLimitResetInterval: 60_000, + sessionId: undefined, + socket: undefined, + state: ShardState.Offline, + totalShards: options.totalShards, + events: options.events ?? {}, + calculateSafeRequests: function() { + return calculateSafeRequestsOverwritten(this); + }, + close: function(code, reason) { + return closeOverwritten(this, code, reason); + }, + connect: async function() { + return await connectOverwritten(this); + }, + identify: async function() { + return await identifyOverwritten(this); + }, + isOpen: function() { + return isOpenOverwritten(this); + }, + makePresence: options.makePresence, + resume: async function() { + return await resumeOverwritten(this); + }, + send: async function(message, highPriority = false) { + return await sendOverwritten(this, message, highPriority); + }, + shutdown: async function() { + return await shutdownOverwritten(this); + }, + bucket: createLeakyBucket({ + max: 120, + refillInterval: 60_000, + refillAmount: 120 + }), + handleClose: async function(close) { + return await handleCloseOverwritten(this, close); + }, + handleMessage: async function(message) { + return await handleMessageOverwritten(this, message); + }, + requestIdentify: async function() { + return await options.requestIdentify(this.id); + }, + offlineSendQueue: [], + resolves: new Map(), + startHeartbeating: function(interval) { + return startHeartbeatingOverwritten(this, interval); + }, + stopHeartbeating: function() { + return stopHeartbeatingOverwritten(this); + } + }; +} +function createShardManager(options) { + return { + createShardOptions: { + ...options.createShardOptions, + events: { + ...options.createShardOptions?.events, + message: options.createShardOptions?.events?.message ?? options.handleMessage + } + }, + gatewayConfig: options.gatewayConfig, + shards: new Map(options.shardIds.map((shardId)=>{ + const shard = createShard({ + ...options.createShardOptions, + id: shardId, + totalShards: options.totalShards, + gatewayConfig: options.gatewayConfig, + requestIdentify: async function() { + return await options.requestIdentify(shardId); + } + }); + return [ + shardId, + shard + ]; + })), + totalShards: options.totalShards, + identify: async function(shardId) { + let shard = this.shards.get(shardId); + if (!shard) { + shard = createShard({ + ...this.createShardOptions, + id: shardId, + totalShards: this.totalShards, + gatewayConfig: this.gatewayConfig, + requestIdentify: async function() { + return await options.requestIdentify(shardId); + } + }); + this.shards.set(shardId, shard); + } + return await shard.identify(); + }, + kill: async function(shardId) { + const shard = this.shards.get(shardId); + if (!shard) return; + this.shards.delete(shardId); + return await shard.shutdown(); + }, + requestIdentify: options.requestIdentify + }; +} +async function stop(gateway, code, reason) { + gateway.manager.shards.forEach((shard)=>shard.close(code, reason)); + await delay(5000); +} +function createGatewayManager(options) { + const prepareBucketsOverwritten = options.prepareBuckets ?? prepareBuckets; + const spawnShardsOverwritten = options.spawnShards ?? spawnShards; + const stopOverwritten = options.stop ?? stop; + const tellWorkerToIdentifyOverwritten = options.tellWorkerToIdentify ?? tellWorkerToIdentify; + const calculateTotalShardsOverwritten = options.calculateTotalShards ?? calculateTotalShards; + const calculateWorkerIdOverwritten = options.calculateWorkerId ?? calculateWorkerId; + const totalShards = (options.totalShards ?? options.gatewayBot.shards) ?? 1; + const gatewayManager = { + buckets: new Map(), + firstShardId: options.firstShardId ?? 0, + gatewayBot: options.gatewayBot, + lastShardId: (options.lastShardId ?? totalShards - 1) ?? 1, + manager: {}, + spawnShardDelay: options.spawnShardDelay ?? 5300, + shardsPerWorker: options.shardsPerWorker ?? 25, + totalWorkers: options.totalWorkers ?? 4, + prepareBuckets: function() { + return prepareBucketsOverwritten(this); + }, + spawnShards: function() { + return spawnShardsOverwritten(this); + }, + stop: function(code, reason) { + return stopOverwritten(this, code, reason); + }, + tellWorkerToIdentify: function(workerId, shardId, bucketId) { + return tellWorkerToIdentifyOverwritten(this, workerId, shardId, bucketId); + }, + debug: options.debug || function() {}, + calculateTotalShards: function() { + return calculateTotalShardsOverwritten(this); + }, + calculateWorkerId: function(shardId) { + return calculateWorkerIdOverwritten(this, shardId); + } + }; + gatewayManager.manager = createShardManager({ + createShardOptions: options.createShardOptions, + gatewayConfig: options.gatewayConfig, + shardIds: [], + totalShards, + handleMessage: function(shard, message) { + return options.handleDiscordPayload(shard, message); + }, + requestIdentify: async (shardId)=>{ + await gatewayManager.buckets.get(shardId % gatewayManager.gatewayBot.sessionStartLimit.maxConcurrency).leak.acquire(1); + } + }); + return gatewayManager; +} +function checkRateLimits(rest, url) { + const ratelimited = rest.rateLimitedPaths.get(url); + const global = rest.rateLimitedPaths.get("global"); + const now = Date.now(); + if (ratelimited && now < ratelimited.resetTimestamp) { + return ratelimited.resetTimestamp - now; + } + if (global && now < global.resetTimestamp) { + return global.resetTimestamp - now; + } + return false; +} +function cleanupQueues(rest) { + for (const [key, queue] of rest.pathQueues){ + rest.debug(`[REST - cleanupQueues] Running for of loop. ${key}`); + if (queue.requests.length) continue; + rest.pathQueues.delete(key); + } + if (!rest.pathQueues.size) rest.processingQueue = false; +} +function createRequestBody(rest, options) { + const headers = { + "user-agent": USER_AGENT + }; + if (!options.unauthorized) headers["authorization"] = `Bot ${rest.token}`; + if (options.headers) { + for(const key in options.headers){ + headers[key.toLowerCase()] = options.headers[key]; + } + } + if (options.method === "GET") { + options.body = undefined; + } + if (options.body?.reason) { + headers["X-Audit-Log-Reason"] = encodeURIComponent(options.body.reason); + options.body.reason = undefined; + } + if (options.body?.file) { + if (!Array.isArray(options.body.file)) { + options.body.file = [ + options.body.file + ]; + } + const form = new FormData(); + for(let i = 0; i < options.body.file.length; i++){ + form.append(`file${i}`, options.body.file[i].blob, options.body.file[i].name); + } + form.append("payload_json", JSON.stringify({ + ...options.body, + file: undefined + })); + options.body.file = form; + } else if (options.body && ![ + "GET", + "DELETE" + ].includes(options.method)) { + headers["Content-Type"] = "application/json"; + } + return { + headers, + body: options.body?.file ?? JSON.stringify(options.body), + method: options.method + }; +} +async function processGlobalQueue(rest) { + if (!rest.globalQueue.length) return; + if (rest.globalQueueProcessing) return; + rest.globalQueueProcessing = true; + while(rest.globalQueue.length){ + if (rest.globallyRateLimited) { + setTimeout(()=>{ + rest.debug(`[REST - processGlobalQueue] Globally rate limited, running setTimeout.`); + rest.processGlobalQueue(rest); + }, 1000); + break; + } + if (rest.invalidRequests === rest.maxInvalidRequests - rest.invalidRequestsSafetyAmount) { + setTimeout(()=>{ + const time = rest.invalidRequestsInterval - (Date.now() - rest.invalidRequestFrozenAt); + rest.debug(`[REST - processGlobalQueue] Freeze global queue because of invalid requests. Time Remaining: ${time / 1000} seconds.`); + rest.processGlobalQueue(rest); + }, 1000); + break; + } + const request = rest.globalQueue.shift(); + if (!request) continue; + const urlResetIn = rest.checkRateLimits(rest, request.basicURL); + const bucketResetIn = request.payload.bucketId ? rest.checkRateLimits(rest, request.payload.bucketId) : false; + if (urlResetIn || bucketResetIn) { + setTimeout(()=>{ + rest.debug(`[REST - processGlobalQueue] rate limited, running setTimeout.`); + rest.globalQueue.unshift(request); + rest.processGlobalQueue(rest); + }, urlResetIn || bucketResetIn); + continue; + } + await rest.sendRequest(rest, { + url: request.urlToUse, + method: request.request.method, + bucketId: request.payload.bucketId, + reject: request.request.reject, + respond: request.request.respond, + retryCount: request.payload.retryCount ?? 0, + payload: rest.createRequestBody(rest, { + method: request.request.method, + body: request.payload.body + }) + }).catch(()=>null); + } + rest.globalQueueProcessing = false; +} +function processQueue(rest, id) { + const queue = rest.pathQueues.get(id); + if (!queue) return; + while(queue.requests.length){ + rest.debug(`[REST - processQueue] Running while loop.`); + const queuedRequest = queue.requests[0]; + if (!queuedRequest) break; + const basicURL = rest.simplifyUrl(queuedRequest.request.url, queuedRequest.request.method); + const urlResetIn = rest.checkRateLimits(rest, basicURL); + if (urlResetIn) { + if (!queue.isWaiting) { + queue.isWaiting = true; + setTimeout(()=>{ + queue.isWaiting = false; + rest.debug(`[REST - processQueue] rate limited, running setTimeout.`); + rest.processQueue(rest, id); + }, urlResetIn); + } + break; + } + const bucketResetIn = queuedRequest.payload.bucketId ? rest.checkRateLimits(rest, queuedRequest.payload.bucketId) : false; + if (bucketResetIn) continue; + rest.debug(`[REST - Add To Global Queue] ${JSON.stringify(queuedRequest.payload)}`); + rest.globalQueue.push({ + ...queuedRequest, + urlToUse: queuedRequest.request.url, + basicURL + }); + rest.processGlobalQueue(rest); + queue.requests.shift(); + } + rest.cleanupQueues(rest); +} +function processRateLimitedPaths(rest) { + const now = Date.now(); + for (const [key, value] of rest.rateLimitedPaths.entries()){ + rest.debug(`[REST - processRateLimitedPaths] Running for of loop. ${value.resetTimestamp - now}`); + if (value.resetTimestamp > now) continue; + rest.rateLimitedPaths.delete(key); + if (key === "global") rest.globallyRateLimited = false; + } + if (!rest.rateLimitedPaths.size) { + rest.processingRateLimitedPaths = false; + } else { + rest.processingRateLimitedPaths = true; + setTimeout(()=>{ + rest.debug(`[REST - processRateLimitedPaths] Running setTimeout.`); + rest.processRateLimitedPaths(rest); + }, 1000); + } +} +function processRequest(rest, request, payload) { + const route = request.url.substring(request.url.indexOf("api/")); + const parts = route.split("/"); + parts.shift(); + if (parts[0]?.startsWith("v")) parts.shift(); + request.url = `${BASE_URL}/v${rest.version}/${parts.join("/")}`; + parts.shift(); + const url = rest.simplifyUrl(request.url, request.method); + const queue = rest.pathQueues.get(url); + if (queue) { + queue.requests.push({ + request, + payload + }); + } else { + rest.pathQueues.set(url, { + isWaiting: false, + requests: [ + { + request, + payload + }, + ] + }); + rest.processQueue(rest, url); + } +} +function processRequestHeaders(rest, url, headers) { + let rateLimited = false; + const remaining = headers.get("x-ratelimit-remaining"); + const retryAfter = headers.get("x-ratelimit-reset-after"); + const reset = Date.now() + Number(retryAfter) * 1000; + const global = headers.get("x-ratelimit-global"); + const bucketId = headers.get("x-ratelimit-bucket") || undefined; + if (remaining === "0") { + rateLimited = true; + rest.rateLimitedPaths.set(url, { + url, + resetTimestamp: reset, + bucketId + }); + if (bucketId) { + rest.rateLimitedPaths.set(bucketId, { + url, + resetTimestamp: reset, + bucketId + }); + } + } + if (global) { + const retryAfter1 = headers.get("retry-after"); + const globalReset = Date.now() + Number(retryAfter1) * 1000; + rest.debug(`[REST = Globally Rate Limited] URL: ${url} | Global Rest: ${globalReset}`); + rest.globallyRateLimited = true; + rateLimited = true; + rest.rateLimitedPaths.set("global", { + url: "global", + resetTimestamp: globalReset, + bucketId + }); + if (bucketId) { + rest.rateLimitedPaths.set(bucketId, { + url: "global", + resetTimestamp: globalReset, + bucketId + }); + } + } + if (rateLimited && !rest.processingRateLimitedPaths) { + rest.processRateLimitedPaths(rest); + } + return rateLimited ? bucketId : undefined; +} +function convertRestError(errorStack, data) { + errorStack.message = `[${data.status}] ${data.error}\n${data.body}`; + return errorStack; +} +async function runMethod(rest, method, route, body, options) { + rest.debug(`[REST - RequestCreate] Method: ${method} | URL: ${route} | Retry Count: ${options?.retryCount ?? 0} | Bucket ID: ${options?.bucketId} | Body: ${JSON.stringify(body)}`); + const errorStack = new Error("Location:"); + Error.captureStackTrace?.(errorStack); + if (!baseEndpoints.BASE_URL.startsWith(BASE_URL) && route[0] === "/") { + const result = await fetch(`${baseEndpoints.BASE_URL}${route}`, { + body: body ? JSON.stringify(body) : undefined, + headers: { + Authorization: rest.secretKey, + "Content-Type": "application/json" + }, + method + }).catch((error)=>{ + errorStack.message = error?.message; + console.error(error); + throw errorStack; + }); + if (!result.ok) { + errorStack.message = result.statusText; + rest.debug(`[ERROR] ${errorStack.message}`); + await result.text(); + throw errorStack; + } + return result.status !== 204 ? await result.json() : undefined; + } + return new Promise((resolve, reject)=>{ + rest.processRequest(rest, { + url: route[0] === "/" ? `${BASE_URL}/v${10}${route}` : route, + method, + reject: (data)=>{ + const restError = rest.convertRestError(errorStack, data); + reject(restError); + }, + respond: (data)=>resolve(data.status !== 204 ? JSON.parse(data.body ?? "{}") : undefined) + }, { + bucketId: options?.bucketId, + body: body, + retryCount: options?.retryCount ?? 0, + headers: options?.headers + }); + }); +} +function simplifyUrl(url, method) { + let route = url.replace(/\/([a-z-]+)\/(?:[0-9]{17,19})/g, function(match, p) { + return [ + "channels", + "guilds" + ].includes(p) ? match : `/${p}/skillzPrefersID`; + }).replace(/\/reactions\/[^/]+/g, "/reactions/skillzPrefersID"); + if (route.includes("/reactions")) { + route = route.substring(0, route.indexOf("/reactions") + "/reactions".length); + } + if (method === "DELETE" && route.endsWith("/messages/skillzPrefersID")) { + route = method + route; + } + return route; +} +function removeTokenPrefix(token, type = "REST") { + if (!token) throw new Error(`The ${type} was not given a token. Please provide a token and try again.`); + if (!token.startsWith("Bot ")) return token; + return token.substring(token.indexOf(" ") + 1); +} +function getBotIdFromToken(token) { + return BigInt(atob(token.split(".")[0])); +} +async function sendRequest(rest, options) { + try { + rest.debug(`[REST - fetching] URL: ${options.url} | ${JSON.stringify(options)}`); + const newURL = options.url.startsWith(BASE_URL) ? options.url : `${BASE_URL}/v${rest.version}/${options.url}`; + rest.debug(`[REST - url data] URL: ${newURL}`); + const response = await fetch(new Request(newURL, { + method: options.method, + headers: options.payload?.headers, + body: options.payload?.body + })); + rest.debug(`[REST - fetched] URL: ${options.url} | ${JSON.stringify(options)}`); + const bucketIdFromHeaders = rest.processRequestHeaders(rest, rest.simplifyUrl(options.url, options.method), response.headers); + if (bucketIdFromHeaders) { + options.bucketId = bucketIdFromHeaders; + } + if (response.status < 200 || response.status >= 400) { + rest.debug(`[REST - httpError] Payload: ${JSON.stringify(options)} | Response: ${JSON.stringify(response)}`); + let error = "REQUEST_UNKNOWN_ERROR"; + switch(response.status){ + case HTTPResponseCodes.BadRequest: + error = "The options was improperly formatted, or the server couldn't understand it."; + break; + case HTTPResponseCodes.Unauthorized: + error = "The Authorization header was missing or invalid."; + break; + case HTTPResponseCodes.Forbidden: + error = "The Authorization token you passed did not have permission to the resource."; + break; + case HTTPResponseCodes.NotFound: + error = "The resource at the location specified doesn't exist."; + break; + case HTTPResponseCodes.MethodNotAllowed: + error = "The HTTP method used is not valid for the location specified."; + break; + case HTTPResponseCodes.GatewayUnavailable: + error = "There was not a gateway available to process your options. Wait a bit and retry."; + break; + } + if (rest.invalidRequestErrorStatuses.includes(response.status) && !(response.status === 429 && response.headers.get("X-RateLimit-Scope"))) { + ++rest.invalidRequests; + if (!rest.invalidRequestsTimeoutId) { + rest.invalidRequestsTimeoutId = setTimeout(()=>{ + rest.debug(`[REST - processGlobalQueue] Resetting invalid optionss counter in setTimeout.`); + rest.invalidRequests = 0; + rest.invalidRequestsTimeoutId = 0; + }, rest.invalidRequestsInterval); + } + } + if (response.status !== 429) { + options.reject?.({ + ok: false, + status: response.status, + error, + body: response.type ? JSON.stringify(await response.json()) : undefined + }); + throw new Error(JSON.stringify({ + ok: false, + status: response.status, + error, + body: response.type ? JSON.stringify(await response.json()) : undefined + })); + } else { + if (options.retryCount && (options.retryCount++) >= rest.maxRetryCount) { + rest.debug(`[REST - RetriesMaxed] ${JSON.stringify(options)}`); + options.reject?.({ + ok: false, + status: response.status, + error: "The options was rate limited and it maxed out the retries limit." + }); + return; + } + } + } + if (response.status === 204) { + rest.debug(`[REST - FetchSuccess] URL: ${options.url} | ${JSON.stringify(options)}`); + options.respond?.({ + ok: true, + status: 204 + }); + return; + } else { + const json = JSON.stringify(await response.json()); + rest.debug(`[REST - fetchSuccess] ${JSON.stringify(options)}`); + options.respond?.({ + ok: true, + status: 200, + body: json + }); + return JSON.parse(json); + } + } catch (error1) { + rest.debug(`[REST - fetchFailed] Payload: ${JSON.stringify(options)} | Error: ${error1}`); + options.reject?.({ + ok: false, + status: 599, + error: "Internal Proxy Error" + }); + throw new Error("Something went wrong in sendRequest", { + cause: error1 + }); + } +} +function createRestManager(options) { + const version = options.version || 10; + if (options.customUrl) { + baseEndpoints.BASE_URL = `${options.customUrl}/v${version}`; + } + return { + invalidRequests: 0, + maxInvalidRequests: 10000, + invalidRequestsInterval: 600000, + invalidRequestsTimeoutId: 0, + invalidRequestsSafetyAmount: 1, + invalidRequestFrozenAt: 0, + invalidRequestErrorStatuses: [ + 401, + 403, + 429 + ], + version, + token: removeTokenPrefix(options.token), + maxRetryCount: options.maxRetryCount || 10, + secretKey: options.secretKey || "discordeno_best_lib_ever", + customUrl: options.customUrl || "", + pathQueues: new Map(), + processingQueue: false, + processingRateLimitedPaths: false, + globallyRateLimited: false, + globalQueue: [], + globalQueueProcessing: false, + rateLimitedPaths: new Map(), + debug: options.debug || function(_text) {}, + checkRateLimits: options.checkRateLimits || checkRateLimits, + cleanupQueues: options.cleanupQueues || cleanupQueues, + processQueue: options.processQueue || processQueue, + processRateLimitedPaths: options.processRateLimitedPaths || processRateLimitedPaths, + processRequestHeaders: options.processRequestHeaders || processRequestHeaders, + processRequest: options.processRequest || processRequest, + createRequestBody: options.createRequestBody || createRequestBody, + runMethod: options.runMethod || runMethod, + simplifyUrl: options.simplifyUrl || simplifyUrl, + processGlobalQueue: options.processGlobalQueue || processGlobalQueue, + convertRestError: options.convertRestError || convertRestError, + sendRequest: options.sendRequest || sendRequest + }; +} +var AutoModerationEventTypes; +(function(AutoModerationEventTypes) { + AutoModerationEventTypes[AutoModerationEventTypes["MessageSend"] = 1] = "MessageSend"; +})(AutoModerationEventTypes || (AutoModerationEventTypes = {})); +var AutoModerationTriggerTypes; +(function(AutoModerationTriggerTypes) { + AutoModerationTriggerTypes[AutoModerationTriggerTypes["Keyword"] = 1] = "Keyword"; + AutoModerationTriggerTypes[AutoModerationTriggerTypes["HarmfulLink"] = 2] = "HarmfulLink"; + AutoModerationTriggerTypes[AutoModerationTriggerTypes["Spam"] = 3] = "Spam"; + AutoModerationTriggerTypes[AutoModerationTriggerTypes["KeywordPreset"] = 4] = "KeywordPreset"; +})(AutoModerationTriggerTypes || (AutoModerationTriggerTypes = {})); +var DiscordAutoModerationRuleTriggerMetadataPresets; +(function(DiscordAutoModerationRuleTriggerMetadataPresets) { + DiscordAutoModerationRuleTriggerMetadataPresets[DiscordAutoModerationRuleTriggerMetadataPresets["Profanity"] = 1] = "Profanity"; + DiscordAutoModerationRuleTriggerMetadataPresets[DiscordAutoModerationRuleTriggerMetadataPresets["SexualContent"] = 2] = "SexualContent"; + DiscordAutoModerationRuleTriggerMetadataPresets[DiscordAutoModerationRuleTriggerMetadataPresets["Slurs"] = 3] = "Slurs"; +})(DiscordAutoModerationRuleTriggerMetadataPresets || (DiscordAutoModerationRuleTriggerMetadataPresets = {})); +var AutoModerationActionType; +(function(AutoModerationActionType) { + AutoModerationActionType[AutoModerationActionType["BlockMessage"] = 1] = "BlockMessage"; + AutoModerationActionType[AutoModerationActionType["SendAlertMessage"] = 2] = "SendAlertMessage"; + AutoModerationActionType[AutoModerationActionType["Timeout"] = 3] = "Timeout"; +})(AutoModerationActionType || (AutoModerationActionType = {})); +class Permissions { + static Flags = BitwisePermissionFlags; + bitfield; + constructor(bitfield){ + this.bitfield = Permissions.resolve(bitfield); + } + has(bit) { + if (this.bitfield & BigInt(Permissions.Flags.ADMINISTRATOR)) { + return true; + } + return !!(this.bitfield & Permissions.resolve(bit)); + } + static resolve(bit) { + switch(typeof bit){ + case "bigint": + return bit; + case "number": + return BigInt(bit); + case "string": + return BigInt(Permissions.Flags[bit]); + case "object": + return Permissions.resolve(bit.map((p)=>BigInt(Permissions.Flags[p])).reduce((acc, cur)=>acc | cur, 0n)); + default: + throw new TypeError(`Cannot resolve permission: ${bit}`); + } + } +} +class EventEmitter { + listeners = new Map(); + #addListener(event, func) { + this.listeners.set(event, this.listeners.get(event) || []); + this.listeners.get(event)?.push(func); + return this; + } + on(event, func) { + return this.#addListener(event, func); + } + #removeListener(event1, func1) { + if (this.listeners.has(event1)) { + const listener = this.listeners.get(event1); + if (listener?.includes(func1)) { + listener.splice(listener.indexOf(func1), 1); + if (listener.length === 0) { + this.listeners.delete(event1); + } + } + } + return this; + } + off(event, func) { + return this.#removeListener(event, func); + } + once(event, func) { + const closure = ()=>{ + func(); + this.off(event, func); + }; + const listener = this.listeners.get(event) ?? []; + listener.push(closure); + return this; + } + emit(event, ...args) { + const listener = this.listeners.get(event); + if (!listener) { + return false; + } + listener.forEach((f)=>f(...args)); + return true; + } + listenerCount(eventName) { + return this.listeners.get(eventName)?.length ?? 0; + } + rawListeners(eventName) { + return this.listeners.get(eventName); + } +} +var MessageFlags; +(function(MessageFlags) { + MessageFlags[MessageFlags["CrossPosted"] = 1] = "CrossPosted"; + MessageFlags[MessageFlags["IsCrosspost"] = 2] = "IsCrosspost"; + MessageFlags[MessageFlags["SupressEmbeds"] = 4] = "SupressEmbeds"; + MessageFlags[MessageFlags["SourceMessageDeleted"] = 8] = "SourceMessageDeleted"; + MessageFlags[MessageFlags["Urgent"] = 16] = "Urgent"; + MessageFlags[MessageFlags["HasThread"] = 32] = "HasThread"; + MessageFlags[MessageFlags["Ephemeral"] = 64] = "Ephemeral"; + MessageFlags[MessageFlags["Loading"] = 128] = "Loading"; + MessageFlags[MessageFlags["FailedToMentionSomeRolesInThread"] = 256] = "FailedToMentionSomeRolesInThread"; +})(MessageFlags || (MessageFlags = {})); +class Util { + static formatImageURL(url, size = 128, format) { + return `${url}.${format || (url.includes("/a_") ? "gif" : "jpg")}?size=${size}`; + } + static iconHashToBigInt(hash) { + return BigInt("0x" + (hash.startsWith("a_") ? `a${hash.substring(2)}` : `b${hash}`)); + } + static iconBigintToHash(icon) { + const hash = icon.toString(16); + return hash.startsWith("a") ? `a_${hash.substring(1)}` : hash.substring(1); + } +} +function USER_AVATAR(userId, icon) { + return `${baseEndpoints.CDN_URL}/avatars/${userId}/${icon}`; +} +function EMOJI_URL(id, animated = false) { + return `https://cdn.discordapp.com/emojis/${id}.${animated ? "gif" : "png"}`; +} +function USER_DEFAULT_AVATAR(altIcon) { + return `${baseEndpoints.CDN_URL}/embed/avatars/${altIcon}.png`; +} +function GUILD_BANNER(guildId, icon) { + return `${baseEndpoints.CDN_URL}/banners/${guildId}/${icon}`; +} +function GUILD_SPLASH(guildId, icon) { + return `${baseEndpoints.CDN_URL}/splashes/${guildId}/${icon}`; +} +function GUILD_ICON(guildId, icon) { + return `${baseEndpoints.CDN_URL}/icons/${guildId}/${icon}`; +} +function USER(userId) { + return `/users/${userId}`; +} +function GATEWAY_BOT() { + return "/gateway/bot"; +} +function CHANNEL(channelId) { + return `/channels/${channelId}`; +} +function CHANNEL_INVITES(channelId) { + return `/channels/${channelId}/invites`; +} +function CHANNEL_TYPING(channelId) { + return `/channels/${channelId}/typing`; +} +function CHANNEL_MESSAGES(channelId, options) { + let url = `/channels/${channelId}/messages?`; + if (options) { + if (options.after) url += `after=${options.after}`; + if (options.before) url += `&before=${options.before}`; + if (options.around) url += `&around=${options.around}`; + if (options.limit) url += `&limit=${options.limit}`; + } + return url; +} +function CHANNEL_MESSAGE(channelId, messageId) { + return `/channels/${channelId}/messages/${messageId}`; +} +function GUILD_MEMBER(guildId, userId) { + return `/guilds/${guildId}/members/${userId}`; +} +function GUILD_BAN(guildId, userId) { + return `/guilds/${guildId}/bans/${userId}`; +} +function GUILD_ROLE(guildId, roleId) { + return `/guilds/${guildId}/roles/${roleId}`; +} +function GUILD_ROLES(guildId) { + return `/guilds/${guildId}/roles`; +} +function GUILD_EMOJIS(guildId) { + return `/guilds/${guildId}/emojis`; +} +function GUILD_EMOJI(guildId, emojiId) { + return `/guilds/${guildId}/emojis/${emojiId}`; +} +function GUILDS() { + return `/guilds`; +} +function INVITE(inviteCode, options) { + let url = `/invites/${inviteCode}?`; + if (options) { + if (options.withCounts) url += `with_counts=${options.withCounts}`; + if (options.withExpiration) url += `&with_expiration=${options.withExpiration}`; + if (options.scheduledEventId) url += `&guild_scheduled_event_id=${options.scheduledEventId}`; + } + return url; +} +function GUILD_INVITES(guildId) { + return `/guilds/${guildId}/invites`; +} +function INTERACTION_ID_TOKEN(interactionId, token) { + return `/interactions/${interactionId}/${token}/callback`; +} +function WEBHOOK_MESSAGE(webhookId, token, messageId) { + return `/webhooks/${webhookId}/${token}/messages/${messageId}`; +} +function WEBHOOK_TOKEN(webhookId, token) { + if (!token) return `/webhooks/${webhookId}`; + return `/webhooks/${webhookId}/${token}`; +} +function WEBHOOK(webhookId, token, options) { + let url = `/webhooks/${webhookId}/${token}`; + if (options?.wait) url += `?wait=${options.wait}`; + if (options?.threadId) url += `?threadId=${options.threadId}`; + if (options?.wait && options.threadId) url += `?wait=${options.wait}&threadId=${options.threadId}`; + return url; +} +function USER_NICK(guildId) { + return `/guilds/${guildId}/members/@me`; +} +function GUILD_PRUNE(guildId, options) { + let url = `/guilds/${guildId}/prune?`; + if (options?.days) url += `days=${options.days}`; + if (options?.includeRoles) url += `&include_roles=${options.includeRoles}`; + return url; +} +function CHANNEL_PIN(channelId, messageId) { + return `/channels/${channelId}/pins/${messageId}`; +} +function CHANNEL_PINS(channelId) { + return `/channels/${channelId}/pins`; +} +function CHANNEL_MESSAGE_REACTION_ME(channelId, messageId, emoji) { + return `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}/@me`; +} +function CHANNEL_MESSAGE_REACTION_USER(channelId, messageId, emoji, userId) { + return `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}/${userId}`; +} +function CHANNEL_MESSAGE_REACTIONS(channelId, messageId) { + return `/channels/${channelId}/messages/${messageId}/reactions`; +} +function CHANNEL_MESSAGE_REACTION(channelId, messageId, emoji, options) { + let url = `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}?`; + if (options?.after) url += `after=${options.after}`; + if (options?.limit) url += `&limit=${options.limit}`; + return url; +} +function CHANNEL_MESSAGE_CROSSPOST(channelId, messageId) { + return `/channels/${channelId}/messages/${messageId}/crosspost`; +} +function GUILD_MEMBER_ROLE(guildId, memberId, roleId) { + return `/guilds/${guildId}/members/${memberId}/roles/${roleId}`; +} +function CHANNEL_WEBHOOKS(channelId) { + return `/channels/${channelId}/webhooks`; +} +function THREAD_START_PUBLIC(channelId, messageId) { + return `/channels/${channelId}/messages/${messageId}/threads`; +} +function THREAD_START_PRIVATE(channelId) { + return `/channels/${channelId}/threads`; +} +function THREAD_ACTIVE(guildId) { + return `/guilds/${guildId}/threads/active`; +} +function THREAD_ME(channelId) { + return `/channels/${channelId}/thread-members/@me`; +} +function THREAD_MEMBERS(channelId) { + return `/channels/${channelId}/thread-members`; +} +function THREAD_USER(channelId, userId) { + return `/channels/${channelId}/thread-members/${userId}`; +} +function THREAD_ARCHIVED_PUBLIC(channelId, options) { + let url = `/channels/${channelId}/threads/archived/public?`; + if (options) { + if (options.before) url += `before=${new Date(options.before).toISOString()}`; + if (options.limit) url += `&limit=${options.limit}`; + } + return url; +} +function THREAD_ARCHIVED_PRIVATE_JOINED(channelId, options) { + let url = `/channels/${channelId}/users/@me/threads/archived/private?`; + if (options) { + if (options.before) url += `before=${new Date(options.before).toISOString()}`; + if (options.limit) url += `&limit=${options.limit}`; + } + return url; +} +function STAGE_INSTANCE(channelId) { + return `/stage-instances/${channelId}`; +} +function APPLICATION_COMMANDS(appId, commandId) { + if (commandId) return `/applications/${appId}/commands/${commandId}`; + return `/applications/${appId}/commands`; +} +function GUILD_APPLICATION_COMMANDS(appId, guildId, commandId) { + if (commandId) return `/applications/${appId}/guilds/${guildId}/commands/${commandId}`; + return `/applications/${appId}/guilds/${guildId}/commands`; +} +function GUILD_APPLICATION_COMMANDS_PERMISSIONS(appId, guildId, commandId) { + if (commandId) return `/applications/${appId}/guilds/${guildId}/commands/${commandId}/permissions`; + return `/applications/${appId}/guilds/${guildId}/commands/permissions`; +} +function GUILD_APPLICATION_COMMANDS_LOCALIZATIONS(appId, guildId, commandId, withLocalizations) { + let url = `/applications/${appId}/guilds/${guildId}/commands/${commandId}?`; + if (withLocalizations !== undefined) { + url += `with_localizations=${withLocalizations}`; + } + return url; +} +function STICKER_PACKS() { + return `stickers-packs`; +} +class User { + constructor(session, data){ + this.session = session; + this.id = data.id; + this.username = data.username; + this.discriminator = data.discriminator; + this.avatarHash = data.avatar ? Util.iconHashToBigInt(data.avatar) : undefined; + this.accentColor = data.accent_color; + this.bot = !!data.bot; + this.system = !!data.system; + this.banner = data.banner; + } + session; + id; + username; + discriminator; + avatarHash; + accentColor; + bot; + system; + banner; + get tag() { + return `${this.username}#${this.discriminator}}`; + } + avatarURL(options = { + size: 128 + }) { + let url; + if (!this.avatarHash) { + url = USER_DEFAULT_AVATAR(Number(this.discriminator) % 5); + } else { + url = USER_AVATAR(this.id, Util.iconBigintToHash(this.avatarHash)); + } + return Util.formatImageURL(url, options.size, options.format); + } + toString() { + return `<@${this.id}>`; + } +} +class AutoModerationRule { + constructor(session, data){ + this.session = session; + this.id = data.id; + this.guildId = data.guild_id; + this.name = data.name; + this.creatorId = data.creator_id; + this.eventType = data.event_type; + this.triggerType = data.trigger_type; + this.triggerMetadata = { + keywordFilter: data.trigger_metadata.keyword_filter, + presets: data.trigger_metadata.presets + }; + this.actions = data.actions.map((action)=>Object.create({ + type: action.type, + metadata: { + channelId: action.metadata.channel_id, + durationSeconds: action.metadata.duration_seconds + } + })); + this.enabled = !!data.enabled; + this.exemptRoles = data.exempt_roles; + this.exemptChannels = data.exempt_channels; + } + session; + id; + guildId; + name; + creatorId; + eventType; + triggerType; + triggerMetadata; + actions; + enabled; + exemptRoles; + exemptChannels; +} +class AutoModerationExecution { + constructor(session, data){ + this.session = session; + this.guildId = data.guild_id; + this.action = Object.create({ + type: data.action.type, + metadata: { + channelId: data.action.metadata.channel_id, + durationSeconds: data.action.metadata.duration_seconds + } + }); + this.ruleId = data.rule_id; + this.ruleTriggerType = data.rule_trigger_type; + this.userId = data.user_id; + this.content = data.content; + if (data.channel_id) { + this.channelId = data.channel_id; + } + if (data.message_id) { + this.messageId = data.message_id; + } + if (data.alert_system_message_id) { + this.alertSystemMessageId = data.alert_system_message_id; + } + if (data.matched_keyword) { + this.matchedKeyword = data.matched_keyword; + } + if (data.matched_content) { + this.matched_content = data.matched_content; + } + } + session; + guildId; + action; + ruleId; + ruleTriggerType; + userId; + channelId; + messageId; + alertSystemMessageId; + content; + matchedKeyword; + matched_content; +} +class Emoji { + constructor(session, data){ + this.id = data.id; + this.name = data.name; + this.animated = !!data.animated; + this.available = !!data.available; + this.requireColons = !!data.require_colons; + this.session = session; + } + id; + session; + name; + animated; + available; + requireColons; +} +const Snowflake = { + snowflakeToTimestamp (id) { + return (Number(id) >> 22) + 14200704e5; + } +}; +class WelcomeChannel { + constructor(session, data){ + this.session = session; + this.channelId = data.channel_id; + this.description = data.description; + this.emoji = new Emoji(session, { + name: data.emoji_name ? data.emoji_name : undefined, + id: data.emoji_id ? data.emoji_id : undefined + }); + } + session; + channelId; + description; + emoji; + get id() { + return this.channelId; + } +} +class WelcomeScreen { + constructor(session, data){ + this.session = session; + this.welcomeChannels = data.welcome_channels.map((welcomeChannel)=>new WelcomeChannel(session, welcomeChannel)); + if (data.description) { + this.description = data.description; + } + } + session; + description; + welcomeChannels; +} +class ThreadMember { + constructor(session, data){ + this.session = session; + this.id = data.id; + this.flags = data.flags; + this.timestamp = Date.parse(data.join_timestamp); + } + session; + id; + flags; + timestamp; + get threadId() { + return this.id; + } + async quitThread(memberId = this.session.botId) { + await this.session.rest.runMethod(this.session.rest, "DELETE", THREAD_USER(this.id, memberId)); + } + async fetchMember(memberId = this.session.botId) { + const member = await this.session.rest.runMethod(this.session.rest, "GET", THREAD_USER(this.id, memberId)); + return new ThreadMember(this.session, member); + } +} +async function urlToBase64(url) { + const buffer = await fetch(url).then((res)=>res.arrayBuffer()); + const imageStr = encode(buffer); + const type = url.substring(url.lastIndexOf(".") + 1); + return `data:image/${type};base64,${imageStr}`; +} +const base64abc = [ + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "+", + "/", +]; +function encode(data) { + const uint8 = typeof data === "string" ? new TextEncoder().encode(data) : data instanceof Uint8Array ? data : new Uint8Array(data); + let result = "", i; + const l = uint8.length; + for(i = 2; i < l; i += 3){ + result += base64abc[uint8[i - 2] >> 2]; + result += base64abc[(uint8[i - 2] & 0x03) << 4 | uint8[i - 1] >> 4]; + result += base64abc[(uint8[i - 1] & 0x0f) << 2 | uint8[i] >> 6]; + result += base64abc[uint8[i] & 0x3f]; + } + if (i === l + 1) { + result += base64abc[uint8[i - 2] >> 2]; + result += base64abc[(uint8[i - 2] & 0x03) << 4]; + result += "=="; + } + if (i === l) { + result += base64abc[uint8[i - 2] >> 2]; + result += base64abc[(uint8[i - 2] & 0x03) << 4 | uint8[i - 1] >> 4]; + result += base64abc[(uint8[i - 1] & 0x0f) << 2]; + result += "="; + } + return result; +} +function NewTeam(session, data) { + return { + icon: data.icon ? data.icon : undefined, + id: data.id, + members: data.members.map((member)=>{ + return { + membershipState: member.membership_state, + permissions: member.permissions, + teamId: member.team_id, + user: new User(session, member.user) + }; + }), + ownerUserId: data.owner_user_id, + name: data.name + }; +} +class Application { + constructor(session, data){ + this.id = data.id; + this.session = session; + this.name = data.name; + this.icon = data.icon || undefined; + this.description = data.description; + this.rpcOrigins = data.rpc_origins; + this.botPublic = data.bot_public; + this.botRequireCodeGrant = data.bot_require_code_grant; + this.termsOfServiceURL = data.terms_of_service_url; + this.privacyPolicyURL = data.privacy_policy_url; + this.owner = data.owner ? new User(session, data.owner) : undefined; + this.summary = ""; + this.verifyKey = data.verify_key; + this.team = data.team ? NewTeam(session, data.team) : undefined; + this.guildId = data.guild_id; + this.coverImage = data.cover_image; + this.tags = data.tags; + this.installParams = data.install_params; + this.customInstallURL = data.custom_install_url; + } + session; + id; + name; + icon; + description; + rpcOrigins; + botPublic; + botRequireCodeGrant; + termsOfServiceURL; + privacyPolicyURL; + owner; + summary; + verifyKey; + team; + guildId; + primarySkuId; + slug; + coverImage; + flags; + tags; + installParams; + customInstallURL; +} +class Attachment { + constructor(session, data){ + this.session = session; + this.id = data.id; + this.contentType = data.content_type ? data.content_type : undefined; + this.attachment = data.url; + this.proxyUrl = data.proxy_url; + this.name = data.filename; + this.size = data.size; + this.height = data.height ? data.height : undefined; + this.width = data.width ? data.width : undefined; + this.ephemeral = !!data.ephemeral; + } + session; + id; + contentType; + attachment; + proxyUrl; + name; + size; + height; + width; + ephemeral; +} +class BaseComponent { + constructor(type){ + this.type = type; + } + type; + isActionRow() { + return this.type === MessageComponentTypes.ActionRow; + } + isButton() { + return this.type === MessageComponentTypes.Button; + } + isSelectMenu() { + return this.type === MessageComponentTypes.SelectMenu; + } + isTextInput() { + return this.type === MessageComponentTypes.InputText; + } +} +class Button extends BaseComponent { + constructor(session, data){ + super(data.type); + this.session = session; + this.type = data.type; + this.customId = data.custom_id; + this.label = data.label; + this.style = data.style; + this.disabled = data.disabled; + if (data.emoji) { + this.emoji = new Emoji(session, data.emoji); + } + } + session; + type; + customId; + label; + style; + disabled; + emoji; +} +class LinkButton extends BaseComponent { + constructor(session, data){ + super(data.type); + this.session = session; + this.type = data.type; + this.url = data.url; + this.label = data.label; + this.style = data.style; + this.disabled = data.disabled; + if (data.emoji) { + this.emoji = new Emoji(session, data.emoji); + } + } + session; + type; + url; + label; + style; + disabled; + emoji; +} +class SelectMenu extends BaseComponent { + constructor(session, data){ + super(data.type); + this.session = session; + this.type = data.type; + this.customId = data.custom_id; + this.options = data.options.map((option)=>{ + return { + label: option.label, + description: option.description, + emoji: option.emoji || new Emoji(session, option.emoji), + value: option.value + }; + }); + this.placeholder = data.placeholder; + this.minValues = data.min_values; + this.maxValues = data.max_values; + this.disabled = data.disabled; + } + session; + type; + customId; + options; + placeholder; + minValues; + maxValues; + disabled; +} +class TextInput extends BaseComponent { + constructor(session, data){ + super(data.type); + this.session = session; + this.type = data.type; + this.customId = data.custom_id; + this.label = data.label; + this.style = data.style; + this.placeholder = data.placeholder; + this.value = data.value; + this.minLength = data.min_length; + this.maxLength = data.max_length; + } + session; + type; + style; + customId; + label; + placeholder; + value; + minLength; + maxLength; +} +class ActionRow extends BaseComponent { + constructor(session, data){ + super(data.type); + this.session = session; + this.type = data.type; + this.components = data.components.map((component)=>{ + switch(component.type){ + case MessageComponentTypes.Button: + if (component.style === ButtonStyles.Link) { + return new LinkButton(session, component); + } + return new Button(session, component); + case MessageComponentTypes.SelectMenu: + return new SelectMenu(session, component); + case MessageComponentTypes.InputText: + return new TextInput(session, component); + case MessageComponentTypes.ActionRow: + throw new Error("Cannot have an action row inside an action row"); + } + }); + } + session; + type; + components; +} +class ComponentFactory { + static from(session, component) { + switch(component.type){ + case MessageComponentTypes.ActionRow: + return new ActionRow(session, component); + case MessageComponentTypes.Button: + if (component.style === ButtonStyles.Link) { + return new Button(session, component); + } + return new Button(session, component); + case MessageComponentTypes.SelectMenu: + return new SelectMenu(session, component); + case MessageComponentTypes.InputText: + return new TextInput(session, component); + } + } +} +function calculateShardId(gateway, guildId) { + if (gateway.manager.totalShards === 1) return 0; + return Number((guildId >> 22n) % BigInt(gateway.manager.totalShards - 1)); +} +class Member { + constructor(session, data, guildId){ + this.session = session; + this.user = new User(session, data.user); + this.guildId = guildId; + this.avatarHash = data.avatar ? Util.iconHashToBigInt(data.avatar) : undefined; + this.nickname = data.nick ? data.nick : undefined; + this.joinedTimestamp = Number.parseInt(data.joined_at); + this.roles = data.roles; + this.deaf = !!data.deaf; + this.mute = !!data.mute; + this.pending = !!data.pending; + this.communicationDisabledUntilTimestamp = data.communication_disabled_until ? Number.parseInt(data.communication_disabled_until) : undefined; + } + session; + user; + guildId; + avatarHash; + nickname; + joinedTimestamp; + roles; + deaf; + mute; + pending; + communicationDisabledUntilTimestamp; + get id() { + return this.user.id; + } + get nicknameOrUsername() { + return this.nickname ?? this.user.username; + } + get joinedAt() { + return new Date(this.joinedTimestamp); + } + async ban(options) { + await Guild.prototype.banMember.call({ + id: this.guildId, + session: this.session + }, this.user.id, options); + return this; + } + async kick(options) { + await Guild.prototype.kickMember.call({ + id: this.guildId, + session: this.session + }, this.user.id, options); + return this; + } + async unban() { + await Guild.prototype.unbanMember.call({ + id: this.guildId, + session: this.session + }, this.user.id); + } + async edit(options) { + const member = await Guild.prototype.editMember.call({ + id: this.guildId, + session: this.session + }, this.user.id, options); + return member; + } + async addRole(roleId, options = {}) { + await Guild.prototype.addRole.call({ + id: this.guildId, + session: this.session + }, this.user.id, roleId, options); + } + async removeRole(roleId, options = {}) { + await Guild.prototype.removeRole.call({ + id: this.guildId, + session: this.session + }, this.user.id, roleId, options); + } + avatarURL(options = { + size: 128 + }) { + let url; + if (this.user.bot) { + return this.user.avatarURL(); + } + if (!this.avatarHash) { + url = USER_DEFAULT_AVATAR(Number(this.user.discriminator) % 5); + } else { + url = USER_AVATAR(this.user.id, Util.iconBigintToHash(this.avatarHash)); + } + return Util.formatImageURL(url, options.size, options.format); + } + toString() { + return `<@!${this.user.id}>`; + } +} +function NewMessageReactionAdd(session, data) { + return { + userId: data.user_id, + channelId: data.channel_id, + messageId: data.message_id, + guildId: data.guild_id, + member: data.member ? new Member(session, data.member, data.guild_id || "") : undefined, + emoji: new Emoji(session, data.emoji) + }; +} +class BaseChannel { + constructor(session, data){ + this.id = data.id; + this.session = session; + this.name = data.name; + this.type = data.type; + } + id; + session; + name; + type; + isText() { + return textBasedChannels.includes(this.type); + } + isVoice() { + return this.type === ChannelTypes.GuildVoice; + } + isDM() { + return this.type === ChannelTypes.DM; + } + isNews() { + return this.type === ChannelTypes.GuildNews; + } + isThread() { + return this.type === ChannelTypes.GuildPublicThread || this.type === ChannelTypes.GuildPrivateThread; + } + isStage() { + return this.type === ChannelTypes.GuildStageVoice; + } + toString() { + return `<#${this.id}>`; + } +} +class Webhook { + constructor(session, data){ + this.session = session; + this.id = data.id; + this.type = data.type; + this.token = data.token; + if (data.avatar) { + this.avatar = Util.iconHashToBigInt(data.avatar); + } + if (data.user) { + this.user = new User(session, data.user); + } + if (data.guild_id) { + this.guildId = data.guild_id; + } + if (data.channel_id) { + this.channelId = data.channel_id; + } + if (data.application_id) { + this.applicationId = data.application_id; + } + } + session; + id; + type; + token; + avatar; + applicationId; + channelId; + guildId; + user; + async execute(options) { + if (!this.token) { + return; + } + const data = { + content: options?.content, + embeds: options?.embeds, + tts: options?.tts, + allowed_mentions: options?.allowedMentions, + components: options?.components, + file: options?.files + }; + const message = await this.session.rest.sendRequest(this.session.rest, { + url: WEBHOOK(this.id, this.token, { + wait: options?.wait, + threadId: options?.threadId + }), + method: "POST", + payload: this.session.rest.createRequestBody(this.session.rest, { + method: "POST", + body: { + ...data + } + }) + }); + return options?.wait ?? true ? new Message(this.session, message) : undefined; + } + async fetch() { + const message = await this.session.rest.runMethod(this.session.rest, "GET", WEBHOOK_TOKEN(this.id, this.token)); + return new Webhook(this.session, message); + } + async fetchMessage(messageId) { + if (!this.token) { + return; + } + const message = await this.session.rest.runMethod(this.session.rest, "GET", WEBHOOK_MESSAGE(this.id, this.token, messageId)); + return new Message(this.session, message); + } +} +class MessageReaction { + constructor(session, data){ + this.session = session; + this.me = data.me; + this.count = data.count; + this.emoji = new Emoji(session, data.emoji); + } + session; + me; + count; + emoji; +} +class Message { + constructor(session, data){ + this.session = session; + this.id = data.id; + this.type = data.type; + this.channelId = data.channel_id; + this.guildId = data.guild_id; + this.applicationId = data.application_id; + if (!data.webhook_id) { + this.author = new User(session, data.author); + } + this.flags = data.flags; + this.pinned = !!data.pinned; + this.tts = !!data.tts; + this.content = data.content; + this.nonce = data.nonce; + this.mentionEveryone = data.mention_everyone; + this.timestamp = Date.parse(data.timestamp); + this.editedTimestamp = data.edited_timestamp ? Date.parse(data.edited_timestamp) : undefined; + this.reactions = data.reactions?.map((react)=>new MessageReaction(session, react)) ?? []; + this.attachments = data.attachments.map((attachment)=>new Attachment(session, attachment)); + this.embeds = data.embeds; + if (data.thread && data.guild_id) { + this.thread = new ThreadChannel(session, data.thread, data.guild_id); + } + if (data.webhook_id && data.author.discriminator === "0000") { + this.webhook = { + id: data.webhook_id, + username: data.author.username, + discriminator: data.author.discriminator, + avatar: data.author.avatar ? Util.iconHashToBigInt(data.author.avatar) : undefined + }; + } + if (data.guild_id && data.member && !this.isWebhookMessage()) { + this.member = new Member(session, { + ...data.member, + user: data.author + }, data.guild_id); + } + this.components = data.components?.map((component)=>ComponentFactory.from(session, component)) ?? []; + if (data.activity) { + this.activity = { + partyId: data.activity.party_id, + type: data.activity.type + }; + } + if (data.sticker_items) { + this.stickers = data.sticker_items.map((si)=>{ + return { + id: si.id, + name: si.name, + formatType: si.format_type + }; + }); + } + } + session; + id; + type; + channelId; + guildId; + applicationId; + author; + flags; + pinned; + tts; + content; + nonce; + mentionEveryone; + timestamp; + editedTimestamp; + stickers; + reactions; + attachments; + embeds; + member; + thread; + components; + webhook; + activity; + get createdTimestamp() { + return Snowflake.snowflakeToTimestamp(this.id); + } + get createdAt() { + return new Date(this.createdTimestamp); + } + get sentAt() { + return new Date(this.timestamp); + } + get editedAt() { + return this.editedTimestamp ? new Date(this.editedTimestamp) : undefined; + } + get edited() { + return this.editedTimestamp; + } + get url() { + return `https://discord.com/channels/${this.guildId ?? "@me"}/${this.channelId}/${this.id}`; + } + get isBot() { + return this.author.bot; + } + async pin() { + await this.session.rest.runMethod(this.session.rest, "PUT", CHANNEL_PIN(this.channelId, this.id)); + } + async unpin() { + await this.session.rest.runMethod(this.session.rest, "DELETE", CHANNEL_PIN(this.channelId, this.id)); + } + async edit(options) { + const message = await this.session.rest.runMethod(this.session.rest, "POST", CHANNEL_MESSAGE(this.id, this.channelId), { + content: options.content, + allowed_mentions: { + parse: options.allowedMentions?.parse, + roles: options.allowedMentions?.roles, + users: options.allowedMentions?.users, + replied_user: options.allowedMentions?.repliedUser + }, + flags: options.flags, + embeds: options.embeds + }); + return message; + } + async suppressEmbeds(suppress = true) { + if (this.flags === MessageFlags.SupressEmbeds && suppress === false) { + return; + } + const message = await this.edit({ + flags: MessageFlags.SupressEmbeds + }); + return message; + } + async delete({ reason }) { + await this.session.rest.runMethod(this.session.rest, "DELETE", CHANNEL_MESSAGE(this.channelId, this.id), { + reason + }); + return this; + } + async reply(options) { + const message = await this.session.rest.runMethod(this.session.rest, "POST", CHANNEL_MESSAGES(this.channelId), { + content: options.content, + file: options.files, + allowed_mentions: { + parse: options.allowedMentions?.parse, + roles: options.allowedMentions?.roles, + users: options.allowedMentions?.users, + replied_user: options.allowedMentions?.repliedUser + }, + message_reference: options.messageReference ? { + message_id: options.messageReference.messageId, + channel_id: options.messageReference.channelId, + guild_id: options.messageReference.guildId, + fail_if_not_exists: options.messageReference.failIfNotExists ?? true + } : undefined, + embeds: options.embeds, + tts: options.tts, + components: options.components + }); + return new Message(this.session, message); + } + get react() { + return this.addReaction; + } + async addReaction(reaction) { + const r = typeof reaction === "string" ? reaction : `${reaction.name}:${reaction.id}`; + await this.session.rest.runMethod(this.session.rest, "PUT", CHANNEL_MESSAGE_REACTION_ME(this.channelId, this.id, r), {}); + } + async removeReaction(reaction, options) { + const r = typeof reaction === "string" ? reaction : `${reaction.name}:${reaction.id}`; + await this.session.rest.runMethod(this.session.rest, "DELETE", options?.userId ? CHANNEL_MESSAGE_REACTION_USER(this.channelId, this.id, r, options.userId) : CHANNEL_MESSAGE_REACTION_ME(this.channelId, this.id, r)); + } + async fetchReactions(reaction, options) { + const r = typeof reaction === "string" ? reaction : `${reaction.name}:${reaction.id}`; + const users = await this.session.rest.runMethod(this.session.rest, "GET", CHANNEL_MESSAGE_REACTION(this.channelId, this.id, encodeURIComponent(r), options)); + return users.map((user)=>new User(this.session, user)); + } + async removeReactionEmoji(reaction) { + const r = typeof reaction === "string" ? reaction : `${reaction.name}:${reaction.id}`; + await this.session.rest.runMethod(this.session.rest, "DELETE", CHANNEL_MESSAGE_REACTION(this.channelId, this.id, r)); + } + async nukeReactions() { + await this.session.rest.runMethod(this.session.rest, "DELETE", CHANNEL_MESSAGE_REACTIONS(this.channelId, this.id)); + } + async crosspost() { + const message = await this.session.rest.runMethod(this.session.rest, "POST", CHANNEL_MESSAGE_CROSSPOST(this.channelId, this.id)); + return new Message(this.session, message); + } + async fetch() { + const message = await this.session.rest.runMethod(this.session.rest, "GET", CHANNEL_MESSAGE(this.channelId, this.id)); + if (!message?.id) return; + return new Message(this.session, message); + } + get publish() { + return this.crosspost; + } + inGuild() { + return !!this.guildId; + } + isWebhookMessage() { + return !!this.webhook; + } +} +class BaseGuild { + constructor(session, data){ + this.session = session; + this.id = data.id; + this.name = data.name; + this.iconHash = data.icon ? Util.iconHashToBigInt(data.icon) : undefined; + this.features = data.features; + } + session; + id; + name; + iconHash; + features; + get createdTimestamp() { + return Snowflake.snowflakeToTimestamp(this.id); + } + get createdAt() { + return new Date(this.createdTimestamp); + } + get partnered() { + return this.features.includes(GuildFeatures.Partnered); + } + get verified() { + return this.features.includes(GuildFeatures.Verified); + } + iconURL(options = { + size: 128 + }) { + if (this.iconHash) { + return Util.formatImageURL(GUILD_ICON(this.id, Util.iconBigintToHash(this.iconHash)), options.size, options.format); + } + } + toString() { + return this.name; + } +} +function NewInviteCreate(session, invite) { + return { + channelId: invite.channel_id, + code: invite.code, + createdAt: invite.created_at, + guildId: invite.guild_id, + inviter: invite.inviter ? new User(session, invite.inviter) : undefined, + maxAge: invite.max_age, + maxUses: invite.max_uses, + targetType: invite.target_type, + targetUser: invite.target_user ? new User(session, invite.target_user) : undefined, + targetApplication: invite.target_application ? new Application(session, invite.target_application) : undefined, + temporary: invite.temporary, + uses: invite.uses + }; +} +class Role { + constructor(session, data, guildId){ + this.session = session; + this.id = data.id; + this.guildId = guildId; + this.hoist = data.hoist; + this.iconHash = data.icon ? Util.iconHashToBigInt(data.icon) : undefined; + this.color = data.color; + this.name = data.name; + this.unicodeEmoji = data.unicode_emoji; + this.mentionable = data.mentionable; + this.managed = data.managed; + this.permissions = new Permissions(BigInt(data.permissions)); + } + session; + id; + guildId; + hoist; + iconHash; + color; + name; + unicodeEmoji; + mentionable; + managed; + permissions; + get createdTimestamp() { + return Snowflake.snowflakeToTimestamp(this.id); + } + get createdAt() { + return new Date(this.createdTimestamp); + } + get hexColor() { + return `#${this.color.toString(16).padStart(6, "0")}`; + } + async delete() { + await Guild.prototype.deleteRole.call({ + id: this.guildId, + session: this.session + }, this.id); + } + async edit(options) { + const role = await Guild.prototype.editRole.call({ + id: this.guildId, + session: this.session + }, this.id, options); + return role; + } + async add(memberId, options = {}) { + await Guild.prototype.addRole.call({ + id: this.guildId, + session: this.session + }, memberId, this.id, options); + } + async remove(memberId, options = {}) { + await Guild.prototype.removeRole.call({ + id: this.guildId, + session: this.session + }, memberId, this.id, options); + } + toString() { + switch(this.id){ + case this.guildId: + return "@everyone"; + default: + return `<@&${this.id}>`; + } + } +} +class GuildEmoji extends Emoji { + constructor(session, data, guildId){ + super(session, data); + this.guildId = guildId; + this.roles = data.roles; + this.user = data.user ? new User(this.session, data.user) : undefined; + this.managed = !!data.managed; + this.id = super.id; + } + guildId; + roles; + user; + managed; + id; + async edit(options) { + const emoji = await Guild.prototype.editEmoji.call({ + id: this.guildId, + session: this.session + }, this.id, options); + return emoji; + } + async delete({ reason } = {}) { + await Guild.prototype.deleteEmoji.call({ + id: this.guildId, + session: this.session + }, this.id, { + reason + }); + return this; + } + get url() { + return EMOJI_URL(this.id, this.animated); + } +} +const textBasedChannels = [ + ChannelTypes.DM, + ChannelTypes.GroupDm, + ChannelTypes.GuildPrivateThread, + ChannelTypes.GuildPublicThread, + ChannelTypes.GuildNews, + ChannelTypes.GuildVoice, + ChannelTypes.GuildText, +]; +class TextChannel { + constructor(session, data){ + this.session = session; + this.id = data.id; + this.name = data.name; + this.type = data.type; + this.rateLimitPerUser = data.rate_limit_per_user ?? 0; + this.nsfw = !!data.nsfw ?? false; + if (data.last_message_id) { + this.lastMessageId = data.last_message_id; + } + if (data.last_pin_timestamp) { + this.lastPinTimestamp = data.last_pin_timestamp; + } + } + session; + id; + name; + type; + lastMessageId; + lastPinTimestamp; + rateLimitPerUser; + nsfw; + static applyTo(klass, ignore = []) { + const methods = [ + "fetchPins", + "createInvite", + "fetchMessages", + "sendTyping", + "pinMessage", + "unpinMessage", + "addReaction", + "removeReaction", + "nukeReactions", + "fetchPins", + "sendMessage", + "editMessage", + "createWebhook", + ]; + for (const method of methods){ + if (ignore.includes(method)) continue; + klass.prototype[method] = TextChannel.prototype[method]; + } + } + async fetchPins() { + const messages = await this.session.rest.runMethod(this.session.rest, "GET", CHANNEL_PINS(this.id)); + return messages[0] ? messages.map((x)=>new Message(this.session, x)) : []; + } + async createInvite(options) { + const invite = await this.session.rest.runMethod(this.session.rest, "POST", CHANNEL_INVITES(this.id), options ? { + max_age: options.maxAge, + max_uses: options.maxUses, + temporary: options.temporary, + unique: options.unique, + target_type: options.targetType, + target_user_id: options.targetUserId, + target_application_id: options.targetApplicationId + } : {}); + return new Invite(this.session, invite); + } + async fetchMessages(options) { + if (options?.limit > 100) throw Error("Values must be between 0-100"); + const messages = await this.session.rest.runMethod(this.session.rest, "GET", CHANNEL_MESSAGES(this.id, options)); + return messages[0] ? messages.map((x)=>new Message(this.session, x)) : []; + } + async sendTyping() { + await this.session.rest.runMethod(this.session.rest, "POST", CHANNEL_TYPING(this.id)); + } + async pinMessage(messageId) { + await Message.prototype.pin.call({ + id: messageId, + channelId: this.id, + session: this.session + }); + } + async unpinMessage(messageId) { + await Message.prototype.unpin.call({ + id: messageId, + channelId: this.id, + session: this.session + }); + } + async addReaction(messageId, reaction) { + await Message.prototype.addReaction.call({ + channelId: this.id, + id: messageId, + session: this.session + }, reaction); + } + async removeReaction(messageId, reaction, options) { + await Message.prototype.removeReaction.call({ + channelId: this.id, + id: messageId, + session: this.session + }, reaction, options); + } + async removeReactionEmoji(messageId, reaction) { + await Message.prototype.removeReactionEmoji.call({ + channelId: this.id, + id: messageId, + session: this.session + }, reaction); + } + async nukeReactions(messageId) { + await Message.prototype.nukeReactions.call({ + channelId: this.id, + id: messageId + }); + } + async fetchReactions(messageId, reaction, options) { + const users = await Message.prototype.fetchReactions.call({ + channelId: this.id, + id: messageId, + session: this.session + }, reaction, options); + return users; + } + sendMessage(options) { + return Message.prototype.reply.call({ + channelId: this.id, + session: this.session + }, options); + } + editMessage(messageId, options) { + return Message.prototype.edit.call({ + channelId: this.id, + id: messageId, + session: this.session + }, options); + } + async createWebhook(options) { + const webhook = await this.session.rest.runMethod(this.session.rest, "POST", CHANNEL_WEBHOOKS(this.id), { + name: options.name, + avatar: options.avatar ? urlToBase64(options.avatar) : undefined, + reason: options.reason + }); + return new Webhook(this.session, webhook); + } +} +class GuildChannel extends BaseChannel { + constructor(session, data, guildId){ + super(session, data); + this.type = data.type; + this.guildId = guildId; + this.position = data.position; + data.topic ? this.topic = data.topic : null; + data.parent_id ? this.parentId = data.parent_id : undefined; + } + type; + guildId; + topic; + position; + parentId; + async fetchInvites() { + const invites = await this.session.rest.runMethod(this.session.rest, "GET", CHANNEL_INVITES(this.id)); + return invites.map((invite)=>new Invite(this.session, invite)); + } + async edit(options) { + const channel = await this.session.rest.runMethod(this.session.rest, "PATCH", CHANNEL(this.id), { + name: options.name, + type: "type" in options ? options.type : undefined, + position: options.position, + topic: "topic" in options ? options.topic : undefined, + nsfw: "nfsw" in options ? options.nfsw : undefined, + rate_limit_per_user: "rateLimitPerUser" in options ? options.rateLimitPerUser : undefined, + bitrate: "bitrate" in options ? options.bitrate : undefined, + user_limit: "userLimit" in options ? options.userLimit : undefined, + permissions_overwrites: options.permissionOverwrites, + parent_id: "parentId" in options ? options.parentId : undefined, + rtc_region: "rtcRegion" in options ? options.rtcRegion : undefined, + video_quality_mode: "videoQualityMode" in options ? options.videoQualityMode : undefined, + default_auto_archive_duration: "defaultAutoArchiveDuration" in options ? options.defaultAutoArchiveDuration : undefined + }); + return ChannelFactory.from(this.session, channel); + } + async getArchivedThreads(options) { + let func; + switch(options.type){ + case "public": + func = THREAD_ARCHIVED_PUBLIC; + break; + case "private": + func = THREAD_START_PRIVATE; + break; + case "privateJoinedThreads": + func = THREAD_ARCHIVED_PRIVATE_JOINED; + break; + } + const { threads , members , has_more } = await this.session.rest.runMethod(this.session.rest, "GET", func(this.id, options)); + return { + threads: Object.fromEntries(threads.map((thread)=>[ + thread.id, + new ThreadChannel(this.session, thread, this.id) + ])), + members: Object.fromEntries(members.map((threadMember)=>[ + threadMember.id, + new ThreadMember(this.session, threadMember) + ])), + hasMore: has_more + }; + } + async createThread(options) { + const thread = await this.session.rest.runMethod(this.session.rest, "POST", "messageId" in options ? THREAD_START_PUBLIC(this.id, options.messageId) : THREAD_START_PRIVATE(this.id), { + name: options.name, + auto_archive_duration: options.autoArchiveDuration + }); + return new ThreadChannel(this.session, thread, thread.guild_id ?? this.guildId); + } +} +class BaseVoiceChannel extends GuildChannel { + constructor(session, data, guildId){ + super(session, data, guildId); + this.bitRate = data.bitrate; + this.userLimit = data.user_limit ?? 0; + this.videoQuality = data.video_quality_mode; + this.nsfw = !!data.nsfw; + this.type = data.type; + if (data.rtc_region) { + this.rtcRegion = data.rtc_region; + } + } + type; + bitRate; + userLimit; + rtcRegion; + videoQuality; + nsfw; + async connect(options) { + const shardId = calculateShardId(this.session.gateway, BigInt(super.guildId)); + const shard = this.session.gateway.manager.shards.get(shardId); + if (!shard) { + throw new Error(`Shard (id: ${shardId} not found`); + } + await shard.send({ + op: GatewayOpcodes.VoiceStateUpdate, + d: { + guild_id: super.guildId, + channel_id: super.id, + self_mute: Boolean(options?.selfMute), + self_deaf: options?.selfDeaf ?? true + } + }); + } +} +class DMChannel extends BaseChannel { + constructor(session, data){ + super(session, data); + this.user = new User(this.session, data.recipents.find((r)=>r.id !== this.session.botId)); + this.type = data.type; + if (data.last_message_id) { + this.lastMessageId = data.last_message_id; + } + } + type; + user; + lastMessageId; + async close() { + const channel = await this.session.rest.runMethod(this.session.rest, "DELETE", CHANNEL(this.id)); + return new DMChannel(this.session, channel); + } +} +TextChannel.applyTo(DMChannel); +class VoiceChannel extends BaseVoiceChannel { + constructor(session, data, guildId){ + super(session, data, guildId); + this.type = data.type; + } + type; +} +TextChannel.applyTo(VoiceChannel); +class NewsChannel extends GuildChannel { + constructor(session, data, guildId){ + super(session, data, guildId); + this.type = data.type; + this.defaultAutoArchiveDuration = data.default_auto_archive_duration; + } + type; + defaultAutoArchiveDuration; + crosspostMessage(messageId) { + return Message.prototype.crosspost.call({ + id: messageId, + channelId: this.id, + session: this.session + }); + } + get publishMessage() { + return this.crosspostMessage; + } +} +TextChannel.applyTo(NewsChannel); +class StageChannel extends BaseVoiceChannel { + constructor(session, data, guildId){ + super(session, data, guildId); + this.type = data.type; + this.topic = data.topic ? data.topic : undefined; + } + type; + topic; +} +class ThreadChannel extends GuildChannel { + constructor(session, data, guildId){ + super(session, data, guildId); + this.type = data.type; + this.archived = !!data.thread_metadata?.archived; + this.archiveTimestamp = data.thread_metadata?.archive_timestamp; + this.autoArchiveDuration = data.thread_metadata?.auto_archive_duration; + this.locked = !!data.thread_metadata?.locked; + this.messageCount = data.message_count; + this.memberCount = data.member_count; + this.ownerId = data.owner_id; + if (data.member) { + this.member = new ThreadMember(session, data.member); + } + } + type; + archived; + archiveTimestamp; + autoArchiveDuration; + locked; + messageCount; + memberCount; + member; + ownerId; + async joinThread() { + await this.session.rest.runMethod(this.session.rest, "PUT", THREAD_ME(this.id)); + } + async addToThread(guildMemberId) { + await this.session.rest.runMethod(this.session.rest, "PUT", THREAD_USER(this.id, guildMemberId)); + } + async leaveToThread(guildMemberId) { + await this.session.rest.runMethod(this.session.rest, "DELETE", THREAD_USER(this.id, guildMemberId)); + } + removeMember(memberId = this.session.botId) { + return ThreadMember.prototype.quitThread.call({ + id: this.id, + session: this.session + }, memberId); + } + fetchMember(memberId = this.session.botId) { + return ThreadMember.prototype.fetchMember.call({ + id: this.id, + session: this.session + }, memberId); + } + async fetchMembers() { + const members = await this.session.rest.runMethod(this.session.rest, "GET", THREAD_MEMBERS(this.id)); + return members.map((threadMember)=>new ThreadMember(this.session, threadMember)); + } +} +TextChannel.applyTo(ThreadChannel); +class GuildTextChannel extends GuildChannel { + constructor(session, data, guildId){ + super(session, data, guildId); + this.type = data.type; + } + type; +} +TextChannel.applyTo(GuildTextChannel); +class ChannelFactory { + static fromGuildChannel(session, channel) { + switch(channel.type){ + case ChannelTypes.GuildPublicThread: + case ChannelTypes.GuildPrivateThread: + return new ThreadChannel(session, channel, channel.guild_id); + case ChannelTypes.GuildText: + return new GuildTextChannel(session, channel, channel.guild_id); + case ChannelTypes.GuildNews: + return new NewsChannel(session, channel, channel.guild_id); + case ChannelTypes.GuildVoice: + return new VoiceChannel(session, channel, channel.guild_id); + case ChannelTypes.GuildStageVoice: + return new StageChannel(session, channel, channel.guild_id); + default: + throw new Error("Channel was not implemented"); + } + } + static from(session, channel) { + switch(channel.type){ + case ChannelTypes.GuildPublicThread: + case ChannelTypes.GuildPrivateThread: + return new ThreadChannel(session, channel, channel.guild_id); + case ChannelTypes.GuildText: + return new GuildTextChannel(session, channel, channel.guild_id); + case ChannelTypes.GuildNews: + return new NewsChannel(session, channel, channel.guild_id); + case ChannelTypes.DM: + return new DMChannel(session, channel); + case ChannelTypes.GuildVoice: + return new VoiceChannel(session, channel, channel.guild_id); + case ChannelTypes.GuildStageVoice: + return new StageChannel(session, channel, channel.guild_id); + default: + if (textBasedChannels.includes(channel.type)) { + return new TextChannel(session, channel); + } + throw new Error("Channel was not implemented"); + } + } +} +class AnonymousGuild extends BaseGuild { + constructor(session, data){ + super(session, data); + this.splashHash = data.splash ? Util.iconHashToBigInt(data.splash) : undefined; + this.bannerHash = data.banner ? Util.iconHashToBigInt(data.banner) : undefined; + this.verificationLevel = data.verification_level; + this.vanityUrlCode = data.vanity_url_code ? data.vanity_url_code : undefined; + this.nsfwLevel = data.nsfw_level; + this.description = data.description ? data.description : undefined; + this.premiumSubscriptionCount = data.premium_subscription_count; + } + splashHash; + bannerHash; + verificationLevel; + vanityUrlCode; + nsfwLevel; + description; + premiumSubscriptionCount; + splashURL(options = { + size: 128 + }) { + if (this.splashHash) { + return Util.formatImageURL(GUILD_SPLASH(this.id, Util.iconBigintToHash(this.splashHash)), options.size, options.format); + } + } + bannerURL(options = { + size: 128 + }) { + if (this.bannerHash) { + return Util.formatImageURL(GUILD_BANNER(this.id, Util.iconBigintToHash(this.bannerHash)), options.size, options.format); + } + } +} +class InviteGuild extends AnonymousGuild { + constructor(session, data){ + super(session, data); + if (data.welcome_screen) { + this.welcomeScreen = new WelcomeScreen(session, data.welcome_screen); + } + } + welcomeScreen; +} +class Guild extends BaseGuild { + constructor(session, data){ + super(session, data); + this.splashHash = data.splash ? Util.iconHashToBigInt(data.splash) : undefined; + this.discoverySplashHash = data.discovery_splash ? Util.iconHashToBigInt(data.discovery_splash) : undefined; + this.ownerId = data.owner_id; + this.widgetEnabled = !!data.widget_enabled; + this.widgetChannelId = data.widget_channel_id ? data.widget_channel_id : undefined; + this.vefificationLevel = data.verification_level; + this.defaultMessageNotificationLevel = data.default_message_notifications; + this.explicitContentFilterLevel = data.explicit_content_filter; + this.members = new Map(data.members?.map((member)=>[ + data.id, + new Member(session, { + ...member, + user: member.user + }, data.id) + ])); + this.roles = new Map(data.roles.map((role)=>[ + data.id, + new Role(session, role, data.id) + ])); + this.emojis = new Map(data.emojis.map((guildEmoji)=>[ + guildEmoji.id, + new GuildEmoji(session, guildEmoji, data.id) + ])); + this.channels = new Map(data.channels?.map((guildChannel)=>[ + guildChannel.id, + new GuildChannel(session, guildChannel, data.id) + ])); + } + splashHash; + discoverySplashHash; + ownerId; + widgetEnabled; + widgetChannelId; + vefificationLevel; + defaultMessageNotificationLevel; + explicitContentFilterLevel; + members; + roles; + emojis; + channels; + async editBotNickname(options) { + const result = await this.session.rest.runMethod(this.session.rest, "PATCH", USER_NICK(this.id), options); + return result?.nick; + } + async createEmoji(options) { + if (options.image && !options.image.startsWith("data:image/")) { + options.image = await urlToBase64(options.image); + } + const emoji = await this.session.rest.runMethod(this.session.rest, "POST", GUILD_EMOJIS(this.id), options); + return new GuildEmoji(this.session, emoji, this.id); + } + async deleteEmoji(id, { reason } = {}) { + await this.session.rest.runMethod(this.session.rest, "DELETE", GUILD_EMOJI(this.id, id), { + reason + }); + } + async editEmoji(id, options) { + const emoji = await this.session.rest.runMethod(this.session.rest, "PATCH", GUILD_EMOJI(this.id, id), options); + return new GuildEmoji(this.session, emoji, this.id); + } + async createRole(options) { + let icon; + if (options.iconHash) { + if (typeof options.iconHash === "string") { + icon = options.iconHash; + } else { + icon = Util.iconBigintToHash(options.iconHash); + } + } + const role = await this.session.rest.runMethod(this.session.rest, "PUT", GUILD_ROLES(this.id), { + name: options.name, + color: options.color, + icon, + unicode_emoji: options.unicodeEmoji, + hoist: options.hoist, + mentionable: options.mentionable + }); + return new Role(this.session, role, this.id); + } + async deleteRole(roleId) { + await this.session.rest.runMethod(this.session.rest, "DELETE", GUILD_ROLE(this.id, roleId)); + } + async editRole(roleId, options) { + const role = await this.session.rest.runMethod(this.session.rest, "PATCH", GUILD_ROLE(this.id, roleId), { + name: options.name, + color: options.color, + hoist: options.hoist, + mentionable: options.mentionable + }); + return new Role(this.session, role, this.id); + } + async addRole(memberId, roleId, { reason } = {}) { + await this.session.rest.runMethod(this.session.rest, "PUT", GUILD_MEMBER_ROLE(this.id, memberId, roleId), { + reason + }); + } + async removeRole(memberId, roleId, { reason } = {}) { + await this.session.rest.runMethod(this.session.rest, "DELETE", GUILD_MEMBER_ROLE(this.id, memberId, roleId), { + reason + }); + } + async moveRoles(options) { + const roles = await this.session.rest.runMethod(this.session.rest, "PATCH", GUILD_ROLES(this.id), options); + return roles.map((role)=>new Role(this.session, role, this.id)); + } + async deleteInvite(inviteCode) { + await this.session.rest.runMethod(this.session.rest, "DELETE", INVITE(inviteCode), {}); + } + async fetchInvite(inviteCode, options) { + const inviteMetadata = await this.session.rest.runMethod(this.session.rest, "GET", INVITE(inviteCode, options)); + return new Invite(this.session, inviteMetadata); + } + async fetchInvites() { + const invites = await this.session.rest.runMethod(this.session.rest, "GET", GUILD_INVITES(this.id)); + return invites.map((invite)=>new Invite(this.session, invite)); + } + async banMember(memberId, options) { + await this.session.rest.runMethod(this.session.rest, "PUT", GUILD_BAN(this.id, memberId), options ? { + delete_message_days: options.deleteMessageDays, + reason: options.reason + } : {}); + } + async kickMember(memberId, { reason }) { + await this.session.rest.runMethod(this.session.rest, "DELETE", GUILD_MEMBER(this.id, memberId), { + reason + }); + } + async unbanMember(memberId) { + await this.session.rest.runMethod(this.session.rest, "DELETE", GUILD_BAN(this.id, memberId)); + } + async editMember(memberId, options) { + const member = await this.session.rest.runMethod(this.session.rest, "PATCH", GUILD_MEMBER(this.id, memberId), { + nick: options.nick, + roles: options.roles, + mute: options.mute, + deaf: options.deaf, + channel_id: options.channelId, + communication_disabled_until: options.communicationDisabledUntil ? new Date(options.communicationDisabledUntil).toISOString() : undefined + }); + return new Member(this.session, member, this.id); + } + async pruneMembers(options) { + const result = await this.session.rest.runMethod(this.session.rest, "POST", GUILD_PRUNE(this.id), { + days: options.days, + compute_prune_count: options.computePruneCount, + include_roles: options.includeRoles + }); + return result.pruned; + } + async getPruneCount() { + const result = await this.session.rest.runMethod(this.session.rest, "GET", GUILD_PRUNE(this.id)); + return result.pruned; + } + async getActiveThreads() { + const { threads , members } = await this.session.rest.runMethod(this.session.rest, "GET", THREAD_ACTIVE(this.id)); + return { + threads: Object.fromEntries(threads.map((thread)=>[ + thread.id, + new ThreadChannel(this.session, thread, this.id) + ])), + members: Object.fromEntries(members.map((threadMember)=>[ + threadMember.id, + new ThreadMember(this.session, threadMember) + ])) + }; + } + async leave() {} + async delete() { + await this.session.rest.runMethod(this.session.rest, "DELETE", GUILDS()); + } + static async create(session, options) { + const guild = await session.rest.runMethod(session.rest, "POST", GUILDS(), { + name: options.name, + afk_channel_id: options.afkChannelId, + afk_timeout: options.afkTimeout, + default_message_notifications: options.defaultMessageNotifications, + explicit_content_filter: options.explicitContentFilter, + system_channel_flags: options.systemChannelFlags, + verification_level: options.verificationLevel, + icon: "iconURL" in options ? options.iconURL || urlToBase64(options.iconURL) : options.iconHash || Util.iconBigintToHash(options.iconHash), + channels: options.channels?.map((channel)=>({ + name: channel.name, + nsfw: channel.nsfw, + id: channel.id, + bitrate: channel.bitrate, + parent_id: channel.parentId, + permission_overwrites: channel.permissionOverwrites, + rtc_region: channel.rtcRegion, + user_limit: channel.userLimit, + video_quality_mode: channel.videoQualityMode, + rate_limit_per_user: channel.rateLimitPerUser + })), + roles: options.roles?.map((role)=>({ + name: role.name, + id: role.id, + color: role.color, + mentionable: role.mentionable, + hoist: role.hoist, + position: role.position, + unicode_emoji: role.unicodeEmoji, + icon: options.iconURL || urlToBase64(options.iconURL) + })) + }); + return new Guild(session, guild); + } + async edit(session, options) { + const guild = await session.rest.runMethod(session.rest, "PATCH", GUILDS(), { + name: options.name, + afk_channel_id: options.afkChannelId, + afk_timeout: options.afkTimeout, + default_message_notifications: options.defaultMessageNotifications, + explicit_content_filter: options.explicitContentFilter, + system_channel_flags: options.systemChannelFlags, + verification_level: options.verificationLevel, + icon: "iconURL" in options ? options.iconURL || urlToBase64(options.iconURL) : options.iconHash || Util.iconBigintToHash(options.iconHash), + splash: "splashURL" in options ? options.splashURL || urlToBase64(options.splashURL) : options.splashHash || Util.iconBigintToHash(options.iconHash), + banner: "bannerURL" in options ? options.bannerURL || urlToBase64(options.bannerURL) : options.bannerHash || Util.iconBigintToHash(options.bannerHash), + discovery_splash: "discoverySplashURL" in options ? options.discoverySplashURL || urlToBase64(options.discoverySplashURL) : options.discoverySplashHash || Util.iconBigintToHash(options.discoverySplashHash), + owner_id: options.ownerId, + rules_channel_id: options.rulesChannelId, + public_updates_channel_id: options.publicUpdatesChannelId, + preferred_locale: options.preferredLocale, + features: options.features, + description: options.description, + premiumProgressBarEnabled: options.premiumProgressBarEnabled + }); + return new Guild(session, guild); + } +} +class Invite { + constructor(session, data){ + this.session = session; + this.guild = data.guild ? new InviteGuild(session, data.guild) : undefined; + this.approximateMemberCount = data.approximate_member_count ? data.approximate_member_count : undefined; + this.approximatePresenceCount = data.approximate_presence_count ? data.approximate_presence_count : undefined; + this.code = data.code; + this.expiresAt = data.expires_at ? Number.parseInt(data.expires_at) : undefined; + this.inviter = data.inviter ? new User(session, data.inviter) : undefined; + this.targetUser = data.target_user ? new User(session, data.target_user) : undefined; + this.targetApplication = data.target_application ? new Application(session, data.target_application) : undefined; + this.targetType = data.target_type; + if (data.channel) { + const guildId = data.guild && data.guild?.id ? data.guild.id : ""; + this.channel = new GuildChannel(session, data.channel, guildId); + } + if (data.guild_scheduled_event) { + this.guildScheduledEvent = { + id: data.guild_scheduled_event.id, + guildId: data.guild_scheduled_event.guild_id, + channelId: data.guild_scheduled_event.channel_id ? data.guild_scheduled_event.channel_id : undefined, + creatorId: data.guild_scheduled_event.creator_id ? data.guild_scheduled_event.creator_id : undefined, + name: data.guild_scheduled_event.name, + description: data.guild_scheduled_event.description ? data.guild_scheduled_event.description : undefined, + scheduledStartTime: data.guild_scheduled_event.scheduled_start_time, + scheduledEndTime: data.guild_scheduled_event.scheduled_end_time ? data.guild_scheduled_event.scheduled_end_time : undefined, + privacyLevel: data.guild_scheduled_event.privacy_level, + status: data.guild_scheduled_event.status, + entityType: data.guild_scheduled_event.entity_type, + entityId: data.guild ? data.guild.id : undefined, + entityMetadata: data.guild_scheduled_event.entity_metadata ? data.guild_scheduled_event.entity_metadata : undefined, + creator: data.guild_scheduled_event.creator ? new User(session, data.guild_scheduled_event.creator) : undefined, + userCount: data.guild_scheduled_event.user_count ? data.guild_scheduled_event.user_count : undefined, + image: data.guild_scheduled_event.image ? data.guild_scheduled_event.image : undefined + }; + } + if (data.stage_instance) { + const guildId1 = data.guild && data.guild?.id ? data.guild.id : ""; + this.stageInstance = { + members: data.stage_instance.members.map((m)=>new Member(session, m, guildId1)), + participantCount: data.stage_instance.participant_count, + speakerCount: data.stage_instance.speaker_count, + topic: data.stage_instance.topic + }; + } + } + session; + guild; + approximateMemberCount; + approximatePresenceCount; + code; + expiresAt; + inviter; + targetUser; + targetType; + channel; + stageInstance; + guildScheduledEvent; + targetApplication; + async delete() { + await Guild.prototype.deleteInvite.call(this.guild, this.code); + return this; + } +} +var PrivacyLevels; +(function(PrivacyLevels) { + PrivacyLevels[PrivacyLevels["Public"] = 1] = "Public"; + PrivacyLevels[PrivacyLevels["GuildOnly"] = 2] = "GuildOnly"; +})(PrivacyLevels || (PrivacyLevels = {})); +class StageInstance { + constructor(session, data){ + this.session = session; + this.id = data.id; + this.channelId = data.channel_id; + this.guildId = data.guild_id; + this.topic = data.topic; + this.privacyLevel = data.privacy_level; + this.discoverableDisabled = data.discoverable_disabled; + this.guildScheduledEventId = data.guild_scheduled_event_id; + } + session; + id; + channelId; + guildId; + topic; + privacyLevel; + discoverableDisabled; + guildScheduledEventId; + async edit(options) { + const stageInstance = await this.session.rest.runMethod(this.session.rest, "PATCH", STAGE_INSTANCE(this.id), { + topic: options.topic, + privacy_level: options.privacyLevel + }); + return new StageInstance(this.session, stageInstance); + } + async delete() { + await this.session.rest.runMethod(this.session.rest, "DELETE", STAGE_INSTANCE(this.id)); + } +} +class ScheduledEvent { + constructor(session, data){ + this.session = session; + this.id = data.id; + this.guildId = data.guild_id; + this.channelId = data.channel_id; + this.creatorId = data.creator_id ? data.creator_id : undefined; + this.name = data.name; + this.description = data.description; + this.scheduledStartTime = data.scheduled_start_time; + this.scheduledEndTime = data.scheduled_end_time; + this.privacyLevel = PrivacyLevels.GuildOnly; + this.status = data.status; + this.entityType = data.entity_type; + this.entityMetadata = data.entity_metadata ? data.entity_metadata : undefined; + this.creator = data.creator ? new User(session, data.creator) : undefined; + this.userCount = data.user_count; + this.image = data.image ? data.image : undefined; + } + session; + id; + guildId; + channelId; + creatorId; + name; + description; + scheduledStartTime; + scheduledEndTime; + privacyLevel; + status; + entityType; + entityMetadata; + creator; + userCount; + image; +} +var StatusTypes; +(function(StatusTypes) { + StatusTypes[StatusTypes["online"] = 0] = "online"; + StatusTypes[StatusTypes["dnd"] = 1] = "dnd"; + StatusTypes[StatusTypes["idle"] = 2] = "idle"; + StatusTypes[StatusTypes["invisible"] = 3] = "invisible"; + StatusTypes[StatusTypes["offline"] = 4] = "offline"; +})(StatusTypes || (StatusTypes = {})); +class Presence { + constructor(session, data){ + this.session = session; + this.user = new User(this.session, data.user); + this.guildId = data.guild_id; + this.status = StatusTypes[data.status]; + this.activities = data.activities.map((activity)=>Object.create({ + name: activity.name, + type: activity.type, + url: activity.url ? activity.url : undefined, + createdAt: activity.created_at, + timestamps: activity.timestamps, + applicationId: activity.application_id, + details: activity.details ? activity.details : undefined, + state: activity.state, + emoji: activity.emoji ? activity.emoji : undefined, + party: activity.party ? activity.party : undefined, + assets: activity.assets ? { + largeImage: activity.assets.large_image, + largeText: activity.assets.large_text, + smallImage: activity.assets.small_image, + smallText: activity.assets.small_text + } : null, + secrets: activity.secrets ? activity.secrets : undefined, + instance: !!activity.instance, + flags: activity.flags, + buttons: activity.buttons + })); + this.clientStatus = data.client_status; + } + session; + user; + guildId; + status; + activities; + clientStatus; +} +class Integration { + constructor(session, data){ + this.id = data.id; + this.session = session; + data.guild_id ? this.guildId = data.guild_id : null; + this.name = data.name; + this.type = data.type; + this.enabled = !!data.enabled; + this.syncing = !!data.syncing; + this.roleId = data.role_id; + this.enableEmoticons = !!data.enable_emoticons; + this.expireBehavior = data.expire_behavior; + this.expireGracePeriod = data.expire_grace_period; + this.syncedAt = data.synced_at; + this.subscriberCount = data.subscriber_count; + this.revoked = !!data.revoked; + this.user = data.user ? new User(session, data.user) : undefined; + this.account = { + id: data.account.id, + name: data.account.name + }; + if (data.application) { + this.application = { + id: data.application.id, + name: data.application.name, + icon: data.application.icon ? data.application.icon : undefined, + description: data.application.description, + bot: data.application.bot ? new User(session, data.application.bot) : undefined + }; + } + } + session; + id; + guildId; + name; + type; + enabled; + syncing; + roleId; + enableEmoticons; + expireBehavior; + expireGracePeriod; + syncedAt; + subscriberCount; + revoked; + user; + account; + application; +} +class BaseInteraction { + constructor(session, data){ + this.session = session; + this.id = data.id; + this.token = data.token; + this.type = data.type; + this.guildId = data.guild_id; + this.channelId = data.channel_id; + this.applicationId = data.application_id; + this.version = data.version; + const perms = data.app_permissions; + if (perms) { + this.appPermissions = new Permissions(BigInt(perms)); + } + if (!data.guild_id) { + this.user = new User(session, data.user); + } else { + this.member = new Member(session, data.member, data.guild_id); + } + } + session; + id; + token; + type; + guildId; + channelId; + applicationId; + user; + member; + appPermissions; + version; + get createdTimestamp() { + return Snowflake.snowflakeToTimestamp(this.id); + } + get createdAt() { + return new Date(this.createdTimestamp); + } + isCommand() { + return this.type === InteractionTypes.ApplicationCommand; + } + isAutoComplete() { + return this.type === InteractionTypes.ApplicationCommandAutocomplete; + } + isComponent() { + return this.type === InteractionTypes.MessageComponent; + } + isPing() { + return this.type === InteractionTypes.Ping; + } + isModalSubmit() { + return this.type === InteractionTypes.ModalSubmit; + } + inGuild() { + return !!this.guildId; + } +} +function transformOasisInteractionDataOption(o) { + const output = { + ...o, + Otherwise: o.value + }; + switch(o.type){ + case ApplicationCommandOptionTypes.String: + output.String = o.value; + break; + case ApplicationCommandOptionTypes.Number: + output.Number = o.value; + break; + case ApplicationCommandOptionTypes.Integer: + output.Integer = o.value; + break; + case ApplicationCommandOptionTypes.Boolean: + output.Boolean = o.value; + break; + case ApplicationCommandOptionTypes.Role: + output.Role = BigInt(o.value); + break; + case ApplicationCommandOptionTypes.User: + output.User = BigInt(o.value); + break; + case ApplicationCommandOptionTypes.Channel: + output.Channel = BigInt(o.value); + break; + case ApplicationCommandOptionTypes.Mentionable: + case ApplicationCommandOptionTypes.SubCommand: + case ApplicationCommandOptionTypes.SubCommandGroup: + default: + output.Otherwise = o.value; + } + return output; +} +class CommandInteractionOptionResolver { + #subcommand; + #group; + hoistedOptions; + resolved; + constructor(options, resolved){ + this.hoistedOptions = options?.map(transformOasisInteractionDataOption) ?? []; + if (this.hoistedOptions[0]?.type === ApplicationCommandOptionTypes.SubCommandGroup) { + this.#group = this.hoistedOptions[0].name; + this.hoistedOptions = (this.hoistedOptions[0].options ?? []).map(transformOasisInteractionDataOption); + } + if (this.hoistedOptions[0]?.type === ApplicationCommandOptionTypes.SubCommand) { + this.#subcommand = this.hoistedOptions[0].name; + this.hoistedOptions = (this.hoistedOptions[0].options ?? []).map(transformOasisInteractionDataOption); + } + this.resolved = resolved; + } + getTypedOption(name, type, properties, required) { + const option = this.get(name, required); + if (!option) { + return; + } + if (option.type !== type) {} + if (required === true && properties.every((prop)=>typeof option[prop] === "undefined")) { + throw new TypeError(`Properties ${properties.join(", ")} are missing in option ${name}`); + } + return option; + } + get(name, required) { + const option = this.hoistedOptions.find((o)=>typeof name === "number" ? o.name === name.toString() : o.name === name); + if (!option) { + if (required && name in this.hoistedOptions.map((o)=>o.name)) { + throw new TypeError("Option marked as required was undefined"); + } + return; + } + return option; + } + getString(name, required = false) { + const option = this.getTypedOption(name, ApplicationCommandOptionTypes.String, [ + "Otherwise" + ], required); + return option?.Otherwise ?? undefined; + } + getNumber(name, required = false) { + const option = this.getTypedOption(name, ApplicationCommandOptionTypes.Number, [ + "Otherwise" + ], required); + return option?.Otherwise ?? undefined; + } + getInteger(name, required = false) { + const option = this.getTypedOption(name, ApplicationCommandOptionTypes.Integer, [ + "Otherwise" + ], required); + return option?.Otherwise ?? undefined; + } + getBoolean(name, required = false) { + const option = this.getTypedOption(name, ApplicationCommandOptionTypes.Boolean, [ + "Otherwise" + ], required); + return option?.Otherwise ?? undefined; + } + getUser(name, required = false) { + const option = this.getTypedOption(name, ApplicationCommandOptionTypes.User, [ + "Otherwise" + ], required); + return option?.Otherwise ?? undefined; + } + getChannel(name, required = false) { + const option = this.getTypedOption(name, ApplicationCommandOptionTypes.Channel, [ + "Otherwise" + ], required); + return option?.Otherwise ?? undefined; + } + getMentionable(name, required = false) { + const option = this.getTypedOption(name, ApplicationCommandOptionTypes.Mentionable, [ + "Otherwise" + ], required); + return option?.Otherwise ?? undefined; + } + getRole(name, required = false) { + const option = this.getTypedOption(name, ApplicationCommandOptionTypes.Role, [ + "Otherwise" + ], required); + return option?.Otherwise ?? undefined; + } + getAttachment(name, required = false) { + const option = this.getTypedOption(name, ApplicationCommandOptionTypes.Attachment, [ + "Otherwise" + ], required); + return option?.Otherwise ?? undefined; + } + getFocused(full = false) { + const focusedOption = this.hoistedOptions.find((option)=>option.focused); + if (!focusedOption) { + throw new TypeError("No option found"); + } + return full ? focusedOption : focusedOption.Otherwise; + } + getSubCommand(required = true) { + if (required && !this.#subcommand) { + throw new TypeError("Option marked as required was undefined"); + } + return [ + this.#subcommand, + this.hoistedOptions + ]; + } + getSubCommandGroup(required = false) { + if (required && !this.#group) { + throw new TypeError("Option marked as required was undefined"); + } + return [ + this.#group, + this.hoistedOptions + ]; + } +} +class CommandInteraction extends BaseInteraction { + constructor(session, data){ + super(session, data); + this.type = data.type; + this.commandId = data.data.id; + this.commandName = data.data.name; + this.commandType = data.data.type; + this.commandGuildId = data.data.guild_id; + this.options = new CommandInteractionOptionResolver(data.data.options ?? []); + this.resolved = { + users: new Map(), + members: new Map(), + roles: new Map(), + attachments: new Map(), + messages: new Map() + }; + if (data.data.resolved?.users) { + for (const [id, u] of Object.entries(data.data.resolved.users)){ + this.resolved.users.set(id, new User(session, u)); + } + } + if (data.data.resolved?.members && !!super.guildId) { + for (const [id1, m] of Object.entries(data.data.resolved.members)){ + this.resolved.members.set(id1, new Member(session, m, super.guildId)); + } + } + if (data.data.resolved?.roles && !!super.guildId) { + for (const [id2, r] of Object.entries(data.data.resolved.roles)){ + this.resolved.roles.set(id2, new Role(session, r, super.guildId)); + } + } + if (data.data.resolved?.attachments) { + for (const [id3, a] of Object.entries(data.data.resolved.attachments)){ + this.resolved.attachments.set(id3, new Attachment(session, a)); + } + } + if (data.data.resolved?.messages) { + for (const [id4, m1] of Object.entries(data.data.resolved.messages)){ + this.resolved.messages.set(id4, new Message(session, m1)); + } + } + } + type; + commandId; + commandName; + commandType; + commandGuildId; + resolved; + options; + responded = false; + async sendFollowUp(options) { + const message = await Webhook.prototype.execute.call({ + id: this.applicationId, + token: this.token, + session: this.session + }, options); + return message; + } + async respond({ type , data: options }) { + const data = { + content: options?.content, + custom_id: options?.customId, + file: options?.files, + allowed_mentions: options?.allowedMentions, + flags: options?.flags, + chocies: options?.choices, + embeds: options?.embeds, + title: options?.title + }; + if (!this.responded) { + await this.session.rest.sendRequest(this.session.rest, { + url: INTERACTION_ID_TOKEN(this.id, this.token), + method: "POST", + payload: this.session.rest.createRequestBody(this.session.rest, { + method: "POST", + body: { + type, + data, + file: options?.files + }, + headers: { + "Authorization": "" + } + }) + }); + this.responded = true; + return; + } + return this.sendFollowUp(data); + } +} +class ComponentInteraction extends BaseInteraction { + constructor(session, data){ + super(session, data); + this.type = data.type; + this.componentType = data.data.component_type; + this.customId = data.data.custom_id; + this.targetId = data.data.target_id; + this.values = data.data.values; + this.message = new Message(session, data.message); + } + type; + componentType; + customId; + targetId; + values; + message; + responded = false; + isButton() { + return this.componentType === MessageComponentTypes.Button; + } + isActionRow() { + return this.componentType === MessageComponentTypes.ActionRow; + } + isTextInput() { + return this.componentType === MessageComponentTypes.InputText; + } + isSelectMenu() { + return this.componentType === MessageComponentTypes.SelectMenu; + } + sendFollowUp(options) { + return CommandInteraction.prototype.sendFollowUp.call(this, options); + } + respond(options) { + return CommandInteraction.prototype.respond.call(this, options); + } +} +class PingInteraction extends BaseInteraction { + constructor(session, data){ + super(session, data); + this.type = data.type; + this.commandId = data.data.id; + this.commandName = data.data.name; + this.commandType = data.data.type; + this.commandGuildId = data.data.guild_id; + } + type; + commandId; + commandName; + commandType; + commandGuildId; + async pong() { + await this.session.rest.runMethod(this.session.rest, "POST", INTERACTION_ID_TOKEN(this.id, this.token), { + type: InteractionResponseTypes.Pong + }); + } +} +class AutoCompleteInteraction extends BaseInteraction { + constructor(session, data){ + super(session, data); + this.type = data.type; + this.commandId = data.data.id; + this.commandName = data.data.name; + this.commandType = data.data.type; + this.commandGuildId = data.data.guild_id; + } + type; + commandId; + commandName; + commandType; + commandGuildId; + async respond(choices) { + await this.session.rest.runMethod(this.session.rest, "POST", INTERACTION_ID_TOKEN(this.id, this.token), { + data: { + choices + }, + type: InteractionResponseTypes.ApplicationCommandAutocompleteResult + }); + } +} +class ModalSubmitInteraction extends BaseInteraction { + constructor(session, data){ + super(session, data); + this.type = data.type; + this.componentType = data.data.component_type; + this.customId = data.data.custom_id; + this.targetId = data.data.target_id; + this.values = data.data.values; + this.components = data.data?.components?.map(ModalSubmitInteraction.transformComponent); + if (data.message) { + this.message = new Message(session, data.message); + } + } + type; + componentType; + customId; + targetId; + values; + message; + components; + static transformComponent(component) { + return { + type: component.type, + components: component.components.map((component)=>{ + return { + customId: component.custom_id, + value: component.value + }; + }) + }; + } + inMessage() { + return !!this.message; + } +} +class InteractionFactory { + static from(session, interaction) { + switch(interaction.type){ + case InteractionTypes.Ping: + return new PingInteraction(session, interaction); + case InteractionTypes.ApplicationCommand: + return new CommandInteraction(session, interaction); + case InteractionTypes.MessageComponent: + return new ComponentInteraction(session, interaction); + case InteractionTypes.ApplicationCommandAutocomplete: + return new AutoCompleteInteraction(session, interaction); + case InteractionTypes.ModalSubmit: + return new ModalSubmitInteraction(session, interaction); + } + } +} +const READY = (session, shardId, payload)=>{ + session.applicationId = payload.application.id; + session.botId = payload.user.id; + session.emit("ready", { + ...payload, + user: new User(session, payload.user) + }, shardId); +}; +const MESSAGE_CREATE = (session, _shardId, message)=>{ + session.emit("messageCreate", new Message(session, message)); +}; +const MESSAGE_UPDATE = (session, _shardId, new_message)=>{ + if (!new_message.edited_timestamp) { + const message = { + session, + id: new_message.id, + guildId: new_message.guild_id, + channelId: new_message.channel_id + }; + Object.setPrototypeOf(message, Message.prototype); + session.emit("messageUpdate", message); + return; + } + session.emit("messageUpdate", new Message(session, new_message)); +}; +const MESSAGE_DELETE = (session, _shardId, { id , channel_id , guild_id })=>{ + session.emit("messageDelete", { + id, + channelId: channel_id, + guildId: guild_id + }); +}; +const GUILD_CREATE = (session, _shardId, guild)=>{ + session.emit("guildCreate", new Guild(session, guild)); +}; +const GUILD_DELETE = (session, _shardId, guild)=>{ + session.emit("guildDelete", { + id: guild.id, + unavailable: true + }); +}; +const GUILD_MEMBER_ADD = (session, _shardId, member)=>{ + session.emit("guildMemberAdd", new Member(session, member, member.guild_id)); +}; +const GUILD_MEMBER_UPDATE = (session, _shardId, member)=>{ + session.emit("guildMemberUpdate", new Member(session, member, member.guild_id)); +}; +const GUILD_MEMBER_REMOVE = (session, _shardId, member)=>{ + session.emit("guildMemberRemove", new User(session, member.user), member.guild_id); +}; +const GUILD_BAN_ADD = (session, _shardId, data)=>{ + session.emit("guildBanAdd", { + guildId: data.guild_id, + user: data.user + }); +}; +const GUILD_BAN_REMOVE = (session, _shardId, data)=>{ + session.emit("guildBanRemove", { + guildId: data.guild_id, + user: data.user + }); +}; +const GUILD_EMOJIS_UPDATE = (session, _shardId, data)=>{ + session.emit("guildEmojisUpdate", { + guildId: data.guild_id, + emojis: data.emojis + }); +}; +const GUILD_ROLE_CREATE = (session, _shardId, data)=>{ + session.emit("guildRoleCreate", { + guildId: data.guild_id, + role: data.role + }); +}; +const GUILD_ROLE_UPDATE = (session, _shardId, data)=>{ + session.emit("guildRoleUpdate", { + guildId: data.guild_id, + role: data.role + }); +}; +const GUILD_ROLE_DELETE = (session, _shardId, data)=>{ + session.emit("guildRoleDelete", { + guildId: data.guild_id, + roleId: data.role_id + }); +}; +const TYPING_START = (session, _shardId, payload)=>{ + session.emit("typingStart", { + channelId: payload.channel_id, + guildId: payload.guild_id ? payload.guild_id : undefined, + userId: payload.user_id, + timestamp: payload.timestamp, + member: payload.guild_id ? new Member(session, payload.member, payload.guild_id) : undefined + }); +}; +const INTERACTION_CREATE = (session, _shardId, interaction)=>{ + session.emit("interactionCreate", InteractionFactory.from(session, interaction)); +}; +const CHANNEL_CREATE = (session, _shardId, channel)=>{ + session.emit("channelCreate", ChannelFactory.from(session, channel)); +}; +const CHANNEL_UPDATE = (session, _shardId, channel)=>{ + session.emit("channelUpdate", ChannelFactory.from(session, channel)); +}; +const CHANNEL_DELETE = (session, _shardId, channel)=>{ + if (!channel.guild_id) return; + session.emit("channelDelete", new GuildChannel(session, channel, channel.guild_id)); +}; +const THREAD_CREATE = (session, _shardId, channel)=>{ + if (!channel.guild_id) return; + session.emit("threadCreate", new ThreadChannel(session, channel, channel.guild_id)); +}; +const THREAD_UPDATE = (session, _shardId, channel)=>{ + if (!channel.guild_id) return; + session.emit("threadUpdate", new ThreadChannel(session, channel, channel.guild_id)); +}; +const THREAD_DELETE = (session, _shardId, channel)=>{ + if (!channel.guild_id) return; + session.emit("threadDelete", new ThreadChannel(session, channel, channel.guild_id)); +}; +const THREAD_MEMBER_UPDATE = (session, _shardId, payload)=>{ + session.emit("threadMemberUpdate", { + guildId: payload.guild_id, + id: payload.id, + userId: payload.user_id, + joinedAt: payload.joined_at, + flags: payload.flags + }); +}; +const THREAD_MEMBERS_UPDATE = (session, _shardId, payload)=>{ + session.emit("threadMembersUpdate", { + memberCount: payload.member_count, + addedMembers: payload.added_members ? payload.added_members.map((tm)=>new ThreadMember(session, tm)) : undefined, + removedMemberIds: payload.removed_member_ids ? payload.removed_member_ids : undefined, + guildId: payload.guild_id, + id: payload.id + }); +}; +const THREAD_LIST_SYNC = (session, _shardId, payload)=>{ + session.emit("threadListSync", { + guildId: payload.guild_id, + channelIds: payload.channel_ids ?? [], + threads: payload.threads.map((channel)=>new ThreadChannel(session, channel, payload.guild_id)), + members: payload.members.map((member)=>new ThreadMember(session, member)) + }); +}; +const CHANNEL_PINS_UPDATE = (session, _shardId, payload)=>{ + session.emit("channelPinsUpdate", { + guildId: payload.guild_id, + channelId: payload.channel_id, + lastPinTimestamp: payload.last_pin_timestamp ? Date.parse(payload.last_pin_timestamp) : undefined + }); +}; +const USER_UPDATE = (session, _shardId, payload)=>{ + session.emit("userUpdate", new User(session, payload)); +}; +const PRESENCE_UPDATE = (session, _shardId, payload)=>{ + session.emit("presenceUpdate", new Presence(session, payload)); +}; +const WEBHOOKS_UPDATE = (session, _shardId, webhook)=>{ + session.emit("webhooksUpdate", { + guildId: webhook.guild_id, + channelId: webhook.channel_id + }); +}; +const INTEGRATION_CREATE = (session, _shardId, payload)=>{ + session.emit("integrationCreate", new Integration(session, payload)); +}; +const INTEGRATION_UPDATE = (session, _shardId, payload)=>{ + session.emit("integrationCreate", new Integration(session, payload)); +}; +const INTEGRATION_DELETE = (session, _shardId, payload)=>{ + session.emit("integrationDelete", { + id: payload.id, + guildId: payload.guild_id, + applicationId: payload.application_id + }); +}; +const AUTO_MODERATION_RULE_CREATE = (session, _shardId, payload)=>{ + session.emit("autoModerationRuleCreate", new AutoModerationRule(session, payload)); +}; +const AUTO_MODERATION_RULE_UPDATE = (session, _shardId, payload)=>{ + session.emit("autoModerationRuleUpdate", new AutoModerationRule(session, payload)); +}; +const AUTO_MODERATION_RULE_DELETE = (session, _shardId, payload)=>{ + session.emit("autoModerationRuleDelete", new AutoModerationRule(session, payload)); +}; +const AUTO_MODERATION_ACTION_EXECUTE = (session, _shardId, payload)=>{ + session.emit("autoModerationActionExecution", new AutoModerationExecution(session, payload)); +}; +const MESSAGE_REACTION_ADD = (session, _shardId, reaction)=>{ + session.emit("messageReactionAdd", NewMessageReactionAdd(session, reaction)); +}; +const MESSAGE_REACTION_REMOVE = (session, _shardId, reaction)=>{ + session.emit("messageReactionRemove", NewMessageReactionAdd(session, reaction)); +}; +const MESSAGE_REACTION_REMOVE_ALL = (session, _shardId, reaction)=>{ + session.emit("messageReactionRemoveAll", NewMessageReactionAdd(session, reaction)); +}; +const MESSAGE_REACTION_REMOVE_EMOJI = (session, _shardId, reaction)=>{ + session.emit("messageReactionRemoveEmoji", NewMessageReactionAdd(session, reaction)); +}; +const INVITE_CREATE = (session, _shardId, invite)=>{ + session.emit("inviteCreate", NewInviteCreate(session, invite)); +}; +const INVITE_DELETE = (session, _shardId, data)=>{ + session.emit("inviteDelete", { + channelId: data.channel_id, + guildId: data.guild_id, + code: data.code + }); +}; +const STAGE_INSTANCE_CREATE = (session, _shardId, payload)=>{ + session.emit("stageInstanceCreate", new StageInstance(session, payload)); +}; +const STAGE_INSTANCE_UPDATE = (session, _shardId, payload)=>{ + session.emit("stageInstanceUpdate", new StageInstance(session, payload)); +}; +const STAGE_INSTANCE_DELETE = (session, _shardId, payload)=>{ + session.emit("stageInstanceDelete", new StageInstance(session, payload)); +}; +const GUILD_SCHEDULED_EVENT_CREATE = (session, _shardId, payload)=>{ + session.emit("guildScheduledEventCreate", new ScheduledEvent(session, payload)); +}; +const GUILD_SCHEDULED_EVENT_UPDATE = (session, _shardId, payload)=>{ + session.emit("guildScheduledEventUpdate", new ScheduledEvent(session, payload)); +}; +const GUILD_SCHEDULED_EVENT_DELETE = (session, _shardId, payload)=>{ + session.emit("guildScheduledEventDelete", new ScheduledEvent(session, payload)); +}; +const GUILD_SCHEDULED_EVENT_USER_ADD = (session, _shardId, payload)=>{ + session.emit("guildScheduledEventUserAdd", { + scheduledEventId: payload.guild_scheduled_event_id, + userId: payload.user_id, + guildId: payload.guild_id + }); +}; +const GUILD_SCHEDULED_EVENT_USER_REMOVE = (session, _shardId, payload)=>{ + session.emit("guildScheduledEventUserRemove", { + scheduledEventId: payload.guild_scheduled_event_id, + userId: payload.user_id, + guildId: payload.guild_id + }); +}; +const raw = (session, shardId, data)=>{ + session.emit("raw", data, shardId); +}; +const mod = { + READY: READY, + MESSAGE_CREATE: MESSAGE_CREATE, + MESSAGE_UPDATE: MESSAGE_UPDATE, + MESSAGE_DELETE: MESSAGE_DELETE, + GUILD_CREATE: GUILD_CREATE, + GUILD_DELETE: GUILD_DELETE, + GUILD_MEMBER_ADD: GUILD_MEMBER_ADD, + GUILD_MEMBER_UPDATE: GUILD_MEMBER_UPDATE, + GUILD_MEMBER_REMOVE: GUILD_MEMBER_REMOVE, + GUILD_BAN_ADD: GUILD_BAN_ADD, + GUILD_BAN_REMOVE: GUILD_BAN_REMOVE, + GUILD_EMOJIS_UPDATE: GUILD_EMOJIS_UPDATE, + GUILD_ROLE_CREATE: GUILD_ROLE_CREATE, + GUILD_ROLE_UPDATE: GUILD_ROLE_UPDATE, + GUILD_ROLE_DELETE: GUILD_ROLE_DELETE, + TYPING_START: TYPING_START, + INTERACTION_CREATE: INTERACTION_CREATE, + CHANNEL_CREATE: CHANNEL_CREATE, + CHANNEL_UPDATE: CHANNEL_UPDATE, + CHANNEL_DELETE: CHANNEL_DELETE, + THREAD_CREATE: THREAD_CREATE, + THREAD_UPDATE: THREAD_UPDATE, + THREAD_DELETE: THREAD_DELETE, + THREAD_MEMBER_UPDATE: THREAD_MEMBER_UPDATE, + THREAD_MEMBERS_UPDATE: THREAD_MEMBERS_UPDATE, + THREAD_LIST_SYNC: THREAD_LIST_SYNC, + CHANNEL_PINS_UPDATE: CHANNEL_PINS_UPDATE, + USER_UPDATE: USER_UPDATE, + PRESENCE_UPDATE: PRESENCE_UPDATE, + WEBHOOKS_UPDATE: WEBHOOKS_UPDATE, + INTEGRATION_CREATE: INTEGRATION_CREATE, + INTEGRATION_UPDATE: INTEGRATION_UPDATE, + INTEGRATION_DELETE: INTEGRATION_DELETE, + AUTO_MODERATION_RULE_CREATE: AUTO_MODERATION_RULE_CREATE, + AUTO_MODERATION_RULE_UPDATE: AUTO_MODERATION_RULE_UPDATE, + AUTO_MODERATION_RULE_DELETE: AUTO_MODERATION_RULE_DELETE, + AUTO_MODERATION_ACTION_EXECUTE: AUTO_MODERATION_ACTION_EXECUTE, + MESSAGE_REACTION_ADD: MESSAGE_REACTION_ADD, + MESSAGE_REACTION_REMOVE: MESSAGE_REACTION_REMOVE, + MESSAGE_REACTION_REMOVE_ALL: MESSAGE_REACTION_REMOVE_ALL, + MESSAGE_REACTION_REMOVE_EMOJI: MESSAGE_REACTION_REMOVE_EMOJI, + INVITE_CREATE: INVITE_CREATE, + INVITE_DELETE: INVITE_DELETE, + STAGE_INSTANCE_CREATE: STAGE_INSTANCE_CREATE, + STAGE_INSTANCE_UPDATE: STAGE_INSTANCE_UPDATE, + STAGE_INSTANCE_DELETE: STAGE_INSTANCE_DELETE, + GUILD_SCHEDULED_EVENT_CREATE: GUILD_SCHEDULED_EVENT_CREATE, + GUILD_SCHEDULED_EVENT_UPDATE: GUILD_SCHEDULED_EVENT_UPDATE, + GUILD_SCHEDULED_EVENT_DELETE: GUILD_SCHEDULED_EVENT_DELETE, + GUILD_SCHEDULED_EVENT_USER_ADD: GUILD_SCHEDULED_EVENT_USER_ADD, + GUILD_SCHEDULED_EVENT_USER_REMOVE: GUILD_SCHEDULED_EVENT_USER_REMOVE, + raw: raw +}; +class Session extends EventEmitter { + options; + rest; + gateway; + #botId; + #applicationId; + set applicationId(id) { + this.#applicationId = id; + } + get applicationId() { + return this.#applicationId; + } + set botId(id) { + this.#botId = id; + } + get botId() { + return this.#botId; + } + constructor(options){ + super(); + this.options = options; + const defHandler = (shard, data)=>{ + mod.raw(this, shard.id, data); + if (!data.t || !data.d) { + return; + } + mod[data.t]?.(this, shard.id, data.d); + }; + this.rest = createRestManager({ + token: this.options.token, + debug: (text)=>{ + super.rawListeners("debug")?.forEach((fn)=>fn(text)); + }, + secretKey: this.options.rest?.secretKey ?? undefined + }); + this.gateway = createGatewayManager({ + gatewayBot: this.options.gateway?.data ?? {}, + gatewayConfig: { + token: this.options.token, + intents: this.options.intents + }, + handleDiscordPayload: this.options.rawHandler ?? defHandler + }); + this.#botId = getBotIdFromToken(options.token).toString(); + } + on(event, func) { + return super.on(event, func); + } + off(event, func) { + return super.off(event, func); + } + once(event, func) { + return super.once(event, func); + } + emit(event, ...params) { + return super.emit(event, ...params); + } + editStatus(shardId, status) { + const shard = this.gateway.manager.shards.get(shardId); + if (!shard) { + throw new Error(`Unknown shard ${shardId}`); + } + shard.send({ + op: GatewayOpcodes.PresenceUpdate, + d: { + status: status.status, + since: null, + afk: false, + activities: status.activities.map((activity)=>{ + return { + name: activity.name, + type: activity.type, + url: activity.url, + created_at: activity.createdAt, + timestamps: activity.timestamps, + application_id: this.applicationId, + details: activity.details, + state: activity.state, + emoji: activity.emoji || { + name: activity.emoji.name, + id: activity.emoji.id, + animated: activity.emoji.animated + }, + party: activity.party, + assets: activity.assets ? { + large_image: activity.assets.largeImage, + large_text: activity.assets.largeText, + small_image: activity.assets.smallImage, + small_text: activity.assets.smallText + } : undefined, + secrets: activity.secrets, + instance: activity.instance, + flags: activity.flags, + buttons: activity.buttons + }; + }) + } + }); + } + async fetchUser(id) { + const user = await this.rest.runMethod(this.rest, "GET", USER(id)); + if (!user.id) return; + return new User(this, user); + } + createApplicationCommand(options, guildId) { + return this.rest.runMethod(this.rest, "POST", guildId ? GUILD_APPLICATION_COMMANDS(this.applicationId, guildId) : APPLICATION_COMMANDS(this.applicationId), this.isContextApplicationCommand(options) ? { + name: options.name, + name_localizations: options.nameLocalizations, + type: options.type + } : { + name: options.name, + name_localizations: options.nameLocalizations, + description: options.description, + description_localizations: options.descriptionLocalizations, + type: options.type, + options: options.options, + default_member_permissions: options.defaultMemberPermissions ? new Permissions(options.defaultMemberPermissions).bitfield.toString() : undefined, + dm_permission: options.dmPermission + }); + } + deleteApplicationCommand(id, guildId) { + return this.rest.runMethod(this.rest, "DELETE", guildId ? GUILD_APPLICATION_COMMANDS(this.applicationId, guildId, id) : APPLICATION_COMMANDS(this.applicationId, id)); + } + updateApplicationCommandPermissions(guildId, id, bearerToken, options) { + return this.rest.runMethod(this.rest, "PUT", GUILD_APPLICATION_COMMANDS_PERMISSIONS(this.applicationId, guildId, id), { + permissions: options + }, { + headers: { + authorization: `Bearer ${bearerToken}` + } + }); + } + fetchApplicationCommand(id, options) { + return this.rest.runMethod(this.rest, "GET", options?.guildId ? GUILD_APPLICATION_COMMANDS_LOCALIZATIONS(this.applicationId, options.guildId, id, options?.withLocalizations) : APPLICATION_COMMANDS(this.applicationId, id)); + } + fetchApplicationCommandPermissions(guildId) { + return this.rest.runMethod(this.rest, "GET", GUILD_APPLICATION_COMMANDS_PERMISSIONS(this.applicationId, guildId)); + } + fetchApplicationCommandPermission(guildId, id) { + return this.rest.runMethod(this.rest, "GET", GUILD_APPLICATION_COMMANDS_PERMISSIONS(this.applicationId, guildId, id)); + } + upsertApplicationCommand(id, options, guildId) { + return this.rest.runMethod(this.rest, "PATCH", guildId ? GUILD_APPLICATION_COMMANDS(this.applicationId, guildId) : APPLICATION_COMMANDS(this.applicationId, id), this.isContextApplicationCommand(options) ? { + name: options.name, + type: options.type + } : { + name: options.name, + description: options.description, + type: options.type, + options: options.options + }); + } + upsertApplicationCommands(options, guildId) { + return this.rest.runMethod(this.rest, "PUT", guildId ? GUILD_APPLICATION_COMMANDS(this.applicationId, guildId) : APPLICATION_COMMANDS(this.applicationId), options.map((o)=>this.isContextApplicationCommand(o) ? { + name: o.name, + type: o.type + } : { + name: o.name, + description: o.description, + type: o.type, + options: o.options + })); + } + fetchCommands(guildId) { + return this.rest.runMethod(this.rest, "GET", guildId ? GUILD_APPLICATION_COMMANDS(this.applicationId, guildId) : APPLICATION_COMMANDS(this.applicationId)); + } + isContextApplicationCommand(cmd) { + return cmd.type === ApplicationCommandTypes.Message || cmd.type === ApplicationCommandTypes.User; + } + async start() { + const getGatewayBot = ()=>this.rest.runMethod(this.rest, "GET", GATEWAY_BOT()); + if (!Object.keys(this.options.gateway?.data ?? {}).length) { + const nonParsed = await getGatewayBot(); + this.gateway.gatewayBot = { + url: nonParsed.url, + shards: nonParsed.shards, + sessionStartLimit: { + total: nonParsed.session_start_limit.total, + remaining: nonParsed.session_start_limit.remaining, + resetAfter: nonParsed.session_start_limit.reset_after, + maxConcurrency: nonParsed.session_start_limit.max_concurrency + } + }; + this.gateway.lastShardId = this.gateway.gatewayBot.shards - 1; + this.gateway.manager.totalShards = this.gateway.gatewayBot.shards; + } + this.gateway.spawnShards(); + } +} +class Sticker { + constructor(session, data){ + this.session = session; + this.id = data.id; + this.packId = data.pack_id; + this.name = data.name; + this.description = data.description; + this.tags = data.tags.split(","); + this.type = data.type; + this.formatType = data.format_type; + this.available = !!data.available; + this.guildId = data.guild_id; + this.user = data.user ? new User(this.session, data.user) : undefined; + this.sortValue = data.sort_value; + } + session; + id; + packId; + name; + description; + tags; + type; + formatType; + available; + guildId; + user; + sortValue; + async fetchPremiumPack() { + const data = await this.session.rest.runMethod(this.session.rest, "GET", STICKER_PACKS()); + return { + id: data.id, + stickers: data.stickers.map((st)=>new Sticker(this.session, st)), + name: data.name, + skuId: data.sku_id, + coverStickerId: data.cover_sticker_id, + description: data.description, + bannerAssetId: data.banner_asset_id + }; + } +} +class ChoiceBuilder { + name; + value; + setName(name) { + this.name = name; + return this; + } + setValue(value) { + this.value = value; + return this; + } + toJSON() { + if (!this.name) throw new TypeError("Property 'name' is required"); + if (!this.value) throw new TypeError("Property 'value' is required"); + return { + name: this.name, + value: this.value + }; + } +} +class OptionBuilder { + required; + autocomplete; + constructor(type, name, description){ + this.type = type; + this.name = name; + this.description = description; + this.type = type; + this.name = name; + this.description = description; + } + setType(type) { + return this.type = type, this; + } + setName(name) { + return this.name = name, this; + } + setDescription(description) { + return this.description = description, this; + } + setRequired(required) { + return this.required = required, this; + } + toJSON() { + if (!this.type) throw new TypeError("Property 'type' is required"); + if (!this.name) throw new TypeError("Property 'name' is required"); + if (!this.description) { + throw new TypeError("Property 'description' is required"); + } + const applicationCommandOption = { + type: this.type, + name: this.name, + description: this.description, + required: this.required ? true : false + }; + return applicationCommandOption; + } + type; + name; + description; +} +class OptionBuilderLimitedValues extends OptionBuilder { + choices; + minValue; + maxValue; + constructor(type, name, description){ + super(); + this.type = type; + this.name = name; + this.description = description; + this.type = type; + this.name = name; + this.description = description; + } + setMinValue(n) { + return this.minValue = n, this; + } + setMaxValue(n) { + return this.maxValue = n, this; + } + addChoice(fn) { + const choice = fn(new ChoiceBuilder()); + this.choices ??= []; + this.choices.push(choice); + return this; + } + toJSON() { + return { + ...super.toJSON(), + choices: this.choices?.map((c)=>c.toJSON()) ?? [], + minValue: this.minValue, + maxValue: this.maxValue + }; + } + type; + name; + description; +} +class OptionBuilderString extends OptionBuilder { + choices; + constructor(type, name, description){ + super(); + this.type = type; + this.name = name; + this.description = description; + this.type = type; + this.name = name; + this.description = description; + } + addChoice(fn) { + const choice = fn(new ChoiceBuilder()); + this.choices ??= []; + this.choices.push(choice); + return this; + } + toJSON() { + return { + ...super.toJSON(), + choices: this.choices?.map((c)=>c.toJSON()) ?? [] + }; + } + type; + name; + description; +} +class OptionBuilderChannel extends OptionBuilder { + channelTypes; + constructor(type, name, description){ + super(); + this.type = type; + this.name = name; + this.description = description; + this.type = type; + this.name = name; + this.description = description; + } + addChannelTypes(...channels) { + this.channelTypes ??= []; + this.channelTypes.push(...channels); + return this; + } + toJSON() { + return { + ...super.toJSON(), + channelTypes: this.channelTypes ?? [] + }; + } + type; + name; + description; +} +class OptionBased { + options; + addOption(fn, type) { + const option = fn(new OptionBuilder(type)); + this.options ??= []; + this.options.push(option); + return this; + } + addNestedOption(fn) { + const option = fn(new OptionBuilder(ApplicationCommandOptionTypes.SubCommand)); + this.options ??= []; + this.options.push(option); + return this; + } + addStringOption(fn) { + const option = fn(new OptionBuilderString(ApplicationCommandOptionTypes.String)); + this.options ??= []; + this.options.push(option); + return this; + } + addIntegerOption(fn) { + const option = fn(new OptionBuilderLimitedValues(ApplicationCommandOptionTypes.Integer)); + this.options ??= []; + this.options.push(option); + return this; + } + addNumberOption(fn) { + const option = fn(new OptionBuilderLimitedValues(ApplicationCommandOptionTypes.Number)); + this.options ??= []; + this.options.push(option); + return this; + } + addBooleanOption(fn) { + return this.addOption(fn, ApplicationCommandOptionTypes.Boolean); + } + addSubCommand(fn) { + const option = fn(new OptionBuilderNested(ApplicationCommandOptionTypes.SubCommand)); + this.options ??= []; + this.options.push(option); + return this; + } + addSubCommandGroup(fn) { + const option = fn(new OptionBuilderNested(ApplicationCommandOptionTypes.SubCommandGroup)); + this.options ??= []; + this.options.push(option); + return this; + } + addUserOption(fn) { + return this.addOption(fn, ApplicationCommandOptionTypes.User); + } + addChannelOption(fn) { + const option = fn(new OptionBuilderChannel(ApplicationCommandOptionTypes.Channel)); + this.options ??= []; + this.options.push(option); + return this; + } + addRoleOption(fn) { + return this.addOption(fn, ApplicationCommandOptionTypes.Role); + } + addMentionableOption(fn) { + return this.addOption(fn, ApplicationCommandOptionTypes.Mentionable); + } + static applyTo(klass, ignore = []) { + const methods = [ + "addOption", + "addNestedOption", + "addStringOption", + "addIntegerOption", + "addNumberOption", + "addBooleanOption", + "addSubCommand", + "addSubCommandGroup", + "addUserOption", + "addChannelOption", + "addRoleOption", + "addMentionableOption", + ]; + for (const method of methods){ + if (ignore.includes(method)) continue; + klass.prototype[method] = OptionBased.prototype[method]; + } + } +} +class OptionBuilderNested extends OptionBuilder { + constructor(type, name, description){ + super(); + this.type = type; + this.name = name; + this.description = description; + this.type = type; + this.name = name; + this.description = description; + } + toJSON() { + if (!this.type) throw new TypeError("Property 'type' is required"); + if (!this.name) throw new TypeError("Property 'name' is required"); + if (!this.description) { + throw new TypeError("Property 'description' is required"); + } + return { + type: this.type, + name: this.name, + description: this.description, + options: this.options?.map((o)=>o.toJSON()) ?? [], + required: this.required ? true : false + }; + } + type; + name; + description; +} +OptionBased.applyTo(OptionBuilderNested); +class ApplicationCommandBuilder { + constructor(type = ApplicationCommandTypes.ChatInput, name = "", description = "", defaultMemberPermissions, nameLocalizations, descriptionLocalizations, dmPermission = true){ + this.type = type; + this.name = name; + this.description = description; + this.defaultMemberPermissions = defaultMemberPermissions; + this.nameLocalizations = nameLocalizations; + this.descriptionLocalizations = descriptionLocalizations; + this.dmPermission = dmPermission; + this.type = type; + this.name = name; + this.description = description; + this.defaultMemberPermissions = defaultMemberPermissions; + this.nameLocalizations = nameLocalizations; + this.descriptionLocalizations = descriptionLocalizations; + this.dmPermission = dmPermission; + } + setType(type) { + return this.type = type, this; + } + setName(name) { + return this.name = name, this; + } + setDescription(description) { + return this.description = description, this; + } + setDefaultMemberPermission(perm) { + return this.defaultMemberPermissions = perm, this; + } + setNameLocalizations(l) { + return this.nameLocalizations = l, this; + } + setDescriptionLocalizations(l) { + return this.descriptionLocalizations = l, this; + } + setDmPermission(perm) { + return this.dmPermission = perm, this; + } + type; + name; + description; + defaultMemberPermissions; + nameLocalizations; + descriptionLocalizations; + dmPermission; +} +class ChatInputApplicationCommandBuilder extends ApplicationCommandBuilder { + type = ApplicationCommandTypes.ChatInput; + toJSON() { + if (!this.type) throw new TypeError("Propety 'type' is required"); + if (!this.name) throw new TypeError("Propety 'name' is required"); + if (!this.description) { + throw new TypeError("Propety 'description' is required"); + } + return { + type: ApplicationCommandTypes.ChatInput, + name: this.name, + description: this.description, + options: this.options?.map((o)=>o.toJSON()) ?? [], + defaultMemberPermissions: this.defaultMemberPermissions, + nameLocalizations: this.nameLocalizations, + descriptionLocalizations: this.descriptionLocalizations, + dmPermission: this.dmPermission + }; + } +} +OptionBased.applyTo(ChatInputApplicationCommandBuilder); +const cache_sym = Symbol("@cache"); +function __default(session) { + const cache = { + guilds: new StructCache(session), + users: new StructCache(session), + dms: new StructCache(session), + emojis: new StructCache(session), + cache: cache_sym, + session + }; + session.on("raw", (data)=>{ + const raw = data.d; + switch(data.t){ + case "MESSAGE_CREATE": + messageBootstrapper(cache, raw, false); + break; + case "MESSAGE_UPDATE": + messageBootstrapper(cache, raw, !raw.edited_timestamp); + break; + case "CHANNEL_UPDATE": + case "CHANNEL_CREATE": + channelBootstrapper(cache, raw); + break; + case "GUILD_MEMBER_ADD": + memberBootstrapper(cache, raw, raw.guild_id); + break; + case "GUILD_CREATE": + guildBootstrapper(cache, raw); + break; + case "GUILD_DELETE": + cache.guilds.delete(raw.id); + break; + case "MESSAGE_REACTION_ADD": + reactionBootstrapper(cache, raw, false); + break; + case "MESSAGE_REACTION_REMOVE": + reactionBootstrapper(cache, raw, false); + break; + case "MESSAGE_REACTION_REMOVE_ALL": + reactionBootstrapperDeletions(cache, raw); + break; + } + }); + return cache; +} +class StructCache extends Map { + constructor(session, entries){ + super(entries); + this.session = session; + } + session; + get(key) { + return super.get(key); + } + set(key, value) { + return super.set(key, value); + } + has(key) { + return super.has(key); + } + clear() { + return super.clear(); + } + random(amount) { + const arr = [ + ...this.values() + ]; + if (typeof amount === "undefined") return arr[Math.floor(Math.random() * arr.length)]; + if (!arr.length) return []; + if (amount && amount > arr.length) amount = arr.length; + return Array.from({ + length: Math.min(amount, arr.length) + }, ()=>arr.splice(Math.floor(Math.random() * arr.length), 1)[0]); + } + find(fn) { + for (const [key, value] of this.entries()){ + if (fn(value, key, this)) return value; + } + return undefined; + } + filter(fn) { + const result = new StructCache(this.session); + for (const [key, value] of this.entries()){ + if (fn(value, key, this)) result.set(key, value); + } + return result; + } + forEach(fn) { + super.forEach((v, k)=>{ + fn(v, k, this); + }); + } + clone() { + return new StructCache(this.session, this.entries()); + } + concat(structures) { + const conc = this.clone(); + for (const structure of structures){ + if (!structure || !(structure instanceof StructCache)) continue; + for (const [key, value] of structure.entries()){ + conc.set(key, value); + } + } + return conc; + } + some(fn) { + for (const [key, value] of this.entries()){ + if (fn(value, key, this)) { + return true; + } + } + return false; + } + every(fn) { + for (const [key, value] of this.entries()){ + if (!fn(value, key, this)) { + return false; + } + } + return true; + } + first(amount) { + if (!amount || amount <= 1) { + return this.values().next().value; + } + const values = [ + ...this.values() + ]; + amount = Math.min(values.length, amount); + return values.slice(0, amount); + } + last(amount) { + const values = [ + ...this.values() + ]; + if (!amount || amount <= 1) { + return values[values.length - 1]; + } + amount = Math.min(values.length, amount); + return values.slice(-amount); + } + reverse() { + const entries = [ + ...this.entries() + ].reverse(); + this.clear(); + for (const [key, value] of entries)this.set(key, value); + return this; + } + map(fn) { + const result = []; + for (const [key, value] of this.entries()){ + result.push(fn(value, key, this)); + } + return result; + } + reduce(fn, initV) { + const entries = this.entries(); + const first = entries.next().value; + let result = initV; + if (result !== undefined) { + result = fn(result, first[1], first[0], this); + } else { + result = first; + } + for (const [key, value] of entries){ + result = fn(result, value, key, this); + } + return result; + } + get size() { + return super.size; + } + get empty() { + return this.size === 0; + } + updateFields(key, obj) { + const value = this.get(key); + if (!value) { + return; + } + for(const prop in obj){ + if (obj[prop]) { + value[prop] = obj[prop]; + } + } + return this.set(key, value); + } + getOr(key, or) { + return this.get(key) ?? or; + } + retrieve(key, fn) { + const value = this.get(key); + if (!value) { + return; + } + return fn(value); + } +} +function reactionBootstrapperDeletions(cache, payload) { + if (payload.guild_id) { + cache.guilds.retrieve(payload.guild_id, (guild)=>{ + guild.channels.retrieve(payload.channel_id, (channel)=>{ + channel.messages.retrieve(payload.message_id, (message)=>{ + message.reactions = []; + }); + }); + }); + } else { + cache.dms.retrieve(payload.channel_id, (channel)=>{ + channel.messages.retrieve(payload.message_id, (message)=>{ + message.reactions = []; + }); + }); + } +} +function reactionBootstrapper(cache, reaction, remove) { + cache.emojis.set(reaction.emoji.id ?? reaction.emoji.name, new Emoji(cache.session, reaction.emoji)); + function onAdd(message) { + const reactions = message.reactions.map((r)=>r.emoji.name); + const upsertData = { + count: 1, + emoji: reaction.emoji, + me: reaction.user_id === cache.session.botId + }; + if (reactions.length === 0) { + message.reactions = []; + } else if (!reactions.includes(reaction.emoji.name)) { + message.reactions.push(new MessageReaction(cache.session, upsertData)); + } else { + const current = message.reactions?.[reactions.indexOf(reaction.emoji.name)]; + if (current && message.reactions?.[message.reactions.indexOf(current)]) { + ++message.reactions[message.reactions.indexOf(current)].count; + } + } + } + function onRemove(message) { + const reactions = message.reactions.map((r)=>r.emoji.name); + if (reactions.indexOf(reaction.emoji.name) !== undefined) { + const current = message.reactions[reactions.indexOf(reaction.emoji.name)]; + if (current) { + if (current.count > 0) { + current.count--; + } + if (current.count === 0) { + message.reactions.splice(reactions?.indexOf(reaction.emoji.name), 1); + } + } + } + } + if (reaction.guild_id) { + cache.guilds.retrieve(reaction.guild_id, (guild)=>{ + guild.channels.retrieve(reaction.channel_id, (channel)=>{ + channel.messages.retrieve(reaction.message_id, (message)=>{ + if (remove) onRemove(message); + else onAdd(message); + }); + }); + }); + } else { + cache.dms.retrieve(reaction.channel_id, (channel)=>{ + channel.messages.retrieve(reaction.message_id, (message)=>{ + if (remove) onRemove(message); + else onAdd(message); + }); + }); + } +} +function userBootstrapper(cache, user) { + cache.users.set(user.id, new User(cache.session, user)); +} +function emojiBootstrapper(cache, emoji, guildId) { + if (!emoji.id) return; + cache.emojis.set(emoji.id, new GuildEmoji(cache.session, emoji, guildId)); +} +function channelBootstrapper(cache, channel) { + if (!channel.guild_id) return; + cache.guilds.retrieve(channel.guild_id, (guild)=>{ + if (textBasedChannels.includes(channel.type)) { + guild.channels.set(channel.id, Object.assign(ChannelFactory.fromGuildChannel(cache.session, channel), { + messages: new StructCache(cache.session) + })); + } else { + guild.channels.set(channel.id, ChannelFactory.fromGuildChannel(cache.session, channel)); + } + }); +} +function memberBootstrapper(cache, member, guildId) { + cache.guilds.retrieve(guildId, (guild)=>{ + guild.members.set(member.user.id, Object.assign(new Member(cache.session, member, guildId), { + userId: member.user.id, + get user () { + return cache.users.get(this.userId); + } + })); + }); +} +function messageBootstrapper(cache, message, partial) { + if (message.member) { + const member = Object.assign(message.member, { + user: message.author + }); + memberBootstrapper(cache, member, message.guild_id); + } + if (cache.dms.has(message.channel_id)) { + cache.dms.retrieve(message.channel_id, (dm)=>{ + dm.messages[partial ? "updateFields" : "set"](message.id, Object.assign(new Message(cache.session, message), { + authorId: message.author.id, + get author () { + return cache.users.get(this.authorId); + } + })); + }); + } else { + cache.guilds.retrieve(message.guild_id, (guild)=>guild.channels.retrieve(message.channel_id, (dm)=>{ + dm.messages[partial ? "updateFields" : "set"](message.id, Object.assign(new Message(cache.session, message), { + authorId: message.author.id, + get author () { + return cache.users.get(this.authorId); + } + })); + })); + } +} +function guildBootstrapper(cache, guild) { + const members = new StructCache(cache.session, guild.members?.map((data)=>{ + const obj = Object.assign(new Member(cache.session, data, guild.id), { + userId: data.user.id, + get user () { + return cache.users.get(this.userId); + } + }); + return [ + data.user.id, + obj + ]; + })); + const channels = new StructCache(cache.session, guild.channels?.map((data)=>{ + const obj = Object.assign(ChannelFactory.from(cache.session, data), { + messages: new Map() + }); + return [ + data.id, + obj + ]; + })); + cache.guilds.set(guild.id, Object.assign(new Guild(cache.session, guild), { + members, + channels + })); +} +export { cache_sym as cache_sym }; +export { StructCache as StructCache }; +export { reactionBootstrapperDeletions as reactionBootstrapperDeletions }; +export { reactionBootstrapper as reactionBootstrapper }; +export { userBootstrapper as userBootstrapper }; +export { emojiBootstrapper as emojiBootstrapper }; +export { channelBootstrapper as channelBootstrapper }; +export { memberBootstrapper as memberBootstrapper }; +export { messageBootstrapper as messageBootstrapper }; +export { guildBootstrapper as guildBootstrapper }; +export { __default as enableCache }; +export { Session as default }; diff --git a/egg.json b/egg.json index 75e1fbe..77ce825 100644 --- a/egg.json +++ b/egg.json @@ -1,27 +1,27 @@ { - "$schema": "https://x.nest.land/eggs@0.3.10/src/schema.json", - "name": "biscuit", - "entry": "./mod.ts", - "description": "A brand new bleeding edge non bloated Discord library", - "homepage": "https://github.com/oasisjs/biscuit", - "version": "0.1.0", - "releaseType": "patch", - "unstable": false, - "unlisted": false, - "files": [ - "./packages/**/*", - "./mod.ts", - "LICENSE", - "README.md" - ], - "ignore": [ - "npm", - "build.ts", - "scripts.ts", - ".git" - ], - "checkFormat": true, - "checkTests": false, - "checkInstallation": false, - "check": true + "$schema": "https://x.nest.land/eggs@0.3.10/src/schema.json", + "name": "biscuit", + "entry": "./mod.ts", + "description": "A brand new bleeding edge non bloated Discord library", + "homepage": "https://github.com/oasisjs/biscuit", + "version": "0.1.1", + "releaseType": "patch", + "unstable": false, + "unlisted": false, + "files": [ + "./packages/**/*", + "./mod.ts", + "LICENSE", + "README.md" + ], + "ignore": [ + "npm", + "build.ts", + "scripts.ts", + ".git" + ], + "checkFormat": true, + "checkTests": false, + "checkInstallation": false, + "check": true } diff --git a/examples/hello-bun/index.js b/examples/hello-bun/index.js index eba3d84..8922be1 100644 --- a/examples/hello-bun/index.js +++ b/examples/hello-bun/index.js @@ -3,7 +3,7 @@ * this example should work on most systems, but if it doesn't just clone the library and import everything from mod.ts */ -const { GatewayIntents, Session } = require("@oasisjs/biscuit"); +const { GatewayIntents, Session } = require("../mod.ts"); // if it didn't worked use: // const { GatewayIntents, Session } = require("@oasisjs/biscuit");