lunibee 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +12 -23
  2. package/dist/builders/components.d.ts +108 -0
  3. package/dist/builders/index.d.ts +1 -1
  4. package/dist/builders/index.js +178 -2
  5. package/dist/builders/index.js.map +3 -3
  6. package/dist/collection/index.d.ts +6 -0
  7. package/dist/collection/index.js +33 -2
  8. package/dist/collection/index.js.map +4 -4
  9. package/dist/core/events.d.ts +67 -3
  10. package/dist/core/index.d.ts +120 -90
  11. package/dist/core/index.js +816 -1021
  12. package/dist/core/index.js.map +20 -21
  13. package/dist/formatters/index.js.map +1 -1
  14. package/dist/index.d.ts +5 -4
  15. package/dist/index.js +2215 -1392
  16. package/dist/index.js.map +29 -26
  17. package/dist/managers/guild.d.ts +30 -0
  18. package/dist/managers/index.d.ts +56 -75
  19. package/dist/managers/index.js +339 -48
  20. package/dist/managers/index.js.map +16 -12
  21. package/dist/managers/message.d.ts +7 -12
  22. package/dist/managers/user.d.ts +20 -0
  23. package/dist/rest/index.d.ts +83 -1
  24. package/dist/rest/index.js +48 -8
  25. package/dist/rest/index.js.map +4 -4
  26. package/dist/rest/routes.d.ts +4 -1
  27. package/dist/sharding/index.js +4 -1
  28. package/dist/sharding/index.js.map +4 -4
  29. package/dist/structures/base.d.ts +99 -48
  30. package/dist/structures/embed.d.ts +65 -0
  31. package/dist/structures/index.d.ts +45 -25
  32. package/dist/structures/index.js +569 -36
  33. package/dist/structures/index.js.map +10 -8
  34. package/dist/structures/interactions.d.ts +72 -17
  35. package/dist/structures/resources.d.ts +9 -5
  36. package/dist/types/index.d.ts +530 -85
  37. package/dist/types/index.js +71 -1
  38. package/dist/types/index.js.map +3 -3
  39. package/dist/voice/index.js.map +1 -1
  40. package/dist/ws/index.js +4 -1
  41. package/dist/ws/index.js.map +4 -4
  42. package/package.json +15 -15
@@ -2,12 +2,12 @@
2
2
  "version": 3,
3
3
  "sources": ["../../packages/types/src/index.ts", "../../packages/ws/src/index.ts", "../../packages/sharding/src/bus.ts", "../../packages/sharding/src/index.ts"],
4
4
  "sourcesContent": [
5
- "/** Discord API snowflake identifier. */\r\nexport type Snowflake = string;\r\n\r\n/** Gateway intent bit flags supported by Discord (PascalCase). */\r\nexport const GatewayIntentBits = {\r\n Guilds: 1 << 0,\r\n GuildMembers: 1 << 1,\r\n GuildModeration: 1 << 2,\r\n GuildExpressions: 1 << 3,\r\n GuildIntegrations: 1 << 4,\r\n GuildWebhooks: 1 << 5,\r\n GuildInvites: 1 << 6,\r\n GuildVoiceStates: 1 << 7,\r\n GuildPresences: 1 << 8,\r\n GuildMessages: 1 << 9,\r\n GuildMessageReactions: 1 << 10,\r\n GuildMessageTyping: 1 << 11,\r\n DirectMessages: 1 << 12,\r\n DirectMessageReactions: 1 << 13,\r\n DirectMessageTyping: 1 << 14,\r\n MessageContent: 1 << 15,\r\n GuildScheduledEvents: 1 << 16,\r\n AutoModerationConfiguration: 1 << 20,\r\n AutoModerationExecution: 1 << 21,\r\n GuildMessagePolls: 1 << 24,\r\n DirectMessagePolls: 1 << 25,\r\n} as const;\r\n\r\n/** Idiomatic camelCase Gateway intent bit flags supported by Discord. */\r\nexport const IntentBits = {\r\n guild: 1 << 0,\r\n guilds: 1 << 0,\r\n guildMembers: 1 << 1,\r\n guildModeration: 1 << 2,\r\n guildBans: 1 << 2,\r\n guildExpressions: 1 << 3,\r\n guildEmojis: 1 << 3,\r\n guildEmojisAndStickers: 1 << 3,\r\n guildIntegrations: 1 << 4,\r\n guildWebhooks: 1 << 5,\r\n guildInvites: 1 << 6,\r\n guildVoiceStates: 1 << 7,\r\n guildPresences: 1 << 8,\r\n guildMessages: 1 << 9,\r\n guildMessage: 1 << 9,\r\n guildMessageReactions: 1 << 10,\r\n guildMessageTyping: 1 << 11,\r\n directMessages: 1 << 12,\r\n directMessageReactions: 1 << 13,\r\n directMessageTyping: 1 << 14,\r\n messageContent: 1 << 15,\r\n guildScheduledEvents: 1 << 16,\r\n autoModerationConfiguration: 1 << 20,\r\n autoModerationExecution: 1 << 21,\r\n guildMessagePolls: 1 << 24,\r\n directMessagePolls: 1 << 25,\r\n} as const;\r\n\r\n/** Alias for IntentBits. */\r\nexport const Intents = IntentBits;\r\n\r\n/** Gateway intent resolvable value (single bitfield, enum key, or array of bitfields/strings). */\r\nexport type GatewayIntentResolvable =\r\n | number\r\n | keyof typeof GatewayIntentBits\r\n | keyof typeof IntentBits\r\n | (\r\n number | keyof typeof GatewayIntentBits | keyof typeof IntentBits | string\r\n )[];\r\n\r\n/** Resolves any GatewayIntentResolvable into a raw bitfield integer. */\r\nexport function resolveGatewayIntents(\r\n intents: GatewayIntentResolvable,\r\n): number {\r\n if (typeof intents === \"number\") return intents;\r\n if (Array.isArray(intents)) {\r\n return intents.reduce<number>((acc, intent) => {\r\n return acc | resolveGatewayIntents(intent as any);\r\n }, 0);\r\n }\r\n if (typeof intents === \"string\") {\r\n if (intents in GatewayIntentBits)\r\n return (GatewayIntentBits as Record<string, number>)[intents]!;\r\n if (intents in IntentBits)\r\n return (IntentBits as Record<string, number>)[intents]!;\r\n const lower = intents.charAt(0).toLowerCase() + intents.slice(1);\r\n if (lower in IntentBits)\r\n return (IntentBits as Record<string, number>)[lower]!;\r\n const num = Number(intents);\r\n if (!Number.isNaN(num)) return num;\r\n }\r\n return 0;\r\n}\r\n\r\n/** Gateway connection properties (OS, browser, device). */\r\nexport interface GatewayProperties {\r\n os?: string;\r\n browser?: string;\r\n device?: string;\r\n [key: string]: unknown;\r\n}\r\n/** Gateway presence activity. */\r\nexport interface GatewayPresenceActivity {\r\n name: string;\r\n type?: number;\r\n url?: string;\r\n state?: string;\r\n}\r\n/** Gateway presence data. */\r\nexport interface GatewayPresence {\r\n status?: \"online\" | \"dnd\" | \"idle\" | \"invisible\" | \"offline\";\r\n activities?: GatewayPresenceActivity[];\r\n afk?: boolean;\r\n since?: number | null;\r\n}\r\n/** Client configuration. */\r\nexport interface ClientOptions {\r\n token: string;\r\n intents: GatewayIntentResolvable;\r\n gateway?: GatewayOptions;\r\n rest?: RESTOptions;\r\n}\r\n/** Gateway connection configuration. */\r\nexport interface GatewayOptions {\r\n intents?: GatewayIntentResolvable;\r\n reconnect?: boolean;\r\n maxReconnectAttempts?: number;\r\n reconnectBaseDelay?: number;\r\n reconnectMaxDelay?: number;\r\n shardId?: number;\r\n shardCount?: number;\r\n properties?: GatewayProperties;\r\n presence?: GatewayPresence;\r\n}\r\n\r\n/** REST request configuration. */\r\nexport interface RESTOptions {\r\n timeout?: number;\r\n retries?: number;\r\n baseURL?: string;\r\n}\r\n/** Discord user object. */\r\nexport interface UserData {\r\n id: Snowflake;\r\n username: string;\r\n discriminator?: string;\r\n global_name?: string | null;\r\n avatar?: string | null;\r\n bot?: boolean;\r\n system?: boolean;\r\n public_flags?: number;\r\n}\r\n/** Current authenticated bot user. */\r\nexport type ClientUser = UserData;\r\n/** Discord Gateway payload envelope. */\r\nexport interface GatewayPayload<T = unknown> {\r\n op: number;\r\n d: T | null;\r\n s: number | null;\r\n t: string | null;\r\n}\r\n/** Generic Discord API error payload. */\r\nexport interface APIError {\r\n code?: number;\r\n message?: string;\r\n errors?: Record<string, unknown>;\r\n}\r\n/** Discord message flags. */\r\nexport const MessageFlags = {\r\n Crossposted: 1,\r\n IsCrosspost: 2,\r\n SuppressEmbeds: 4,\r\n SourceMessageDeleted: 8,\r\n Urgent: 16,\r\n HasThread: 32,\r\n Ephemeral: 64,\r\n Loading: 128,\r\n IsComponentsV2: 32768,\r\n} as const;\r\n/** Discord channel types. */\r\nexport const ChannelType = {\r\n GuildText: 0,\r\n DM: 1,\r\n GuildVoice: 2,\r\n GroupDM: 3,\r\n GuildCategory: 4,\r\n GuildAnnouncement: 5,\r\n AnnouncementThread: 10,\r\n PublicThread: 11,\r\n PrivateThread: 12,\r\n GuildStageVoice: 13,\r\n GuildDirectory: 14,\r\n GuildForum: 15,\r\n GuildMedia: 16,\r\n} as const;\r\n\r\n/** Raw Discord embed object. */\r\nexport interface APIEmbed {\r\n title?: string;\r\n type?: string;\r\n description?: string;\r\n url?: string;\r\n timestamp?: string;\r\n color?: number;\r\n footer?: Record<string, unknown>;\r\n image?: Record<string, unknown>;\r\n thumbnail?: Record<string, unknown>;\r\n video?: Record<string, unknown>;\r\n provider?: Record<string, unknown>;\r\n author?: Record<string, unknown>;\r\n fields?: Array<Record<string, unknown>>;\r\n}\r\n/** Raw Discord attachment object. */\r\nexport interface APIAttachment {\r\n id: Snowflake;\r\n filename: string;\r\n description?: string | null;\r\n content_type?: string;\r\n size: number;\r\n url: string;\r\n proxy_url: string;\r\n height?: number | null;\r\n width?: number | null;\r\n ephemeral?: boolean;\r\n duration_secs?: number;\r\n waveform?: string;\r\n flags?: number;\r\n}\r\n/** Raw Discord message component object. */\r\nexport interface APIMessageComponent {\r\n type: number;\r\n id?: number;\r\n custom_id?: string;\r\n style?: number;\r\n label?: string;\r\n disabled?: boolean;\r\n emoji?: Record<string, unknown>;\r\n url?: string;\r\n options?: Array<Record<string, unknown>>;\r\n components?: APIMessageComponent[];\r\n}\r\n/** Raw Discord message reference. */\r\nexport interface APIMessageReference {\r\n type?: number;\r\n message_id?: Snowflake;\r\n channel_id?: Snowflake;\r\n guild_id?: Snowflake;\r\n fail_if_not_exists?: boolean;\r\n}\r\n/** Raw Discord message reaction. */\r\nexport interface APIMessageReaction {\r\n count: number;\r\n count_details?: Record<string, number>;\r\n me?: boolean;\r\n me_burst?: boolean;\r\n emoji: Record<string, unknown>;\r\n burst_colors?: string[];\r\n}\r\n/** Raw Discord message object. */\r\nexport interface APIMessage {\r\n id: Snowflake;\r\n channel_id: Snowflake;\r\n author: UserData;\r\n content: string;\r\n timestamp?: string;\r\n edited_timestamp?: string | null;\r\n tts?: boolean;\r\n mention_everyone?: boolean;\r\n mentions?: UserData[];\r\n mention_roles?: Snowflake[];\r\n mention_channels?: Array<Record<string, unknown>>;\r\n attachments?: APIAttachment[];\r\n embeds?: APIEmbed[];\r\n reactions?: APIMessageReaction[];\r\n nonce?: string | number | null;\r\n pinned?: boolean;\r\n webhook_id?: Snowflake;\r\n type?: number;\r\n activity?: Record<string, unknown>;\r\n application?: Record<string, unknown>;\r\n application_id?: Snowflake;\r\n message_reference?: APIMessageReference;\r\n flags?: number;\r\n referenced_message?: APIMessage | null;\r\n interaction_metadata?: Record<string, unknown>;\r\n thread?: Record<string, unknown>;\r\n components?: APIMessageComponent[];\r\n position?: number;\r\n role_subscription_data?: Record<string, unknown>;\r\n purchase_notification?: Record<string, unknown>;\r\n poll?: Record<string, unknown>;\r\n guild_id?: Snowflake;\r\n}\r\n/** Raw Discord channel object. */\r\nexport interface APIChannel {\r\n id: Snowflake;\r\n type: number;\r\n guild_id?: Snowflake;\r\n position?: number;\r\n permission_overwrites?: Array<Record<string, unknown>>;\r\n name?: string | null;\r\n topic?: string | null;\r\n nsfw?: boolean;\r\n last_message_id?: Snowflake | null;\r\n bitrate?: number;\r\n user_limit?: number;\r\n rate_limit_per_user?: number;\r\n recipients?: UserData[];\r\n icon?: string | null;\r\n owner_id?: Snowflake;\r\n application_id?: Snowflake;\r\n parent_id?: Snowflake | null;\r\n last_pin_timestamp?: string | null;\r\n rtc_region?: string | null;\r\n video_quality_mode?: number;\r\n message_count?: number;\r\n member_count?: number;\r\n thread_metadata?: Record<string, unknown>;\r\n default_auto_archive_duration?: number;\r\n flags?: number;\r\n total_message_sent?: number;\r\n available_tags?: Array<Record<string, unknown>>;\r\n default_reaction_emoji?: Record<string, unknown> | null;\r\n default_thread_rate_limit_per_user?: number;\r\n default_sort_order?: number | null;\r\n default_forum_layout?: number;\r\n}\r\n/** Raw Discord guild object. */\r\nexport interface APIGuild {\r\n id: Snowflake;\r\n name: string;\r\n icon?: string | null;\r\n icon_hash?: string | null;\r\n splash?: string | null;\r\n discovery_splash?: string | null;\r\n owner_id?: Snowflake;\r\n afk_channel_id?: Snowflake | null;\r\n afk_timeout?: number;\r\n widget_enabled?: boolean;\r\n widget_channel_id?: Snowflake | null;\r\n verification_level?: number;\r\n default_message_notifications?: number;\r\n explicit_content_filter?: number;\r\n roles?: Array<Record<string, unknown>>;\r\n emojis?: Array<Record<string, unknown>>;\r\n features?: string[];\r\n mfa_level?: number;\r\n application_id?: Snowflake | null;\r\n system_channel_id?: Snowflake | null;\r\n system_channel_flags?: number;\r\n rules_channel_id?: Snowflake | null;\r\n max_presences?: number | null;\r\n max_members?: number;\r\n vanity_url_code?: string | null;\r\n description?: string | null;\r\n banner?: string | null;\r\n premium_tier?: number;\r\n preferred_locale?: string;\r\n public_updates_channel_id?: Snowflake | null;\r\n max_video_channel_users?: number;\r\n approximate_member_count?: number;\r\n approximate_presence_count?: number;\r\n nsfw_level?: number;\r\n safety_alerts_channel_id?: Snowflake | null;\r\n}\r\n/** Raw Discord guild member object. */\r\nexport interface APIGuildMember {\r\n user: UserData;\r\n nick?: string | null;\r\n avatar?: string | null;\r\n roles: Snowflake[];\r\n joined_at: string;\r\n premium_since?: string | null;\r\n deaf?: boolean;\r\n mute?: boolean;\r\n flags?: number;\r\n pending?: boolean;\r\n permissions?: string;\r\n communication_disabled_until?: string | null;\r\n guild_id?: Snowflake;\r\n}\r\n/** Raw Discord reaction event payload. */\r\nexport interface APIMessageReactionEvent {\r\n user_id: Snowflake;\r\n channel_id: Snowflake;\r\n message_id: Snowflake;\r\n guild_id?: Snowflake;\r\n member?: APIGuildMember;\r\n emoji: Record<string, unknown>;\r\n message_author_id?: Snowflake;\r\n burst?: boolean;\r\n type?: number;\r\n}\r\n/** Raw Discord message deletion event payload. */\r\nexport interface APIMessageDeleteEvent {\r\n id: Snowflake;\r\n channel_id: Snowflake;\r\n guild_id?: Snowflake;\r\n}\r\n/** Raw Discord bulk message deletion event payload. */\r\nexport interface APIMessageDeleteBulkEvent {\r\n ids: Snowflake[];\r\n channel_id: Snowflake;\r\n guild_id?: Snowflake;\r\n}\r\n/** Raw Discord channel deletion event payload. */\r\nexport interface APIChannelDeleteEvent extends APIChannel {}\r\n/** Raw Discord guild deletion event payload. */\r\nexport interface APIGuildDeleteEvent {\r\n id: Snowflake;\r\n unavailable?: boolean;\r\n}\r\n/** Raw Discord thread lifecycle payload. */\r\nexport interface APIThreadEvent extends APIChannel {\r\n guild_id: Snowflake;\r\n member?: Record<string, unknown>;\r\n}\r\n/** Raw Discord READY event payload. */\r\nexport interface APIReadyEvent {\r\n v: number;\r\n user: UserData;\r\n guilds: Array<{ id: Snowflake; unavailable?: boolean }>;\r\n session_id: string;\r\n resume_gateway_url: string;\r\n shard?: [number, number];\r\n application?: { id: Snowflake; flags: number; [key: string]: unknown };\r\n}\r\n\r\n/** Discord application command option types. */\r\nexport const ApplicationCommandOptionType = {\r\n SubCommand: 1,\r\n SubCommandGroup: 2,\r\n String: 3,\r\n Integer: 4,\r\n Boolean: 5,\r\n User: 6,\r\n Channel: 7,\r\n Role: 8,\r\n Mentionable: 9,\r\n Number: 10,\r\n Attachment: 11,\r\n} as const;\r\n\r\n/** Discord application command types. */\r\nexport const ApplicationCommandType = {\r\n ChatInput: 1,\r\n User: 2,\r\n Message: 3,\r\n} as const;\r\n\r\n/** Raw Discord application command option. */\r\nexport interface APIApplicationCommandOption {\r\n type: number;\r\n name: string;\r\n description: string;\r\n required?: boolean;\r\n choices?: Array<{ name: string; value: string | number }>;\r\n options?: APIApplicationCommandOption[];\r\n min_value?: number;\r\n max_value?: number;\r\n min_length?: number;\r\n max_length?: number;\r\n autocomplete?: boolean;\r\n channel_types?: number[];\r\n}\r\n\r\n/** Raw Discord application command object (from API). */\r\nexport interface APIApplicationCommand {\r\n id: Snowflake;\r\n type?: number;\r\n application_id: Snowflake;\r\n guild_id?: Snowflake;\r\n name: string;\r\n description: string;\r\n options?: APIApplicationCommandOption[];\r\n default_member_permissions?: string | null;\r\n dm_permission?: boolean;\r\n nsfw?: boolean;\r\n version: Snowflake;\r\n}\r\n\r\n/** Data for creating/overwriting an application command. */\r\nexport interface ApplicationCommandData {\r\n name: string;\r\n description: string;\r\n type?: number;\r\n options?: APIApplicationCommandOption[];\r\n default_member_permissions?: string | null;\r\n dm_permission?: boolean;\r\n nsfw?: boolean;\r\n}\r\n\r\n/** Raw Discord role object. */\r\nexport interface APIRole {\r\n id: Snowflake;\r\n name: string;\r\n color: number;\r\n hoist: boolean;\r\n icon?: string | null;\r\n unicode_emoji?: string | null;\r\n position: number;\r\n permissions: string;\r\n managed: boolean;\r\n mentionable: boolean;\r\n tags?: Record<string, unknown>;\r\n flags?: number;\r\n}\r\n\r\n/** Raw Discord guild role event payload. */\r\nexport interface APIGuildRoleEvent {\r\n guild_id: Snowflake;\r\n role: APIRole;\r\n}\r\n\r\n/** Raw Discord guild role delete event payload. */\r\nexport interface APIGuildRoleDeleteEvent {\r\n guild_id: Snowflake;\r\n role_id: Snowflake;\r\n}\r\n\r\n/** Raw Discord guild ban event payload. */\r\nexport interface APIGuildBanEvent {\r\n guild_id: Snowflake;\r\n user: UserData;\r\n}\r\n\r\n/** Raw Discord emoji object. */\r\nexport interface APIEmoji {\r\n id: Snowflake | null;\r\n name: string | null;\r\n roles?: Snowflake[];\r\n user?: UserData;\r\n require_colons?: boolean;\r\n managed?: boolean;\r\n animated?: boolean;\r\n available?: boolean;\r\n}\r\n\r\n/** Raw Discord guild emojis update event payload. */\r\nexport interface APIGuildEmojisUpdateEvent {\r\n guild_id: Snowflake;\r\n emojis: APIEmoji[];\r\n}\r\n",
6
- "import {\n resolveGatewayIntents,\n type GatewayPayload,\n type GatewayProperties,\n type GatewayPresence,\n type GatewayIntentResolvable,\n} from \"@lunibee/types\";\n\n/** Discord Gateway opcodes. */\nexport const GatewayOpcodes = {\n Dispatch: 0,\n Heartbeat: 1,\n Identify: 2,\n PresenceUpdate: 3,\n VoiceStateUpdate: 4,\n Resume: 6,\n Reconnect: 7,\n RequestGuildMembers: 8,\n InvalidSession: 9,\n Hello: 10,\n HeartbeatAck: 11,\n} as const;\n/** Gateway connection lifecycle states. */\nexport enum GatewayState {\n /** Initial connection state. */ Connect = \"CONNECT\",\n /** Gateway HELLO received state. */ Hello = \"HELLO\",\n /** IDENTIFY operation in progress. */ Identify = \"IDENTIFY\",\n /** RESUME operation in progress. */ Resume = \"RESUME\",\n /** Gateway READY state. */ Ready = \"READY\",\n /** Gateway dispatch processing state. */ Dispatch = \"DISPATCH\",\n /** Heartbeat processing state. */ Heartbeat = \"HEARTBEAT\",\n /** Reconnect in progress. */ Reconnect = \"RECONNECT\",\n /** Gateway is permanently closed. */ Closed = \"CLOSED\",\n}\n/** Gateway protocol error. */\nexport class GatewayError extends Error {\n /** Gateway close/error code. */ public readonly code?: number;\n /** Creates a Gateway error. @param message Error message. @param code Optional Gateway code. @param options Optional error metadata. */ public constructor(\n message: string,\n code?: number,\n options?: ErrorOptions,\n ) {\n super(message, options);\n this.name = \"GatewayError\";\n this.code = code;\n }\n}\n/** Gateway connection configuration. */\nexport interface GatewayOptions {\n /** Authentication token. */ token: string;\n /** Gateway intent bitfield or resolvable. */ intents: GatewayIntentResolvable;\n /** Shard identifier. */ shardId?: number;\n /** Total shard count. */ shardCount?: number;\n /** Whether automatic reconnect is enabled. */ reconnect?: boolean;\n /** Maximum reconnect attempts. */ maxReconnectAttempts?: number;\n /** Initial reconnect delay. */ reconnectBaseDelay?: number;\n /** Maximum reconnect delay. */ reconnectMaxDelay?: number;\n /** Heartbeat acknowledgement timeout. */ heartbeatAckTimeout?: number;\n /** Zombie connection timeout. */ zombieTimeout?: number;\n /** Identification properties. */ properties?: GatewayProperties;\n /** Presence data. */ presence?: GatewayPresence;\n}\n/** Gateway event listener. */\ntype GatewayListener = (data: unknown) => unknown;\n/** Manages a Discord Gateway connection. */\nexport class Gateway {\n /** Current Gateway lifecycle state. */\n public state: GatewayState = GatewayState.Connect;\n #options: Required<Omit<GatewayOptions, \"properties\" | \"presence\">> & {\n properties?: GatewayProperties;\n presence?: GatewayPresence;\n };\n #ws?: WebSocket;\n #sequence: number | null = null;\n #sessionId?: string;\n #resumeURL?: string;\n #heartbeatTimer?: ReturnType<typeof setInterval>;\n #initialHeartbeat?: ReturnType<typeof setTimeout>;\n #heartbeatAckTimer?: ReturnType<typeof setTimeout>;\n #heartbeatACK = true;\n #heartbeatInterval = 0;\n #heartbeatSentAt = 0;\n #lastMessageAt = 0;\n #zombieTimer?: ReturnType<typeof setInterval>;\n #zombieReported = false;\n #closed = false;\n #attempt = 0;\n #reconnectTimer?: ReturnType<typeof setTimeout>;\n #connectPromise?: Promise<void>;\n #resolveConnect?: () => void;\n #rejectConnect?: (error: GatewayError) => void;\n readonly #listeners = new Map<string, Set<GatewayListener>>();\n readonly #sendTimestamps: number[] = [];\n /** Creates a Gateway connection manager. @param options Gateway configuration. @throws {TypeError|RangeError} If configuration is invalid. */\n public constructor(options: GatewayOptions) {\n if (!options.token?.trim())\n throw new TypeError(\"A Gateway token is required.\");\n const resolvedIntents = resolveGatewayIntents(options.intents);\n if (!Number.isInteger(resolvedIntents) || resolvedIntents < 0)\n throw new TypeError(\"Gateway intents must be a non-negative integer.\");\n this.#options = {\n shardId: 0,\n shardCount: 1,\n reconnect: true,\n maxReconnectAttempts: Infinity,\n reconnectBaseDelay: 1000,\n reconnectMaxDelay: 30000,\n heartbeatAckTimeout: 10000,\n zombieTimeout: 30000,\n properties: {\n os: \"Android\",\n browser: \"Discord Android\",\n device: \"Discord Android\",\n },\n presence: { status: \"online\", activities: [], afk: false, since: null },\n ...options,\n };\n if (\n this.#options.shardId < 0 ||\n this.#options.shardId >= this.#options.shardCount\n )\n throw new RangeError(\n \"Gateway shardId must be within the configured shard count.\",\n );\n if (this.#options.zombieTimeout <= this.#options.heartbeatAckTimeout)\n throw new RangeError(\n \"Gateway zombieTimeout must be greater than heartbeatAckTimeout\",\n );\n }\n\n /** Opens the Gateway connection. @param url Gateway WebSocket URL. @returns Promise fulfilled when the socket opens. @throws {GatewayError} If permanently closed or unable to connect. */\n public connect(\n url = \"wss://gateway.discord.gg/?v=10&encoding=json\",\n ): Promise<void> {\n if (this.state === GatewayState.Closed)\n throw new GatewayError(\"Gateway has been permanently closed.\");\n if (this.#connectPromise) return this.#connectPromise;\n this.#closed = false;\n this.#setState(GatewayState.Connect);\n this.#connectPromise = new Promise<void>((resolve, reject) => {\n this.#resolveConnect = resolve;\n this.#rejectConnect = reject;\n this.#open(url);\n });\n return this.#connectPromise;\n }\n /** Permanently closes the Gateway connection. */\n public close(): void {\n this.#closed = true;\n this.#clearTimers();\n this.#settleConnect(\n new GatewayError(\"Gateway connection closed before socket open.\"),\n );\n const ws = this.#ws;\n this.#ws = undefined;\n try {\n ws?.close(1000, \"Client closed connection\");\n } catch (error) {\n this.#emitError(error);\n }\n this.#setState(GatewayState.Closed);\n }\n /** Registers a Gateway event listener. @param event Event name. @param listener Event callback. @returns This Gateway. */\n /** Emits an event to all registered listeners. @param event Event name. @param data Event payload. */\n public emit(event: string, data?: unknown): void {\n this.#emit(event, data);\n }\n public on(event: string, listener: GatewayListener): this {\n if (!event || typeof listener !== \"function\")\n throw new TypeError(\"Gateway event and listener are required.\");\n let listeners = this.#listeners.get(event);\n if (!listeners) this.#listeners.set(event, (listeners = new Set()));\n listeners.add(listener);\n return this;\n }\n /** Removes a Gateway event listener. @param event Event name. @param listener Event callback. @returns This Gateway. */\n public off(event: string, listener: GatewayListener): this {\n this.#listeners.get(event)?.delete(listener);\n return this;\n }\n /** Sends a Gateway payload. @param payload Gateway payload. @returns Whether it was sent. */\n public send(payload: GatewayPayload): boolean {\n if (!payload || !Number.isInteger(payload.op))\n throw new TypeError(\"Gateway payload must contain an integer opcode.\");\n if (this.#ws?.readyState !== WebSocket.OPEN) return false;\n const now = Date.now();\n while (\n this.#sendTimestamps.length &&\n now - this.#sendTimestamps[0]! >= 60000\n )\n this.#sendTimestamps.shift();\n if (this.#sendTimestamps.length >= 115) {\n this.#emitError(new GatewayError(\"Gateway send rate budget exhausted.\"));\n return false;\n }\n try {\n this.#ws.send(JSON.stringify(payload));\n this.#sendTimestamps.push(now);\n return true;\n } catch (error) {\n this.#emitError(error);\n return false;\n }\n }\n /** Sends a presence update. @param data Presence payload. @returns Whether it was sent. */\n public setPresence(data: GatewayPresence): boolean {\n this.#options.presence = { ...this.#options.presence, ...data };\n const payload = {\n since: this.#options.presence.since ?? null,\n activities: this.#options.presence.activities ?? [],\n status: this.#options.presence.status ?? \"online\",\n afk: Boolean(this.#options.presence.afk),\n };\n return this.send({\n op: GatewayOpcodes.PresenceUpdate,\n d: payload,\n s: null,\n t: null,\n });\n }\n /** Sends a voice state update. @param data Voice state payload. @returns Whether it was sent. */\n public setVoiceState(data: Record<string, unknown>): boolean {\n return this.send({\n op: GatewayOpcodes.VoiceStateUpdate,\n d: data,\n s: null,\n t: null,\n });\n }\n /** Requests guild members. @param data Guild member request payload. @returns Whether it was sent. */\n public requestGuildMembers(data: Record<string, unknown>): boolean {\n return this.send({\n op: GatewayOpcodes.RequestGuildMembers,\n d: data,\n s: null,\n t: null,\n });\n }\n #open(url: string): void {\n if (this.#closed) return;\n let ws: WebSocket;\n try {\n ws = new WebSocket(url);\n } catch (error) {\n const failure = this.#normalizeError(error);\n this.#emitError(failure);\n if (this.#options.reconnect) {\n this.#setState(GatewayState.Reconnect);\n this.#scheduleReconnect();\n } else this.#settleConnect(failure);\n return;\n }\n this.#ws = ws;\n ws.addEventListener(\"open\", () => {\n this.#lastMessageAt = Date.now();\n this.#zombieReported = false;\n this.#startZombieDetection();\n this.#emit(\"open\", undefined);\n this.#settleConnect();\n });\n ws.addEventListener(\"message\", (event) => {\n this.#lastMessageAt = Date.now();\n this.#zombieReported = false;\n this.#message(ws, String(event.data));\n });\n ws.addEventListener(\"close\", (event) => this.#close(ws, event.code));\n ws.addEventListener(\"error\", () =>\n this.#emitError(new GatewayError(\"Gateway WebSocket error\")),\n );\n }\n #startZombieDetection(): void {\n if (this.#zombieTimer) clearInterval(this.#zombieTimer);\n const interval = Math.max(\n 1,\n Math.min(\n 250,\n this.#options.heartbeatAckTimeout,\n this.#options.zombieTimeout / 2,\n ),\n );\n this.#zombieTimer = setInterval(() => {\n if (\n this.#closed ||\n this.#ws?.readyState !== WebSocket.OPEN ||\n this.#lastMessageAt === 0\n )\n return;\n const silentFor = Date.now() - this.#lastMessageAt;\n const deadline = Math.max(\n this.#options.zombieTimeout,\n this.#heartbeatInterval + this.#options.heartbeatAckTimeout,\n );\n if (silentFor < deadline || this.#zombieReported) return;\n this.#zombieReported = true;\n const error = new GatewayError(\n `Gateway connection appears stale after ${silentFor}ms without traffic.`,\n );\n this.#emit(\"zombie\", { silentFor, timeout: deadline });\n this.#emitError(error);\n try {\n this.#ws.close(1001, \"Zombie Gateway connection\");\n } catch (closeError) {\n this.#emitError(closeError);\n }\n }, interval);\n }\n #message(ws: WebSocket, raw: string): void {\n let payload: GatewayPayload;\n try {\n payload = JSON.parse(raw) as GatewayPayload;\n } catch (error) {\n this.#emitError(\n new GatewayError(\"Gateway returned invalid JSON\", undefined, {\n cause: error,\n }),\n );\n ws.close(1002, \"Invalid JSON\");\n return;\n }\n if (!payload || typeof payload.op !== \"number\") {\n this.#emitError(new GatewayError(\"Gateway returned an invalid payload\"));\n ws.close(1002, \"Invalid payload\");\n return;\n }\n if (typeof payload.s === \"number\") this.#sequence = payload.s;\n switch (payload.op) {\n case GatewayOpcodes.Dispatch:\n this.#setState(GatewayState.Dispatch);\n this.#handleDispatch(payload.t, payload.d);\n break;\n case GatewayOpcodes.Hello:\n this.#handleHello(payload.d);\n break;\n case GatewayOpcodes.Heartbeat:\n this.#setState(GatewayState.Heartbeat);\n this.#sendHeartbeat();\n break;\n case GatewayOpcodes.HeartbeatAck:\n this.#heartbeatACK = true;\n this.#clearHeartbeatAckTimer();\n this.#emit(\"heartbeatAck\", payload.d);\n break;\n case GatewayOpcodes.Reconnect:\n ws.close(1001, \"Server requested reconnect\");\n break;\n case GatewayOpcodes.InvalidSession:\n this.#sessionId = undefined;\n this.#sequence = null;\n this.#emit(\"invalidSession\", payload.d);\n ws.close(1000, \"Invalid session\");\n break;\n }\n }\n #handleDispatch(event: string | null, data: unknown): void {\n if (event === \"READY\") {\n const ready = data as {\n session_id?: unknown;\n resume_gateway_url?: unknown;\n };\n if (\n typeof ready?.session_id !== \"string\" ||\n typeof ready?.resume_gateway_url !== \"string\"\n ) {\n this.#emitError(\n new GatewayError(\n \"Gateway READY payload is missing session information\",\n ),\n );\n return;\n }\n this.#sessionId = ready.session_id;\n this.#resumeURL = ready.resume_gateway_url;\n this.#attempt = 0;\n this.#setState(GatewayState.Ready);\n this.#emit(\"ready\", data);\n }\n this.#emit(event ?? \"dispatch\", data);\n }\n #handleHello(data: unknown): void {\n const interval = (data as { heartbeat_interval?: unknown })\n ?.heartbeat_interval;\n if (\n typeof interval !== \"number\" ||\n !Number.isFinite(interval) ||\n interval <= 0\n ) {\n this.#emitError(\n new GatewayError(\n \"Gateway HELLO payload contains an invalid heartbeat interval\",\n ),\n );\n this.#ws?.close(1002, \"Invalid heartbeat interval\");\n return;\n }\n this.#heartbeatInterval = interval;\n this.#setState(\n this.#sessionId && this.#sequence !== null && this.#resumeURL\n ? GatewayState.Resume\n : GatewayState.Hello,\n );\n this.#startHeartbeat(interval);\n this.#identifyOrResume();\n }\n #identifyOrResume(): void {\n if (this.#sessionId && this.#sequence !== null && this.#resumeURL) {\n this.#setState(GatewayState.Resume);\n this.send({\n op: GatewayOpcodes.Resume,\n d: {\n token: this.#options.token,\n session_id: this.#sessionId,\n seq: this.#sequence,\n },\n s: null,\n t: null,\n });\n return;\n }\n this.#setState(GatewayState.Identify);\n const props = this.#options.properties ?? {\n os: \"Android\",\n browser: \"Discord Android\",\n device: \"Discord Android\",\n };\n const os = props.os ?? \"Android\";\n const browser = props.browser ?? \"Discord Android\";\n const device = props.device ?? \"Discord Android\";\n this.send({\n op: GatewayOpcodes.Identify,\n d: {\n token: this.#options.token,\n intents: this.#options.intents,\n properties: {\n os,\n browser,\n device,\n $os: os,\n $browser: browser,\n $device: device,\n ...props,\n },\n presence: {\n since: this.#options.presence?.since ?? null,\n activities: this.#options.presence?.activities ?? [],\n status: this.#options.presence?.status ?? \"online\",\n afk: Boolean(this.#options.presence?.afk),\n },\n shard: [this.#options.shardId, this.#options.shardCount],\n },\n s: null,\n t: null,\n });\n }\n #startHeartbeat(interval: number): void {\n this.#clearHeartbeatTimers();\n this.#heartbeatACK = true;\n this.#initialHeartbeat = setTimeout(\n () => this.#sendHeartbeat(),\n Math.random() * interval,\n );\n this.#heartbeatTimer = setInterval(() => this.#sendHeartbeat(), interval);\n }\n #sendHeartbeat(): void {\n this.#heartbeatACK = false;\n this.#heartbeatSentAt = Date.now();\n if (\n !this.send({\n op: GatewayOpcodes.Heartbeat,\n d: this.#sequence,\n s: null,\n t: null,\n })\n ) {\n this.#emitError(\n new GatewayError(\n \"Unable to send Gateway heartbeat because the WebSocket is not open.\",\n ),\n );\n return;\n }\n this.#clearHeartbeatAckTimer();\n this.#heartbeatAckTimer = setTimeout(() => {\n if (!this.#heartbeatACK) {\n const elapsed = Date.now() - this.#heartbeatSentAt;\n this.#emitError(\n new GatewayError(\n `Gateway heartbeat acknowledgement timed out after ${elapsed}ms.`,\n ),\n );\n try {\n this.#ws?.close(1001, \"Heartbeat timeout\");\n } catch (error) {\n this.#emitError(error);\n }\n }\n }, this.#options.heartbeatAckTimeout);\n }\n #close(ws: WebSocket, code: number): void {\n if (this.#ws !== ws) return;\n this.#ws = undefined;\n this.#clearTimers();\n const action = this.#closeAction(code);\n this.#emit(\"close\", { code, action });\n if (this.#closed || !this.#options.reconnect || action === \"stop\") {\n this.#setState(this.#closed ? GatewayState.Closed : GatewayState.Connect);\n if (this.#connectPromise)\n this.#settleConnect(\n new GatewayError(`Gateway closed before READY (code ${code}).`, code),\n );\n return;\n }\n if (action === \"identify\") {\n this.#sequence = null;\n this.#sessionId = undefined;\n }\n this.#setState(GatewayState.Reconnect);\n this.#scheduleReconnect();\n }\n #closeAction(code: number): \"resume\" | \"identify\" | \"stop\" {\n if ([4004, 4010, 4011, 4012, 4013, 4014].includes(code)) return \"stop\";\n if ([4007, 4009].includes(code)) return \"identify\";\n return this.#sessionId && this.#sequence !== null ? \"resume\" : \"identify\";\n }\n #scheduleReconnect(): void {\n if (this.#closed || !this.#options.reconnect || this.#reconnectTimer)\n return;\n if (this.#attempt >= this.#options.maxReconnectAttempts) {\n this.#settleConnect(\n new GatewayError(\"Gateway reconnect attempts exhausted.\"),\n );\n this.#setState(GatewayState.Connect);\n return;\n }\n const delay = Math.min(\n this.#options.reconnectMaxDelay,\n this.#options.reconnectBaseDelay * 2 ** this.#attempt++,\n );\n const jitter = Math.random() * Math.min(250, Math.max(1, delay * 0.25));\n this.#reconnectTimer = setTimeout(() => {\n this.#reconnectTimer = undefined;\n this.#open(\n this.#resumeURL ?? \"wss://gateway.discord.gg/?v=10&encoding=json\",\n );\n }, delay + jitter);\n }\n #settleConnect(error?: GatewayError): void {\n const resolve = this.#resolveConnect;\n const reject = this.#rejectConnect;\n this.#resolveConnect = undefined;\n this.#rejectConnect = undefined;\n this.#connectPromise = undefined;\n if (error) reject?.(error);\n else resolve?.();\n }\n #clearHeartbeatAckTimer(): void {\n if (this.#heartbeatAckTimer) clearTimeout(this.#heartbeatAckTimer);\n this.#heartbeatAckTimer = undefined;\n }\n #clearHeartbeatTimers(): void {\n if (this.#heartbeatTimer) clearInterval(this.#heartbeatTimer);\n if (this.#initialHeartbeat) clearTimeout(this.#initialHeartbeat);\n this.#clearHeartbeatAckTimer();\n this.#heartbeatTimer = undefined;\n this.#initialHeartbeat = undefined;\n }\n #clearTimers(): void {\n if (this.#reconnectTimer) clearTimeout(this.#reconnectTimer);\n if (this.#zombieTimer) clearInterval(this.#zombieTimer);\n this.#reconnectTimer = undefined;\n this.#zombieTimer = undefined;\n this.#clearHeartbeatTimers();\n }\n #normalizeError(error: unknown): GatewayError {\n return error instanceof GatewayError\n ? error\n : new GatewayError(\"Gateway connection failed.\", undefined, {\n cause: error,\n });\n }\n #emitError(error: unknown): void {\n this.#emit(\n \"error\",\n error instanceof Error ? error : new GatewayError(String(error)),\n );\n }\n #emit(event: string, data: unknown): void {\n for (const listener of this.#listeners.get(event) ?? []) {\n try {\n const result = listener(data);\n if (\n result &&\n typeof (result as PromiseLike<unknown>).then === \"function\"\n )\n void Promise.resolve(result).catch((error) => {\n if (event !== \"error\") this.#emitError(error);\n });\n } catch (error) {\n if (event !== \"error\") this.#emitError(error);\n }\n }\n }\n /** Changes the Gateway lifecycle state. @param next Next lifecycle state. */\n #setState(next: GatewayState): void {\n if (this.state === next) return;\n const previous = this.state;\n this.state = next;\n this.#emit(\"stateChange\", { previous, next });\n }\n}\n",
5
+ "/** Discord API snowflake identifier. */\r\nexport type Snowflake = string;\r\n\r\n// ─── Gateway Intents ─────────────────────────────────────────────────────────\r\n\r\n/** Gateway intent bit flags supported by Discord (PascalCase). */\r\nexport const GatewayIntentBits = {\r\n Guilds: 1 << 0,\r\n GuildMembers: 1 << 1,\r\n GuildModeration: 1 << 2,\r\n GuildExpressions: 1 << 3,\r\n GuildIntegrations: 1 << 4,\r\n GuildWebhooks: 1 << 5,\r\n GuildInvites: 1 << 6,\r\n GuildVoiceStates: 1 << 7,\r\n GuildPresences: 1 << 8,\r\n GuildMessages: 1 << 9,\r\n GuildMessageReactions: 1 << 10,\r\n GuildMessageTyping: 1 << 11,\r\n DirectMessages: 1 << 12,\r\n DirectMessageReactions: 1 << 13,\r\n DirectMessageTyping: 1 << 14,\r\n MessageContent: 1 << 15,\r\n GuildScheduledEvents: 1 << 16,\r\n AutoModerationConfiguration: 1 << 20,\r\n AutoModerationExecution: 1 << 21,\r\n GuildMessagePolls: 1 << 24,\r\n DirectMessagePolls: 1 << 25,\r\n} as const;\r\n\r\n/** Idiomatic camelCase Gateway intent bit flags supported by Discord. */\r\nexport const IntentBits = {\r\n guild: 1 << 0,\r\n guilds: 1 << 0,\r\n guildMembers: 1 << 1,\r\n guildModeration: 1 << 2,\r\n guildBans: 1 << 2,\r\n guildExpressions: 1 << 3,\r\n guildEmojis: 1 << 3,\r\n guildEmojisAndStickers: 1 << 3,\r\n guildIntegrations: 1 << 4,\r\n guildWebhooks: 1 << 5,\r\n guildInvites: 1 << 6,\r\n guildVoiceStates: 1 << 7,\r\n guildPresences: 1 << 8,\r\n guildMessages: 1 << 9,\r\n guildMessage: 1 << 9,\r\n guildMessageReactions: 1 << 10,\r\n guildMessageTyping: 1 << 11,\r\n directMessages: 1 << 12,\r\n directMessageReactions: 1 << 13,\r\n directMessageTyping: 1 << 14,\r\n messageContent: 1 << 15,\r\n guildScheduledEvents: 1 << 16,\r\n autoModerationConfiguration: 1 << 20,\r\n autoModerationExecution: 1 << 21,\r\n guildMessagePolls: 1 << 24,\r\n directMessagePolls: 1 << 25,\r\n} as const;\r\n\r\n/** Alias for IntentBits. */\r\nexport const Intents = IntentBits;\r\n\r\n/** Gateway intent resolvable value (single bitfield, enum key, or array of bitfields/strings). */\r\nexport type GatewayIntentResolvable =\r\n | number\r\n | keyof typeof GatewayIntentBits\r\n | keyof typeof IntentBits\r\n | (\r\n number | keyof typeof GatewayIntentBits | keyof typeof IntentBits | string\r\n )[];\r\n\r\n/** Resolves any GatewayIntentResolvable into a raw bitfield integer. */\r\nexport function resolveGatewayIntents(\r\n intents: GatewayIntentResolvable,\r\n): number {\r\n if (typeof intents === \"number\") return intents;\r\n if (Array.isArray(intents)) {\r\n return intents.reduce<number>((acc, intent) => {\r\n return acc | resolveGatewayIntents(intent as any);\r\n }, 0);\r\n }\r\n if (typeof intents === \"string\") {\r\n if (intents in GatewayIntentBits)\r\n return (GatewayIntentBits as Record<string, number>)[intents]!;\r\n if (intents in IntentBits)\r\n return (IntentBits as Record<string, number>)[intents]!;\r\n const lower = intents.charAt(0).toLowerCase() + intents.slice(1);\r\n if (lower in IntentBits)\r\n return (IntentBits as Record<string, number>)[lower]!;\r\n const num = Number(intents);\r\n if (!Number.isNaN(num)) return num;\r\n }\r\n return 0;\r\n}\r\n\r\n// ─── Gateway Config ───────────────────────────────────────────────────────────\r\n\r\n/** Gateway connection properties (OS, browser, device). */\r\nexport interface GatewayProperties {\r\n os?: string;\r\n browser?: string;\r\n device?: string;\r\n [key: string]: unknown;\r\n}\r\n/** Gateway presence activity. */\r\nexport interface GatewayPresenceActivity {\r\n name: string;\r\n type?: number;\r\n url?: string;\r\n state?: string;\r\n}\r\n/** Gateway presence data. */\r\nexport interface GatewayPresence {\r\n status?: \"online\" | \"dnd\" | \"idle\" | \"invisible\" | \"offline\";\r\n activities?: GatewayPresenceActivity[];\r\n afk?: boolean;\r\n since?: number | null;\r\n}\r\n/** Client configuration. */\r\nexport interface ClientOptions {\r\n token: string;\r\n intents: GatewayIntentResolvable;\r\n gateway?: GatewayOptions;\r\n rest?: RESTOptions;\r\n}\r\n/** Gateway connection configuration. */\r\nexport interface GatewayOptions {\r\n intents?: GatewayIntentResolvable;\r\n reconnect?: boolean;\r\n maxReconnectAttempts?: number;\r\n reconnectBaseDelay?: number;\r\n reconnectMaxDelay?: number;\r\n shardId?: number;\r\n shardCount?: number;\r\n properties?: GatewayProperties;\r\n presence?: GatewayPresence;\r\n}\r\n\r\n/** REST request configuration. */\r\nexport interface RESTOptions {\r\n timeout?: number;\r\n retries?: number;\r\n baseURL?: string;\r\n}\r\n\r\n// ─── Core Discord Objects ─────────────────────────────────────────────────────\r\n\r\n/** Discord user object. */\r\nexport interface UserData {\r\n id: Snowflake;\r\n username: string;\r\n discriminator?: string;\r\n global_name?: string | null;\r\n avatar?: string | null;\r\n bot?: boolean;\r\n system?: boolean;\r\n public_flags?: number;\r\n}\r\n/** Current authenticated bot user. */\r\nexport type ClientUser = UserData;\r\n/** Discord Gateway payload envelope. */\r\nexport interface GatewayPayload<T = unknown> {\r\n op: number;\r\n d: T | null;\r\n s: number | null;\r\n t: string | null;\r\n}\r\n/** Generic Discord API error payload. */\r\nexport interface APIError {\r\n code?: number;\r\n message?: string;\r\n errors?: Record<string, unknown>;\r\n}\r\n\r\n// ─── Discord Flags & Enums ────────────────────────────────────────────────────\r\n\r\n/** Discord message flags. */\r\nexport const MessageFlags = {\r\n Crossposted: 1,\r\n IsCrosspost: 2,\r\n SuppressEmbeds: 4,\r\n SourceMessageDeleted: 8,\r\n Urgent: 16,\r\n HasThread: 32,\r\n Ephemeral: 64,\r\n Loading: 128,\r\n IsComponentsV2: 32768,\r\n} as const;\r\n\r\n/** Discord channel types. */\r\nexport const ChannelType = {\r\n GuildText: 0,\r\n DM: 1,\r\n GuildVoice: 2,\r\n GroupDM: 3,\r\n GuildCategory: 4,\r\n GuildAnnouncement: 5,\r\n AnnouncementThread: 10,\r\n PublicThread: 11,\r\n PrivateThread: 12,\r\n GuildStageVoice: 13,\r\n GuildDirectory: 14,\r\n GuildForum: 15,\r\n GuildMedia: 16,\r\n} as const;\r\n\r\n/** Discord component types. */\r\nexport const ComponentType = {\r\n ActionRow: 1,\r\n Button: 2,\r\n StringSelect: 3,\r\n TextInput: 4,\r\n UserSelect: 5,\r\n RoleSelect: 6,\r\n MentionableSelect: 7,\r\n ChannelSelect: 8,\r\n Section: 9,\r\n TextDisplay: 10,\r\n Thumbnail: 11,\r\n MediaGallery: 12,\r\n File: 13,\r\n Separator: 14,\r\n ContentInventoryEntry: 16,\r\n Container: 17,\r\n} as const;\r\n\r\n/** Discord button style types. */\r\nexport const ButtonStyle = {\r\n Primary: 1,\r\n Secondary: 2,\r\n Success: 3,\r\n Danger: 4,\r\n Link: 5,\r\n Premium: 6,\r\n} as const;\r\n\r\n/** Discord text input style types. */\r\nexport const TextInputStyle = {\r\n Short: 1,\r\n Paragraph: 2,\r\n} as const;\r\n\r\n/** Discord interaction response types. */\r\nexport const InteractionResponseType = {\r\n Pong: 1,\r\n ChannelMessage: 4,\r\n DeferredChannelMessage: 5,\r\n DeferredMessageUpdate: 6,\r\n MessageUpdate: 7,\r\n Autocomplete: 8,\r\n Modal: 9,\r\n} as const;\r\n\r\n/** Discord sticker format types. */\r\nexport const StickerFormatType = {\r\n PNG: 1,\r\n APNG: 2,\r\n Lottie: 3,\r\n GIF: 4,\r\n} as const;\r\n\r\n/** Discord sticker types. */\r\nexport const StickerType = {\r\n Standard: 1,\r\n Guild: 2,\r\n} as const;\r\n\r\n/** Discord verification levels. */\r\nexport const VerificationLevel = {\r\n None: 0,\r\n Low: 1,\r\n Medium: 2,\r\n High: 3,\r\n VeryHigh: 4,\r\n} as const;\r\n\r\n/** Discord premium tiers. */\r\nexport const PremiumTier = {\r\n None: 0,\r\n Tier1: 1,\r\n Tier2: 2,\r\n Tier3: 3,\r\n} as const;\r\n\r\n// ─── Embeds ───────────────────────────────────────────────────────────────────\r\n\r\n/** Raw Discord embed footer object. */\r\nexport interface APIEmbedFooter {\r\n text: string;\r\n icon_url?: string;\r\n proxy_icon_url?: string;\r\n}\r\n/** Raw Discord embed image/thumbnail/video object. */\r\nexport interface APIEmbedMedia {\r\n url: string;\r\n proxy_url?: string;\r\n height?: number;\r\n width?: number;\r\n}\r\n/** Raw Discord embed provider object. */\r\nexport interface APIEmbedProvider {\r\n name?: string;\r\n url?: string;\r\n}\r\n/** Raw Discord embed author object. */\r\nexport interface APIEmbedAuthor {\r\n name: string;\r\n url?: string;\r\n icon_url?: string;\r\n proxy_icon_url?: string;\r\n}\r\n/** Raw Discord embed field object. */\r\nexport interface APIEmbedField {\r\n name: string;\r\n value: string;\r\n inline?: boolean;\r\n}\r\n/** Raw Discord embed object. */\r\nexport interface APIEmbed {\r\n title?: string;\r\n type?: string;\r\n description?: string;\r\n url?: string;\r\n timestamp?: string;\r\n color?: number;\r\n footer?: APIEmbedFooter;\r\n image?: APIEmbedMedia;\r\n thumbnail?: APIEmbedMedia;\r\n video?: APIEmbedMedia;\r\n provider?: APIEmbedProvider;\r\n author?: APIEmbedAuthor;\r\n fields?: APIEmbedField[];\r\n}\r\n\r\n// ─── Message Components ───────────────────────────────────────────────────────\r\n\r\n/** Raw Discord select menu option. */\r\nexport interface APISelectMenuOption {\r\n label: string;\r\n value: string;\r\n description?: string;\r\n emoji?: APIPartialEmoji;\r\n default?: boolean;\r\n}\r\n/** Raw Discord emoji (partial, as used in components). */\r\nexport interface APIPartialEmoji {\r\n id?: Snowflake | null;\r\n name?: string | null;\r\n animated?: boolean;\r\n}\r\n/** Raw Discord button component. */\r\nexport interface APIButtonComponent {\r\n type: 2;\r\n style: number;\r\n label?: string;\r\n emoji?: APIPartialEmoji;\r\n custom_id?: string;\r\n url?: string;\r\n sku_id?: string;\r\n disabled?: boolean;\r\n}\r\n/** Raw Discord select menu component. */\r\nexport interface APISelectMenuComponent {\r\n type: 3 | 5 | 6 | 7 | 8;\r\n custom_id: string;\r\n options?: APISelectMenuOption[];\r\n channel_types?: number[];\r\n placeholder?: string;\r\n min_values?: number;\r\n max_values?: number;\r\n disabled?: boolean;\r\n}\r\n/** Raw Discord text input component. */\r\nexport interface APITextInputComponent {\r\n type: 4;\r\n custom_id: string;\r\n style: number;\r\n label: string;\r\n min_length?: number;\r\n max_length?: number;\r\n required?: boolean;\r\n value?: string;\r\n placeholder?: string;\r\n}\r\n/** Union of all raw message component types. */\r\nexport type APIMessageActionRowComponent =\r\n APIButtonComponent | APISelectMenuComponent | APITextInputComponent;\r\n/** Raw Discord action row component. */\r\nexport interface APIActionRowComponent {\r\n type: 1;\r\n id?: number;\r\n components: APIMessageActionRowComponent[];\r\n}\r\n/** Union including action rows and V2 components. */\r\nexport type APIMessageComponent = APIActionRowComponent | { type: Exclude<number, 1>; [key: string]: any };\r\n\r\n// ─── Attachments ─────────────────────────────────────────────────────────────\r\n\r\n/** Raw Discord attachment object. */\r\nexport interface APIAttachment {\r\n id: Snowflake;\r\n filename: string;\r\n description?: string | null;\r\n content_type?: string;\r\n size: number;\r\n url: string;\r\n proxy_url: string;\r\n height?: number | null;\r\n width?: number | null;\r\n ephemeral?: boolean;\r\n duration_secs?: number;\r\n waveform?: string;\r\n flags?: number;\r\n}\r\n\r\n// ─── Stickers ────────────────────────────────────────────────────────────────\r\n\r\n/** Compact sticker item as included in messages. */\r\nexport interface APIStickerItem {\r\n id: Snowflake;\r\n name: string;\r\n format_type: number;\r\n}\r\n/** Full Discord sticker object. */\r\nexport interface APISticker {\r\n id: Snowflake;\r\n pack_id?: Snowflake;\r\n name: string;\r\n description?: string | null;\r\n tags?: string;\r\n type: number;\r\n format_type: number;\r\n available?: boolean;\r\n guild_id?: Snowflake;\r\n user?: UserData;\r\n sort_value?: number;\r\n}\r\n\r\n// ─── Messages ────────────────────────────────────────────────────────────────\r\n\r\n/** Raw Discord message reference. */\r\nexport interface APIMessageReference {\r\n type?: number;\r\n message_id?: Snowflake;\r\n channel_id?: Snowflake;\r\n guild_id?: Snowflake;\r\n fail_if_not_exists?: boolean;\r\n}\r\n/** Raw Discord message reaction. */\r\nexport interface APIMessageReaction {\r\n count: number;\r\n count_details?: Record<string, number>;\r\n me?: boolean;\r\n me_burst?: boolean;\r\n emoji: APIPartialEmoji;\r\n burst_colors?: string[];\r\n}\r\n/** Raw Discord message object. */\r\nexport interface APIMessage {\r\n id: Snowflake;\r\n channel_id: Snowflake;\r\n author: UserData;\r\n content: string;\r\n timestamp?: string;\r\n edited_timestamp?: string | null;\r\n tts?: boolean;\r\n mention_everyone?: boolean;\r\n mentions?: UserData[];\r\n mention_roles?: Snowflake[];\r\n mention_channels?: Array<Record<string, unknown>>;\r\n attachments?: APIAttachment[];\r\n embeds?: APIEmbed[];\r\n reactions?: APIMessageReaction[];\r\n nonce?: string | number | null;\r\n pinned?: boolean;\r\n webhook_id?: Snowflake;\r\n type?: number;\r\n activity?: Record<string, unknown>;\r\n application?: Record<string, unknown>;\r\n application_id?: Snowflake;\r\n message_reference?: APIMessageReference;\r\n flags?: number;\r\n referenced_message?: APIMessage | null;\r\n interaction_metadata?: Record<string, unknown>;\r\n thread?: Record<string, unknown>;\r\n components?: APIMessageComponent[];\r\n sticker_items?: APIStickerItem[];\r\n stickers?: APISticker[];\r\n position?: number;\r\n role_subscription_data?: Record<string, unknown>;\r\n purchase_notification?: Record<string, unknown>;\r\n poll?: Record<string, unknown>;\r\n guild_id?: Snowflake;\r\n}\r\n\r\n// ─── Channels ────────────────────────────────────────────────────────────────\r\n\r\n/** Raw Discord channel object. */\r\nexport interface APIChannel {\r\n id: Snowflake;\r\n type: number;\r\n guild_id?: Snowflake;\r\n position?: number;\r\n permission_overwrites?: Array<Record<string, unknown>>;\r\n name?: string | null;\r\n topic?: string | null;\r\n nsfw?: boolean;\r\n last_message_id?: Snowflake | null;\r\n bitrate?: number;\r\n user_limit?: number;\r\n rate_limit_per_user?: number;\r\n recipients?: UserData[];\r\n icon?: string | null;\r\n owner_id?: Snowflake;\r\n application_id?: Snowflake;\r\n parent_id?: Snowflake | null;\r\n last_pin_timestamp?: string | null;\r\n rtc_region?: string | null;\r\n video_quality_mode?: number;\r\n message_count?: number;\r\n member_count?: number;\r\n thread_metadata?: APIThreadMetadata;\r\n default_auto_archive_duration?: number;\r\n flags?: number;\r\n total_message_sent?: number;\r\n available_tags?: APIForumTag[];\r\n default_reaction_emoji?: APIPartialEmoji | null;\r\n default_thread_rate_limit_per_user?: number;\r\n default_sort_order?: number | null;\r\n default_forum_layout?: number;\r\n}\r\n\r\n/** Raw Discord thread metadata. */\r\nexport interface APIThreadMetadata {\r\n archived: boolean;\r\n auto_archive_duration: number;\r\n archive_timestamp: string;\r\n locked: boolean;\r\n invitable?: boolean;\r\n create_timestamp?: string | null;\r\n}\r\n\r\n/** Raw Discord forum tag. */\r\nexport interface APIForumTag {\r\n id: Snowflake;\r\n name: string;\r\n moderated: boolean;\r\n emoji_id?: Snowflake | null;\r\n emoji_name?: string | null;\r\n}\r\n\r\n/** Raw Discord thread member. */\r\nexport interface APIThreadMember {\r\n id?: Snowflake;\r\n user_id?: Snowflake;\r\n join_timestamp: string;\r\n flags: number;\r\n member?: APIGuildMember;\r\n}\r\n\r\n// ─── Roles ────────────────────────────────────────────────────────────────────\r\n\r\n/** Raw Discord role object. */\r\nexport interface APIRole {\r\n id: Snowflake;\r\n name: string;\r\n color: number;\r\n hoist: boolean;\r\n icon?: string | null;\r\n unicode_emoji?: string | null;\r\n position: number;\r\n permissions: string;\r\n managed: boolean;\r\n mentionable: boolean;\r\n tags?: Record<string, unknown>;\r\n flags?: number;\r\n}\r\n\r\n// ─── Emoji ────────────────────────────────────────────────────────────────────\r\n\r\n/** Raw Discord emoji object. */\r\nexport interface APIEmoji {\r\n id: Snowflake | null;\r\n name: string | null;\r\n roles?: Snowflake[];\r\n user?: UserData;\r\n require_colons?: boolean;\r\n managed?: boolean;\r\n animated?: boolean;\r\n available?: boolean;\r\n}\r\n\r\n// ─── Guilds ───────────────────────────────────────────────────────────────────\r\n\r\n/** Raw Discord guild object. */\r\nexport interface APIGuild {\r\n id: Snowflake;\r\n name: string;\r\n icon?: string | null;\r\n icon_hash?: string | null;\r\n splash?: string | null;\r\n discovery_splash?: string | null;\r\n owner?: boolean;\r\n owner_id?: Snowflake;\r\n permissions?: string;\r\n afk_channel_id?: Snowflake | null;\r\n afk_timeout?: number;\r\n widget_enabled?: boolean;\r\n widget_channel_id?: Snowflake | null;\r\n verification_level?: number;\r\n default_message_notifications?: number;\r\n explicit_content_filter?: number;\r\n roles?: APIRole[];\r\n emojis?: APIEmoji[];\r\n stickers?: APISticker[];\r\n features?: string[];\r\n mfa_level?: number;\r\n application_id?: Snowflake | null;\r\n system_channel_id?: Snowflake | null;\r\n system_channel_flags?: number;\r\n rules_channel_id?: Snowflake | null;\r\n max_presences?: number | null;\r\n max_members?: number;\r\n vanity_url_code?: string | null;\r\n description?: string | null;\r\n banner?: string | null;\r\n premium_tier?: number;\r\n premium_subscription_count?: number;\r\n preferred_locale?: string;\r\n public_updates_channel_id?: Snowflake | null;\r\n max_video_channel_users?: number;\r\n approximate_member_count?: number;\r\n approximate_presence_count?: number;\r\n nsfw_level?: number;\r\n safety_alerts_channel_id?: Snowflake | null;\r\n member_count?: number;\r\n}\r\n\r\n/** Raw Discord guild member object. */\r\nexport interface APIGuildMember {\r\n user: UserData;\r\n nick?: string | null;\r\n avatar?: string | null;\r\n roles: Snowflake[];\r\n joined_at: string;\r\n premium_since?: string | null;\r\n deaf?: boolean;\r\n mute?: boolean;\r\n flags?: number;\r\n pending?: boolean;\r\n permissions?: string;\r\n communication_disabled_until?: string | null;\r\n guild_id?: Snowflake;\r\n}\r\n\r\n// ─── Voice ────────────────────────────────────────────────────────────────────\r\n\r\n/** Raw Discord voice state object. */\r\nexport interface APIVoiceState {\r\n guild_id?: Snowflake;\r\n channel_id?: Snowflake | null;\r\n user_id: Snowflake;\r\n member?: APIGuildMember;\r\n session_id: string;\r\n deaf: boolean;\r\n mute: boolean;\r\n self_deaf: boolean;\r\n self_mute: boolean;\r\n self_stream?: boolean;\r\n self_video: boolean;\r\n suppress: boolean;\r\n request_to_speak_timestamp?: string | null;\r\n}\r\n\r\n/** Raw Discord voice server update event. */\r\nexport interface APIVoiceServerUpdate {\r\n token: string;\r\n guild_id: Snowflake;\r\n endpoint?: string | null;\r\n}\r\n\r\n// ─── Presence ────────────────────────────────────────────────────────────────\r\n\r\n/** Raw Discord activity object. */\r\nexport interface APIActivity {\r\n name: string;\r\n type: number;\r\n url?: string | null;\r\n created_at: number;\r\n state?: string | null;\r\n details?: string | null;\r\n emoji?: APIPartialEmoji | null;\r\n}\r\n\r\n/** Raw Discord presence update event. */\r\nexport interface APIPresenceUpdate {\r\n user: { id: Snowflake } & Partial<UserData>;\r\n guild_id: Snowflake;\r\n status: string;\r\n activities: APIActivity[];\r\n client_status: { desktop?: string; mobile?: string; web?: string };\r\n}\r\n\r\n// ─── Typing ───────────────────────────────────────────────────────────────────\r\n\r\n/** Raw Discord typing start event. */\r\nexport interface APITypingStart {\r\n channel_id: Snowflake;\r\n guild_id?: Snowflake;\r\n user_id: Snowflake;\r\n timestamp: number;\r\n member?: APIGuildMember;\r\n}\r\n\r\n// ─── Guilds ──────────────────────────────────────────────────────────────────\r\n\r\n/** Raw Discord guild preview. */\r\nexport interface APIGuildPreview {\r\n id: Snowflake;\r\n name: string;\r\n icon: string | null;\r\n splash: string | null;\r\n discovery_splash: string | null;\r\n emojis: unknown[];\r\n features: string[];\r\n approximate_member_count: number;\r\n approximate_presence_count: number;\r\n description: string | null;\r\n stickers: unknown[];\r\n}\r\n\r\n// ─── Invites ─────────────────────────────────────────────────────────────────\r\n\r\n/** Raw Discord invite. */\r\nexport interface APIInvite {\r\n code: string;\r\n guild?: Partial<APIGuild>;\r\n channel: Partial<APIChannel>;\r\n inviter?: UserData;\r\n target_type?: number;\r\n target_user?: UserData;\r\n approximate_presence_count?: number;\r\n approximate_member_count?: number;\r\n}\r\n\r\n/** Raw Discord invite create event. */\r\nexport interface APIInviteCreate {\r\n channel_id: Snowflake;\r\n code: string;\r\n created_at: string;\r\n guild_id?: Snowflake;\r\n inviter?: UserData;\r\n max_age: number;\r\n max_uses: number;\r\n target_type?: number;\r\n target_user?: UserData;\r\n temporary: boolean;\r\n uses: number;\r\n}\r\n\r\n/** Raw Discord invite delete event. */\r\nexport interface APIInviteDelete {\r\n channel_id: Snowflake;\r\n guild_id?: Snowflake;\r\n code: string;\r\n}\r\n\r\n// ─── Webhooks ────────────────────────────────────────────────────────────────\r\n\r\n/** Raw Discord webhooks update event. */\r\nexport interface APIWebhooksUpdate {\r\n guild_id: Snowflake;\r\n channel_id: Snowflake;\r\n}\r\n\r\n/** Raw Discord webhook object. */\r\nexport interface APIWebhook {\r\n id: Snowflake;\r\n type: number;\r\n guild_id?: Snowflake | null;\r\n channel_id?: Snowflake | null;\r\n user?: UserData;\r\n name?: string | null;\r\n avatar?: string | null;\r\n token?: string;\r\n application_id?: Snowflake | null;\r\n url?: string;\r\n}\r\n\r\n// ─── AutoMod ─────────────────────────────────────────────────────────────────\r\n\r\n/** Raw Discord AutoMod action. */\r\nexport interface APIAutoModerationAction {\r\n type: number;\r\n metadata?: {\r\n channel_id?: Snowflake;\r\n duration_seconds?: number;\r\n custom_message?: string;\r\n };\r\n}\r\n\r\n/** Raw Discord AutoMod rule object. */\r\nexport interface APIAutoModerationRule {\r\n id: Snowflake;\r\n guild_id: Snowflake;\r\n name: string;\r\n creator_id: Snowflake;\r\n event_type: number;\r\n trigger_type: number;\r\n trigger_metadata: Record<string, unknown>;\r\n actions: APIAutoModerationAction[];\r\n enabled: boolean;\r\n exempt_roles: Snowflake[];\r\n exempt_channels: Snowflake[];\r\n}\r\n\r\n/** Raw Discord AutoMod action execution event. */\r\nexport interface APIAutoModerationActionExecution {\r\n guild_id: Snowflake;\r\n action: APIAutoModerationAction;\r\n rule_id: Snowflake;\r\n rule_trigger_type: number;\r\n user_id: Snowflake;\r\n channel_id?: Snowflake;\r\n message_id?: Snowflake;\r\n alert_system_message_id?: Snowflake;\r\n content: string;\r\n matched_keyword?: string | null;\r\n matched_content?: string | null;\r\n}\r\n\r\n// ─── Scheduled Events ─────────────────────────────────────────────────────────\r\n\r\n/** Raw Discord guild scheduled event entity metadata. */\r\nexport interface APIGuildScheduledEventEntityMetadata {\r\n location?: string;\r\n}\r\n\r\n/** Raw Discord guild scheduled event object. */\r\nexport interface APIGuildScheduledEvent {\r\n id: Snowflake;\r\n guild_id: Snowflake;\r\n channel_id?: Snowflake | null;\r\n creator_id?: Snowflake | null;\r\n name: string;\r\n description?: string | null;\r\n scheduled_start_time: string;\r\n scheduled_end_time?: string | null;\r\n privacy_level: number;\r\n status: number;\r\n entity_type: number;\r\n entity_id?: Snowflake | null;\r\n entity_metadata?: APIGuildScheduledEventEntityMetadata | null;\r\n creator?: UserData;\r\n user_count?: number;\r\n image?: string | null;\r\n}\r\n\r\n// ─── Stage Instances ─────────────────────────────────────────────────────────\r\n\r\n/** Raw Discord stage instance object. */\r\nexport interface APIStageInstance {\r\n id: Snowflake;\r\n guild_id: Snowflake;\r\n channel_id: Snowflake;\r\n topic: string;\r\n privacy_level: number;\r\n discoverable_disabled?: boolean;\r\n guild_scheduled_event_id?: Snowflake | null;\r\n}\r\n\r\n// ─── Application Commands ─────────────────────────────────────────────────────\r\n\r\n/** Discord application command option types. */\r\nexport const ApplicationCommandOptionType = {\r\n SubCommand: 1,\r\n SubCommandGroup: 2,\r\n String: 3,\r\n Integer: 4,\r\n Boolean: 5,\r\n User: 6,\r\n Channel: 7,\r\n Role: 8,\r\n Mentionable: 9,\r\n Number: 10,\r\n Attachment: 11,\r\n} as const;\r\n\r\n/** Discord application command types. */\r\nexport const ApplicationCommandType = {\r\n ChatInput: 1,\r\n User: 2,\r\n Message: 3,\r\n} as const;\r\n\r\n/** Raw Discord application command option. */\r\nexport interface APIApplicationCommandOption {\r\n type: number;\r\n name: string;\r\n description: string;\r\n required?: boolean;\r\n choices?: Array<{ name: string; value: string | number }>;\r\n options?: APIApplicationCommandOption[];\r\n min_value?: number;\r\n max_value?: number;\r\n min_length?: number;\r\n max_length?: number;\r\n autocomplete?: boolean;\r\n channel_types?: number[];\r\n}\r\n\r\n/** Raw Discord application command object (from API). */\r\nexport interface APIApplicationCommand {\r\n id: Snowflake;\r\n type?: number;\r\n application_id: Snowflake;\r\n guild_id?: Snowflake;\r\n name: string;\r\n description: string;\r\n options?: APIApplicationCommandOption[];\r\n default_member_permissions?: string | null;\r\n dm_permission?: boolean;\r\n nsfw?: boolean;\r\n version: Snowflake;\r\n}\r\n\r\n/** Data for creating/overwriting an application command. */\r\nexport interface ApplicationCommandData {\r\n name: string;\r\n description: string;\r\n type?: number;\r\n options?: APIApplicationCommandOption[];\r\n default_member_permissions?: string | null;\r\n dm_permission?: boolean;\r\n nsfw?: boolean;\r\n}\r\n\r\n// ─── Gateway Events ───────────────────────────────────────────────────────────\r\n\r\n/** Raw Discord READY event payload. */\r\nexport interface APIReadyEvent {\r\n v: number;\r\n user: UserData;\r\n guilds: Array<{ id: Snowflake; unavailable?: boolean }>;\r\n session_id: string;\r\n resume_gateway_url: string;\r\n shard?: [number, number];\r\n application?: { id: Snowflake; flags: number; [key: string]: unknown };\r\n}\r\n\r\n/** Raw Discord reaction event payload. */\r\nexport interface APIMessageReactionEvent {\r\n user_id: Snowflake;\r\n channel_id: Snowflake;\r\n message_id: Snowflake;\r\n guild_id?: Snowflake;\r\n member?: APIGuildMember;\r\n emoji: APIPartialEmoji;\r\n message_author_id?: Snowflake;\r\n burst?: boolean;\r\n type?: number;\r\n}\r\n\r\n/** Raw Discord reaction remove emoji event payload. */\r\nexport interface APIMessageReactionRemoveEmojiEvent {\r\n channel_id: Snowflake;\r\n guild_id?: Snowflake;\r\n message_id: Snowflake;\r\n emoji: APIPartialEmoji;\r\n}\r\n\r\n/** Raw Discord message deletion event payload. */\r\nexport interface APIMessageDeleteEvent {\r\n id: Snowflake;\r\n channel_id: Snowflake;\r\n guild_id?: Snowflake;\r\n}\r\n\r\n/** Raw Discord bulk message deletion event payload. */\r\nexport interface APIMessageDeleteBulkEvent {\r\n ids: Snowflake[];\r\n channel_id: Snowflake;\r\n guild_id?: Snowflake;\r\n}\r\n\r\n/** Raw Discord channel deletion event payload. */\r\nexport interface APIChannelDeleteEvent extends APIChannel {}\r\n\r\n/** Raw Discord guild deletion event payload. */\r\nexport interface APIGuildDeleteEvent {\r\n id: Snowflake;\r\n unavailable?: boolean;\r\n}\r\n\r\n/** Raw Discord thread lifecycle payload. */\r\nexport interface APIThreadEvent extends APIChannel {\r\n guild_id: Snowflake;\r\n member?: APIThreadMember;\r\n}\r\n\r\n/** Raw Discord thread list sync event. */\r\nexport interface APIThreadListSync {\r\n guild_id: Snowflake;\r\n channel_ids?: Snowflake[];\r\n threads: APIChannel[];\r\n members: APIThreadMember[];\r\n}\r\n\r\n/** Raw Discord thread members update event. */\r\nexport interface APIThreadMembersUpdate {\r\n id: Snowflake;\r\n guild_id: Snowflake;\r\n member_count: number;\r\n added_members?: APIThreadMember[];\r\n removed_member_ids?: Snowflake[];\r\n}\r\n\r\n/** Raw Discord guild role event payload. */\r\nexport interface APIGuildRoleEvent {\r\n guild_id: Snowflake;\r\n role: APIRole;\r\n}\r\n\r\n/** Raw Discord guild role delete event payload. */\r\nexport interface APIGuildRoleDeleteEvent {\r\n guild_id: Snowflake;\r\n role_id: Snowflake;\r\n}\r\n\r\n/** Raw Discord guild ban event payload. */\r\nexport interface APIGuildBanEvent {\r\n guild_id: Snowflake;\r\n user: UserData;\r\n}\r\n\r\n/** Raw Discord guild emojis update event payload. */\r\nexport interface APIGuildEmojisUpdateEvent {\r\n guild_id: Snowflake;\r\n emojis: APIEmoji[];\r\n}\r\n\r\n/** Raw Discord guild stickers update event payload. */\r\nexport interface APIGuildStickersUpdateEvent {\r\n guild_id: Snowflake;\r\n stickers: APISticker[];\r\n}\r\n\r\n/** Raw Discord channel pins update event. */\r\nexport interface APIChannelPinsUpdate {\r\n guild_id?: Snowflake;\r\n channel_id: Snowflake;\r\n last_pin_timestamp?: string | null;\r\n}\r\n\r\n/** Raw Discord guild members chunk event. */\r\nexport interface APIGuildMembersChunk {\r\n guild_id: Snowflake;\r\n members: APIGuildMember[];\r\n chunk_index: number;\r\n chunk_count: number;\r\n not_found?: Snowflake[];\r\n presences?: APIPresenceUpdate[];\r\n nonce?: string;\r\n}\r\n\r\n/** Raw Discord guild scheduled event user add/remove event. */\r\nexport interface APIGuildScheduledEventUserEvent {\r\n guild_scheduled_event_id: Snowflake;\r\n user_id: Snowflake;\r\n guild_id: Snowflake;\r\n}\r\n\r\n/** Raw Discord message poll vote add/remove event. */\r\nexport interface APIMessagePollVoteEvent {\r\n user_id: Snowflake;\r\n channel_id: Snowflake;\r\n message_id: Snowflake;\r\n guild_id?: Snowflake;\r\n answer_id: number;\r\n}\r\n",
6
+ "import {\r\n resolveGatewayIntents,\r\n type GatewayPayload,\r\n type GatewayProperties,\r\n type GatewayPresence,\r\n type GatewayIntentResolvable,\r\n} from \"@lunibee/types\";\r\n\r\n/** Discord Gateway opcodes. */\r\nexport const GatewayOpcodes = {\r\n Dispatch: 0,\r\n Heartbeat: 1,\r\n Identify: 2,\r\n PresenceUpdate: 3,\r\n VoiceStateUpdate: 4,\r\n Resume: 6,\r\n Reconnect: 7,\r\n RequestGuildMembers: 8,\r\n InvalidSession: 9,\r\n Hello: 10,\r\n HeartbeatAck: 11,\r\n} as const;\r\n/** Gateway connection lifecycle states. */\r\nexport enum GatewayState {\r\n /** Initial connection state. */ Connect = \"CONNECT\",\r\n /** Gateway HELLO received state. */ Hello = \"HELLO\",\r\n /** IDENTIFY operation in progress. */ Identify = \"IDENTIFY\",\r\n /** RESUME operation in progress. */ Resume = \"RESUME\",\r\n /** Gateway READY state. */ Ready = \"READY\",\r\n /** Gateway dispatch processing state. */ Dispatch = \"DISPATCH\",\r\n /** Heartbeat processing state. */ Heartbeat = \"HEARTBEAT\",\r\n /** Reconnect in progress. */ Reconnect = \"RECONNECT\",\r\n /** Gateway is permanently closed. */ Closed = \"CLOSED\",\r\n}\r\n/** Gateway protocol error. */\r\nexport class GatewayError extends Error {\r\n /** Gateway close/error code. */ public readonly code?: number;\r\n /** Creates a Gateway error. @param message Error message. @param code Optional Gateway code. @param options Optional error metadata. */ public constructor(\r\n message: string,\r\n code?: number,\r\n options?: ErrorOptions,\r\n ) {\r\n super(message, options);\r\n this.name = \"GatewayError\";\r\n this.code = code;\r\n }\r\n}\r\n/** Gateway connection configuration. */\r\nexport interface GatewayOptions {\r\n /** Authentication token. */ token: string;\r\n /** Gateway intent bitfield or resolvable. */ intents: GatewayIntentResolvable;\r\n /** Shard identifier. */ shardId?: number;\r\n /** Total shard count. */ shardCount?: number;\r\n /** Whether automatic reconnect is enabled. */ reconnect?: boolean;\r\n /** Maximum reconnect attempts. */ maxReconnectAttempts?: number;\r\n /** Initial reconnect delay. */ reconnectBaseDelay?: number;\r\n /** Maximum reconnect delay. */ reconnectMaxDelay?: number;\r\n /** Heartbeat acknowledgement timeout. */ heartbeatAckTimeout?: number;\r\n /** Zombie connection timeout. */ zombieTimeout?: number;\r\n /** Identification properties. */ properties?: GatewayProperties;\r\n /** Presence data. */ presence?: GatewayPresence;\r\n}\r\n/** Gateway event listener. */\r\ntype GatewayListener = (data: unknown) => unknown;\r\n/** Manages a Discord Gateway connection. */\r\nexport class Gateway {\r\n /** Current Gateway lifecycle state. */\r\n public state: GatewayState = GatewayState.Connect;\r\n #options: Required<Omit<GatewayOptions, \"properties\" | \"presence\">> & {\r\n properties?: GatewayProperties;\r\n presence?: GatewayPresence;\r\n };\r\n #ws?: WebSocket;\r\n #sequence: number | null = null;\r\n #sessionId?: string;\r\n #resumeURL?: string;\r\n #heartbeatTimer?: ReturnType<typeof setInterval>;\r\n #initialHeartbeat?: ReturnType<typeof setTimeout>;\r\n #heartbeatAckTimer?: ReturnType<typeof setTimeout>;\r\n #heartbeatACK = true;\r\n #heartbeatInterval = 0;\r\n #heartbeatSentAt = 0;\r\n #lastMessageAt = 0;\r\n #zombieTimer?: ReturnType<typeof setInterval>;\r\n #zombieReported = false;\r\n #closed = false;\r\n #attempt = 0;\r\n #reconnectTimer?: ReturnType<typeof setTimeout>;\r\n #connectPromise?: Promise<void>;\r\n #resolveConnect?: () => void;\r\n #rejectConnect?: (error: GatewayError) => void;\r\n readonly #listeners = new Map<string, Set<GatewayListener>>();\r\n readonly #sendTimestamps: number[] = [];\r\n /** Creates a Gateway connection manager. @param options Gateway configuration. @throws {TypeError|RangeError} If configuration is invalid. */\r\n public constructor(options: GatewayOptions) {\r\n if (!options.token?.trim())\r\n throw new TypeError(\"A Gateway token is required.\");\r\n const resolvedIntents = resolveGatewayIntents(options.intents);\r\n if (!Number.isInteger(resolvedIntents) || resolvedIntents < 0)\r\n throw new TypeError(\"Gateway intents must be a non-negative integer.\");\r\n this.#options = {\r\n shardId: 0,\r\n shardCount: 1,\r\n reconnect: true,\r\n maxReconnectAttempts: Infinity,\r\n reconnectBaseDelay: 1000,\r\n reconnectMaxDelay: 30000,\r\n heartbeatAckTimeout: 10000,\r\n zombieTimeout: 30000,\r\n properties: {\r\n os: \"Android\",\r\n browser: \"Discord Android\",\r\n device: \"Discord Android\",\r\n },\r\n presence: { status: \"online\", activities: [], afk: false, since: null },\r\n ...options,\r\n };\r\n if (\r\n this.#options.shardId < 0 ||\r\n this.#options.shardId >= this.#options.shardCount\r\n )\r\n throw new RangeError(\r\n \"Gateway shardId must be within the configured shard count.\",\r\n );\r\n if (this.#options.zombieTimeout <= this.#options.heartbeatAckTimeout)\r\n throw new RangeError(\r\n \"Gateway zombieTimeout must be greater than heartbeatAckTimeout\",\r\n );\r\n }\r\n\r\n /** Opens the Gateway connection. @param url Gateway WebSocket URL. @returns Promise fulfilled when the socket opens. @throws {GatewayError} If permanently closed or unable to connect. */\r\n public connect(\r\n url = \"wss://gateway.discord.gg/?v=10&encoding=json\",\r\n ): Promise<void> {\r\n if (this.state === GatewayState.Closed)\r\n throw new GatewayError(\"Gateway has been permanently closed.\");\r\n if (this.#connectPromise) return this.#connectPromise;\r\n this.#closed = false;\r\n this.#setState(GatewayState.Connect);\r\n this.#connectPromise = new Promise<void>((resolve, reject) => {\r\n this.#resolveConnect = resolve;\r\n this.#rejectConnect = reject;\r\n this.#open(url);\r\n });\r\n return this.#connectPromise;\r\n }\r\n /** Permanently closes the Gateway connection. */\r\n public close(): void {\r\n this.#closed = true;\r\n this.#clearTimers();\r\n this.#settleConnect(\r\n new GatewayError(\"Gateway connection closed before socket open.\"),\r\n );\r\n const ws = this.#ws;\r\n this.#ws = undefined;\r\n try {\r\n ws?.close(1000, \"Client closed connection\");\r\n } catch (error) {\r\n this.#emitError(error);\r\n }\r\n this.#setState(GatewayState.Closed);\r\n }\r\n /** Registers a Gateway event listener. @param event Event name. @param listener Event callback. @returns This Gateway. */\r\n /** Emits an event to all registered listeners. @param event Event name. @param data Event payload. */\r\n public emit(event: string, data?: unknown): void {\r\n this.#emit(event, data);\r\n }\r\n public on(event: string, listener: GatewayListener): this {\r\n if (!event || typeof listener !== \"function\")\r\n throw new TypeError(\"Gateway event and listener are required.\");\r\n let listeners = this.#listeners.get(event);\r\n if (!listeners) this.#listeners.set(event, (listeners = new Set()));\r\n listeners.add(listener);\r\n return this;\r\n }\r\n /** Removes a Gateway event listener. @param event Event name. @param listener Event callback. @returns This Gateway. */\r\n public off(event: string, listener: GatewayListener): this {\r\n this.#listeners.get(event)?.delete(listener);\r\n return this;\r\n }\r\n /** Sends a Gateway payload. @param payload Gateway payload. @returns Whether it was sent. */\r\n public send(payload: GatewayPayload): boolean {\r\n if (!payload || !Number.isInteger(payload.op))\r\n throw new TypeError(\"Gateway payload must contain an integer opcode.\");\r\n if (this.#ws?.readyState !== WebSocket.OPEN) return false;\r\n const now = Date.now();\r\n while (\r\n this.#sendTimestamps.length &&\r\n now - this.#sendTimestamps[0]! >= 60000\r\n )\r\n this.#sendTimestamps.shift();\r\n if (this.#sendTimestamps.length >= 115) {\r\n this.#emitError(new GatewayError(\"Gateway send rate budget exhausted.\"));\r\n return false;\r\n }\r\n try {\r\n this.#ws.send(JSON.stringify(payload));\r\n this.#sendTimestamps.push(now);\r\n return true;\r\n } catch (error) {\r\n this.#emitError(error);\r\n return false;\r\n }\r\n }\r\n /** Sends a presence update. @param data Presence payload. @returns Whether it was sent. */\r\n public setPresence(data: GatewayPresence): boolean {\r\n this.#options.presence = { ...this.#options.presence, ...data };\r\n const payload = {\r\n since: this.#options.presence.since ?? null,\r\n activities: this.#options.presence.activities ?? [],\r\n status: this.#options.presence.status ?? \"online\",\r\n afk: Boolean(this.#options.presence.afk),\r\n };\r\n return this.send({\r\n op: GatewayOpcodes.PresenceUpdate,\r\n d: payload,\r\n s: null,\r\n t: null,\r\n });\r\n }\r\n /** Sends a voice state update. @param data Voice state payload. @returns Whether it was sent. */\r\n public setVoiceState(data: Record<string, unknown>): boolean {\r\n return this.send({\r\n op: GatewayOpcodes.VoiceStateUpdate,\r\n d: data,\r\n s: null,\r\n t: null,\r\n });\r\n }\r\n /** Requests guild members. @param data Guild member request payload. @returns Whether it was sent. */\r\n public requestGuildMembers(data: Record<string, unknown>): boolean {\r\n return this.send({\r\n op: GatewayOpcodes.RequestGuildMembers,\r\n d: data,\r\n s: null,\r\n t: null,\r\n });\r\n }\r\n #open(url: string): void {\r\n if (this.#closed) return;\r\n let ws: WebSocket;\r\n try {\r\n ws = new WebSocket(url);\r\n } catch (error) {\r\n const failure = this.#normalizeError(error);\r\n this.#emitError(failure);\r\n if (this.#options.reconnect) {\r\n this.#setState(GatewayState.Reconnect);\r\n this.#scheduleReconnect();\r\n } else this.#settleConnect(failure);\r\n return;\r\n }\r\n this.#ws = ws;\r\n ws.addEventListener(\"open\", () => {\r\n this.#lastMessageAt = Date.now();\r\n this.#zombieReported = false;\r\n this.#startZombieDetection();\r\n this.#emit(\"open\", undefined);\r\n this.#settleConnect();\r\n });\r\n ws.addEventListener(\"message\", (event) => {\r\n this.#lastMessageAt = Date.now();\r\n this.#zombieReported = false;\r\n this.#message(ws, String(event.data));\r\n });\r\n ws.addEventListener(\"close\", (event) => this.#close(ws, event.code));\r\n ws.addEventListener(\"error\", () =>\r\n this.#emitError(new GatewayError(\"Gateway WebSocket error\")),\r\n );\r\n }\r\n #startZombieDetection(): void {\r\n if (this.#zombieTimer) clearInterval(this.#zombieTimer);\r\n const interval = Math.max(\r\n 1,\r\n Math.min(\r\n 250,\r\n this.#options.heartbeatAckTimeout,\r\n this.#options.zombieTimeout / 2,\r\n ),\r\n );\r\n this.#zombieTimer = setInterval(() => {\r\n if (\r\n this.#closed ||\r\n this.#ws?.readyState !== WebSocket.OPEN ||\r\n this.#lastMessageAt === 0\r\n )\r\n return;\r\n const silentFor = Date.now() - this.#lastMessageAt;\r\n const deadline = Math.max(\r\n this.#options.zombieTimeout,\r\n this.#heartbeatInterval + this.#options.heartbeatAckTimeout,\r\n );\r\n if (silentFor < deadline || this.#zombieReported) return;\r\n this.#zombieReported = true;\r\n const error = new GatewayError(\r\n `Gateway connection appears stale after ${silentFor}ms without traffic.`,\r\n );\r\n this.#emit(\"zombie\", { silentFor, timeout: deadline });\r\n this.#emitError(error);\r\n try {\r\n this.#ws.close(1001, \"Zombie Gateway connection\");\r\n } catch (closeError) {\r\n this.#emitError(closeError);\r\n }\r\n }, interval);\r\n }\r\n #message(ws: WebSocket, raw: string): void {\r\n let payload: GatewayPayload;\r\n try {\r\n payload = JSON.parse(raw) as GatewayPayload;\r\n } catch (error) {\r\n this.#emitError(\r\n new GatewayError(\"Gateway returned invalid JSON\", undefined, {\r\n cause: error,\r\n }),\r\n );\r\n ws.close(1002, \"Invalid JSON\");\r\n return;\r\n }\r\n if (!payload || typeof payload.op !== \"number\") {\r\n this.#emitError(new GatewayError(\"Gateway returned an invalid payload\"));\r\n ws.close(1002, \"Invalid payload\");\r\n return;\r\n }\r\n if (typeof payload.s === \"number\") this.#sequence = payload.s;\r\n switch (payload.op) {\r\n case GatewayOpcodes.Dispatch:\r\n this.#setState(GatewayState.Dispatch);\r\n this.#handleDispatch(payload.t, payload.d);\r\n break;\r\n case GatewayOpcodes.Hello:\r\n this.#handleHello(payload.d);\r\n break;\r\n case GatewayOpcodes.Heartbeat:\r\n this.#setState(GatewayState.Heartbeat);\r\n this.#sendHeartbeat();\r\n break;\r\n case GatewayOpcodes.HeartbeatAck:\r\n this.#heartbeatACK = true;\r\n this.#clearHeartbeatAckTimer();\r\n this.#emit(\"heartbeatAck\", payload.d);\r\n break;\r\n case GatewayOpcodes.Reconnect:\r\n ws.close(1001, \"Server requested reconnect\");\r\n break;\r\n case GatewayOpcodes.InvalidSession:\r\n this.#sessionId = undefined;\r\n this.#sequence = null;\r\n this.#emit(\"invalidSession\", payload.d);\r\n ws.close(1000, \"Invalid session\");\r\n break;\r\n }\r\n }\r\n #handleDispatch(event: string | null, data: unknown): void {\r\n if (event === \"READY\") {\r\n const ready = data as {\r\n session_id?: unknown;\r\n resume_gateway_url?: unknown;\r\n };\r\n if (\r\n typeof ready?.session_id !== \"string\" ||\r\n typeof ready?.resume_gateway_url !== \"string\"\r\n ) {\r\n this.#emitError(\r\n new GatewayError(\r\n \"Gateway READY payload is missing session information\",\r\n ),\r\n );\r\n return;\r\n }\r\n this.#sessionId = ready.session_id;\r\n this.#resumeURL = ready.resume_gateway_url;\r\n this.#attempt = 0;\r\n this.#setState(GatewayState.Ready);\r\n this.#emit(\"ready\", data);\r\n }\r\n this.#emit(\"RAW\", { event: event ?? \"UNKNOWN\", data });\r\n if (this.#closed) return;\r\n this.#emit(event ?? \"dispatch\", data);\r\n }\r\n #handleHello(data: unknown): void {\r\n const interval = (data as { heartbeat_interval?: unknown })\r\n ?.heartbeat_interval;\r\n if (\r\n typeof interval !== \"number\" ||\r\n !Number.isFinite(interval) ||\r\n interval <= 0\r\n ) {\r\n this.#emitError(\r\n new GatewayError(\r\n \"Gateway HELLO payload contains an invalid heartbeat interval\",\r\n ),\r\n );\r\n this.#ws?.close(1002, \"Invalid heartbeat interval\");\r\n return;\r\n }\r\n this.#heartbeatInterval = interval;\r\n this.#setState(\r\n this.#sessionId && this.#sequence !== null && this.#resumeURL\r\n ? GatewayState.Resume\r\n : GatewayState.Hello,\r\n );\r\n this.#startHeartbeat(interval);\r\n this.#identifyOrResume();\r\n }\r\n #identifyOrResume(): void {\r\n if (this.#sessionId && this.#sequence !== null && this.#resumeURL) {\r\n this.#setState(GatewayState.Resume);\r\n this.send({\r\n op: GatewayOpcodes.Resume,\r\n d: {\r\n token: this.#options.token,\r\n session_id: this.#sessionId,\r\n seq: this.#sequence,\r\n },\r\n s: null,\r\n t: null,\r\n });\r\n return;\r\n }\r\n this.#setState(GatewayState.Identify);\r\n const props = this.#options.properties ?? {\r\n os: \"Android\",\r\n browser: \"Discord Android\",\r\n device: \"Discord Android\",\r\n };\r\n const os = props.os ?? \"Android\";\r\n const browser = props.browser ?? \"Discord Android\";\r\n const device = props.device ?? \"Discord Android\";\r\n this.send({\r\n op: GatewayOpcodes.Identify,\r\n d: {\r\n token: this.#options.token,\r\n intents: this.#options.intents,\r\n properties: {\r\n os,\r\n browser,\r\n device,\r\n $os: os,\r\n $browser: browser,\r\n $device: device,\r\n ...props,\r\n },\r\n presence: {\r\n since: this.#options.presence?.since ?? null,\r\n activities: this.#options.presence?.activities ?? [],\r\n status: this.#options.presence?.status ?? \"online\",\r\n afk: Boolean(this.#options.presence?.afk),\r\n },\r\n shard: [this.#options.shardId, this.#options.shardCount],\r\n },\r\n s: null,\r\n t: null,\r\n });\r\n }\r\n #startHeartbeat(interval: number): void {\r\n this.#clearHeartbeatTimers();\r\n this.#heartbeatACK = true;\r\n this.#initialHeartbeat = setTimeout(\r\n () => this.#sendHeartbeat(),\r\n Math.random() * interval,\r\n );\r\n this.#heartbeatTimer = setInterval(() => this.#sendHeartbeat(), interval);\r\n }\r\n #sendHeartbeat(): void {\r\n this.#heartbeatACK = false;\r\n this.#heartbeatSentAt = Date.now();\r\n if (\r\n !this.send({\r\n op: GatewayOpcodes.Heartbeat,\r\n d: this.#sequence,\r\n s: null,\r\n t: null,\r\n })\r\n ) {\r\n this.#emitError(\r\n new GatewayError(\r\n \"Unable to send Gateway heartbeat because the WebSocket is not open.\",\r\n ),\r\n );\r\n return;\r\n }\r\n this.#clearHeartbeatAckTimer();\r\n this.#heartbeatAckTimer = setTimeout(() => {\r\n if (!this.#heartbeatACK) {\r\n const elapsed = Date.now() - this.#heartbeatSentAt;\r\n this.#emitError(\r\n new GatewayError(\r\n `Gateway heartbeat acknowledgement timed out after ${elapsed}ms.`,\r\n ),\r\n );\r\n try {\r\n this.#ws?.close(1001, \"Heartbeat timeout\");\r\n } catch (error) {\r\n this.#emitError(error);\r\n }\r\n }\r\n }, this.#options.heartbeatAckTimeout);\r\n }\r\n #close(ws: WebSocket, code: number): void {\r\n if (this.#ws !== ws) return;\r\n this.#ws = undefined;\r\n this.#clearTimers();\r\n const action = this.#closeAction(code);\r\n this.#emit(\"close\", { code, action });\r\n if (this.#closed || !this.#options.reconnect || action === \"stop\") {\r\n this.#setState(this.#closed ? GatewayState.Closed : GatewayState.Connect);\r\n if (this.#connectPromise)\r\n this.#settleConnect(\r\n new GatewayError(`Gateway closed before READY (code ${code}).`, code),\r\n );\r\n return;\r\n }\r\n if (action === \"identify\") {\r\n this.#sequence = null;\r\n this.#sessionId = undefined;\r\n }\r\n this.#setState(GatewayState.Reconnect);\r\n this.#scheduleReconnect();\r\n }\r\n #closeAction(code: number): \"resume\" | \"identify\" | \"stop\" {\r\n if ([4004, 4010, 4011, 4012, 4013, 4014].includes(code)) return \"stop\";\r\n if ([4007, 4009].includes(code)) return \"identify\";\r\n return this.#sessionId && this.#sequence !== null ? \"resume\" : \"identify\";\r\n }\r\n #scheduleReconnect(): void {\r\n if (this.#closed || !this.#options.reconnect || this.#reconnectTimer)\r\n return;\r\n if (this.#attempt >= this.#options.maxReconnectAttempts) {\r\n this.#settleConnect(\r\n new GatewayError(\"Gateway reconnect attempts exhausted.\"),\r\n );\r\n this.#setState(GatewayState.Connect);\r\n return;\r\n }\r\n const delay = Math.min(\r\n this.#options.reconnectMaxDelay,\r\n this.#options.reconnectBaseDelay * 2 ** this.#attempt++,\r\n );\r\n const jitter = Math.random() * Math.min(250, Math.max(1, delay * 0.25));\r\n this.#reconnectTimer = setTimeout(() => {\r\n this.#reconnectTimer = undefined;\r\n this.#open(\r\n this.#resumeURL ?? \"wss://gateway.discord.gg/?v=10&encoding=json\",\r\n );\r\n }, delay + jitter);\r\n }\r\n #settleConnect(error?: GatewayError): void {\r\n const resolve = this.#resolveConnect;\r\n const reject = this.#rejectConnect;\r\n this.#resolveConnect = undefined;\r\n this.#rejectConnect = undefined;\r\n this.#connectPromise = undefined;\r\n if (error) reject?.(error);\r\n else resolve?.();\r\n }\r\n #clearHeartbeatAckTimer(): void {\r\n if (this.#heartbeatAckTimer) clearTimeout(this.#heartbeatAckTimer);\r\n this.#heartbeatAckTimer = undefined;\r\n }\r\n #clearHeartbeatTimers(): void {\r\n if (this.#heartbeatTimer) clearInterval(this.#heartbeatTimer);\r\n if (this.#initialHeartbeat) clearTimeout(this.#initialHeartbeat);\r\n this.#clearHeartbeatAckTimer();\r\n this.#heartbeatTimer = undefined;\r\n this.#initialHeartbeat = undefined;\r\n }\r\n #clearTimers(): void {\r\n if (this.#reconnectTimer) clearTimeout(this.#reconnectTimer);\r\n if (this.#zombieTimer) clearInterval(this.#zombieTimer);\r\n this.#reconnectTimer = undefined;\r\n this.#zombieTimer = undefined;\r\n this.#clearHeartbeatTimers();\r\n }\r\n #normalizeError(error: unknown): GatewayError {\r\n return error instanceof GatewayError\r\n ? error\r\n : new GatewayError(\"Gateway connection failed.\", undefined, {\r\n cause: error,\r\n });\r\n }\r\n #emitError(error: unknown): void {\r\n this.#emit(\r\n \"error\",\r\n error instanceof Error ? error : new GatewayError(String(error)),\r\n );\r\n }\r\n #emit(event: string, data: unknown): void {\r\n for (const listener of this.#listeners.get(event) ?? []) {\r\n try {\r\n const result = listener(data);\r\n if (\r\n result &&\r\n typeof (result as PromiseLike<unknown>).then === \"function\"\r\n )\r\n void Promise.resolve(result).catch((error) => {\r\n if (event !== \"error\") this.#emitError(error);\r\n });\r\n } catch (error) {\r\n if (event !== \"error\") this.#emitError(error);\r\n }\r\n }\r\n }\r\n /** Changes the Gateway lifecycle state. @param next Next lifecycle state. */\r\n #setState(next: GatewayState): void {\r\n if (this.state === next) return;\r\n const previous = this.state;\r\n this.state = next;\r\n this.#emit(\"stateChange\", { previous, next });\r\n }\r\n}\r\n",
7
7
  "/** Message envelope exchanged between Lunibee shards. */\nexport interface ShardMessage<T = unknown> {\n /** Sending shard ID. */ source: number;\n /** Target shard ID, or null for broadcast. */ target: number | null;\n /** Application message type. */ type: string;\n /** Message payload. */ data: T;\n /** Unique message ID. */ id: string;\n}\n/** Handler invoked for shard messages. @typeParam T Message payload type. */\nexport type ShardMessageHandler<T = unknown> = (\n message: ShardMessage<T>,\n) => unknown;\n/** Bun/Node-compatible cross-shard transport using BroadcastChannel. */\nexport class ShardBus {\n /** Underlying broadcast channel. */ readonly #channel: BroadcastChannel;\n /** Message handlers by message type. */ readonly #handlers = new Map<\n string,\n Set<ShardMessageHandler>\n >();\n /** Current shard ID. */ readonly #shardId: number;\n /** Application-specific channel namespace. */ readonly #namespace: string;\n /** BroadcastChannel name used by this bus. */ public readonly channelName: string;\n /** Monotonic message counter. */ #counter = 0;\n /** Creates a shard bus. @param shardId Shard ID. @param channelName Application-specific channel name. @throws {RangeError} If shard ID is invalid. @throws {TypeError} If channel name is empty. */\n public constructor(shardId: number, channelName: string) {\n if (!Number.isInteger(shardId) || shardId < 0)\n throw new RangeError(\"Shard ID must be a non-negative integer.\");\n if (!channelName?.trim())\n throw new TypeError(\n \"An application-specific shard channel name is required.\",\n );\n this.#shardId = shardId;\n this.#namespace = channelName.trim();\n this.channelName = this.#namespace;\n this.#channel = new BroadcastChannel(this.channelName);\n this.#channel.addEventListener(\"message\", (event) =>\n this.#dispatch(event.data as ShardMessage),\n );\n }\n /** Registers a message handler. @param type Message type. @param handler Handler callback. @returns This bus. @throws {TypeError} If type or handler is invalid. */ public on<\n T,\n >(type: string, handler: ShardMessageHandler<T>): this {\n if (!type.trim() || typeof handler !== \"function\")\n throw new TypeError(\"Shard message type and handler are required.\");\n let handlers = this.#handlers.get(type);\n if (!handlers) this.#handlers.set(type, (handlers = new Set()));\n handlers.add(handler as ShardMessageHandler);\n return this;\n }\n /** Removes a message handler. @param type Message type. @param handler Handler callback. @returns This bus. */ public off<\n T,\n >(type: string, handler: ShardMessageHandler<T>): this {\n this.#handlers.get(type)?.delete(handler as ShardMessageHandler);\n return this;\n }\n /** Sends a targeted shard message. @param target Target shard ID. @param type Message type. @param data Payload. @returns Unique message ID. */ public send<\n T,\n >(target: number, type: string, data: T): string {\n if (!Number.isInteger(target) || target < 0)\n throw new RangeError(\"Shard target must be a non-negative integer.\");\n return this.#publish(target, type, data);\n }\n /** Broadcasts to all other shards. @param type Message type. @param data Payload. @returns Unique message ID. */ public broadcast<\n T,\n >(type: string, data: T): string {\n return this.#publish(null, type, data);\n }\n /** Closes the transport. @returns Nothing. */ public close(): void {\n this.#channel.close();\n this.#handlers.clear();\n }\n /** Publishes a message. @param target Target shard ID or null. @param type Message type. @param data Payload. @returns Unique message ID. */ #publish<\n T,\n >(target: number | null, type: string, data: T): string {\n if (!type.trim()) throw new TypeError(\"Shard message type is required.\");\n const id = `${this.#namespace}:${this.#shardId}:${++this.#counter}`;\n this.#channel.postMessage({\n source: this.#shardId,\n target,\n type,\n data,\n id,\n } satisfies ShardMessage<T>);\n return id;\n }\n /** Routes an incoming message to matching handlers. @param message Message envelope. @returns Nothing. */ #dispatch(\n message: ShardMessage,\n ): void {\n if (\n !message ||\n typeof message !== \"object\" ||\n typeof message.type !== \"string\"\n )\n return;\n if (\n message.source === this.#shardId ||\n (message.target !== null && message.target !== this.#shardId)\n )\n return;\n for (const handler of this.#handlers.get(message.type) ?? []) {\n try {\n const result = handler(message);\n if (\n result &&\n typeof (result as PromiseLike<unknown>).then === \"function\"\n )\n void Promise.resolve(result).catch(() => undefined);\n } catch {\n /* Consumer errors are isolated. */\n }\n }\n }\n}\n",
8
8
  "import { Gateway } from \"@lunibee/ws\";\nexport { ShardBus } from \"./bus.js\";\nexport type { ShardMessage, ShardMessageHandler } from \"./bus.js\";\n\n/** Configuration for a sharded Gateway client. */\nexport interface ShardManagerOptions {\n /** Bot token. */ token: string;\n /** Gateway intents. */ intents: number;\n /** Number of shards. Use `\"auto\"` to request Discord's recommended count. */ shardCount?:\n number | \"auto\";\n /** Gateway reconnect behavior. */ reconnect?: boolean;\n /** Delay between shard starts in milliseconds. */ spawnDelay?: number;\n}\n/** Runtime state for a managed shard. */\nexport interface ShardInfo {\n /** Shard identifier. */ id: number;\n /** Gateway instance. */ gateway: Gateway;\n}\n\n/** Manages independent Discord Gateway shards with explicit destruction and reinitialization semantics. */\nexport class ShardManager {\n /** Active Gateway shards indexed by shard identifier. */ public readonly shards =\n new Map<number, Gateway>();\n /** Number of shards managed by this instance after initialization. */ public get shardCount(): number {\n return this.shards.size;\n }\n readonly #options: ShardManagerOptions;\n /** Whether the shard set has been initialized. */ #resolved = false;\n /** Whether this manager is currently destroyed. */ #destroyed = false;\n /** Creates a shard manager. @param options Sharding configuration. @throws {TypeError} If token or intents are invalid. @throws {RangeError} If shard count is invalid. */\n public constructor(options: ShardManagerOptions) {\n if (!options.token?.trim())\n throw new TypeError(\"A Discord bot token is required.\");\n if (!Number.isInteger(options.intents) || options.intents < 0)\n throw new TypeError(\"Gateway intents must be a non-negative integer.\");\n const count =\n options.shardCount === \"auto\" || options.shardCount === undefined\n ? 1\n : options.shardCount;\n if (!Number.isInteger(count) || count < 1)\n throw new RangeError(\"Shard count must be a positive integer.\");\n this.#options = { ...options };\n if (options.shardCount !== \"auto\") this.#initialize(count);\n }\n /** Retrieves Discord's recommended shard count. @returns Recommended shard count. @throws {Error} If discovery fails or returns invalid data. */\n public async fetchRecommendedShardCount(): Promise<number> {\n const response = await fetch(\"https://discord.com/api/v10/gateway/bot\", {\n headers: {\n Authorization: `Bot ${this.#options.token}`,\n \"User-Agent\": \"Lunibee/0.1.0\",\n },\n });\n if (!response.ok)\n throw new Error(\n `Gateway discovery failed with status ${response.status}`,\n );\n const data = (await response.json()) as { shards?: unknown };\n if (\n typeof data.shards !== \"number\" ||\n !Number.isInteger(data.shards) ||\n data.shards < 1\n )\n throw new Error(\"Gateway discovery returned an invalid shard count.\");\n return data.shards;\n }\n /** Connects all shards sequentially. A destroyed manager is reinitialized before connecting. @returns A promise fulfilled after all shards connect. @throws {Error} If a shard fails to connect. */\n public async connect(): Promise<void> {\n await this.#ensureInitialized();\n for (const [id, shard] of this.shards) {\n try {\n await shard.connect();\n } catch (error) {\n this.destroy();\n throw new Error(`Failed to connect shard ${id}.`, { cause: error });\n }\n if (\n id + 1 < this.shardCount &&\n this.#options.spawnDelay &&\n this.#options.spawnDelay > 0\n )\n await Bun.sleep(this.#options.spawnDelay);\n }\n }\n /** Permanently closes the current shard set and releases Gateway resources. The next connect recreates them. @returns Nothing. */\n public destroy(): void {\n for (const shard of this.shards.values()) shard.close();\n this.shards.clear();\n this.#resolved = false;\n this.#destroyed = true;\n }\n /** Calculates the target shard ID for a Discord guild snowflake. @param guildId Guild snowflake. @returns Shard identifier. */\n public getShardIdForGuild(guildId: string): number {\n const id = BigInt(guildId);\n return Number((id >> 22n) % BigInt(this.shardCount || 1));\n }\n /** Gets a shard by ID. @param id Shard identifier. @returns Gateway instance or undefined. */ public get(\n id: number,\n ): Gateway | undefined {\n return this.shards.get(id);\n }\n /** Returns information for all managed shards. @returns Shard information snapshots. */ public values(): ShardInfo[] {\n return [...this.shards].map(([id, gateway]) => ({ id, gateway }));\n }\n /** Ensures a live shard set exists. @returns A promise fulfilled after initialization. @throws {Error} If initialization fails. */\n async #ensureInitialized(): Promise<void> {\n if (this.#resolved) return;\n if (this.#destroyed) this.#destroyed = false;\n const count =\n this.#options.shardCount === \"auto\"\n ? await this.fetchRecommendedShardCount()\n : (this.#options.shardCount ?? 1);\n this.#initialize(count);\n }\n /** Creates every shard for a resolved shard count. @param count Number of shards. @returns Nothing. */\n #initialize(count: number): void {\n if (this.#resolved) return;\n for (let id = 0; id < count; id++)\n this.shards.set(id, this.#createShard(id, count));\n this.#resolved = true;\n }\n /** Creates one Gateway instance with its shard identity. @param id Shard identifier. @param count Total shard count. @returns Configured Gateway. */\n #createShard(id: number, count: number): Gateway {\n return new Gateway({\n token: this.#options.token,\n intents: this.#options.intents,\n shardId: id,\n shardCount: count,\n reconnect: this.#options.reconnect ?? true,\n });\n }\n}\n"
9
9
  ],
10
- "mappings": "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",
11
- "debugId": "3D6EA7786F9CDC6964756E2164756E21",
10
+ "mappings": "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",
11
+ "debugId": "155A3557E58FD4CF64756E2164756E21",
12
12
  "names": []
13
13
  }
@@ -1,75 +1,126 @@
1
1
  /** Common Discord snowflake-backed structure. */
2
2
  export declare class BaseStructure {
3
- /** Discord resource ID. */
4
3
  readonly id: string;
5
- /** Creates a structure from an ID. @param id Discord snowflake identifier. @throws {TypeError} If the ID is invalid. */
6
4
  constructor(id: string);
7
- /** Returns the resource ID. @returns Discord snowflake identifier. */
5
+ /** Returns the snowflake ID as a string. */
8
6
  toString(): string;
7
+ /** Returns the timestamp this snowflake was created at. */
8
+ get createdAt(): Date;
9
9
  }
10
- /** Context used by structures to delegate resource operations to the owning client. */
11
10
  export interface ResourceContext {
12
- /** Sends a message through the owning channel manager. @param channelId Channel identifier. @param options Message payload. @returns The created message. */
13
- sendMessage(channelId: string, options: {
11
+ sendMessage(channelId: string, options: Record<string, unknown> & {
14
12
  content?: string;
15
13
  }): Promise<import("./index.js").Message>;
16
- /** Edits a message through the owning channel manager. @param channelId Channel identifier. @param messageId Message identifier. @param options Edit payload. @returns The updated message. */
17
- editMessage(channelId: string, messageId: string, options: {
14
+ editMessage(channelId: string, messageId: string, options: Record<string, unknown> & {
18
15
  content?: string;
19
16
  }): Promise<import("./index.js").Message>;
20
- /** Deletes a message through the owning channel manager. @param channelId Channel identifier. @param messageId Message identifier. @returns A promise fulfilled after deletion. */
21
17
  deleteMessage(channelId: string, messageId: string): Promise<void>;
22
- /** Crossposts a message through the owning channel manager. @param channelId Channel identifier. @param messageId Message identifier. @returns The crossposted message. */
23
18
  crosspostMessage(channelId: string, messageId: string): Promise<import("./index.js").Message>;
19
+ editChannel?(channelId: string, options: Record<string, unknown>): Promise<import("./base.js").Channel>;
20
+ deleteChannel?(channelId: string): Promise<void>;
21
+ addReaction?(channelId: string, messageId: string, emoji: string): Promise<void>;
22
+ removeOwnReaction?(channelId: string, messageId: string, emoji: string): Promise<void>;
23
+ removeReaction?(channelId: string, messageId: string, emoji: string, userId: string): Promise<void>;
24
+ removeAllReactions?(channelId: string, messageId: string): Promise<void>;
25
+ pinMessage?(channelId: string, messageId: string): Promise<void>;
26
+ unpinMessage?(channelId: string, messageId: string): Promise<void>;
27
+ }
28
+ /** Options for CDN image URLs. */
29
+ export interface ImageURLOptions {
30
+ extension?: "png" | "jpg" | "webp" | "gif" | "jpeg";
31
+ size?: 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096;
32
+ forceStatic?: boolean;
24
33
  }
25
- /** Represents a Discord user. */
26
34
  export declare class User extends BaseStructure {
27
- /** User name. */ username: string;
28
- /** Global display name. */ globalName: string | null;
29
- /** Avatar hash. */ avatar: string | null;
30
- /** Whether the user is a bot. */ bot: boolean;
31
- /** Whether the account is a Discord system user. */ system: boolean;
32
- /** Public user flags. */ flags: number;
33
- /** Creates a user from Discord API data. @param data User payload. @throws {TypeError} If required data is invalid. */
35
+ username: string;
36
+ globalName: string | null;
37
+ avatar: string | null;
38
+ bot: boolean;
39
+ system: boolean;
40
+ flags: number;
41
+ discriminator: string | null;
34
42
  constructor(data: import("@lunibee/types").UserData);
35
- /** Gets the effective display name. @returns Global display name or username. */
43
+ /** Effective display name — global name, falling back to username. */
36
44
  get displayName(): string;
37
- /** Creates an avatar CDN URL. @param options URL format options. @returns Avatar URL, or null when no custom avatar exists. */
38
- avatarURL(options?: {
39
- extension?: "png" | "jpg" | "webp" | "gif";
40
- size?: number;
41
- }): string | null;
42
- /** Creates the default avatar URL. @returns Discord default avatar URL. */
45
+ /** Returns the user's avatar URL, or null if they have no avatar. */
46
+ avatarURL(options?: ImageURLOptions): string | null;
47
+ /** Returns the default avatar URL based on the user's discriminator/snowflake. */
43
48
  defaultAvatarURL(): string;
44
- /** Creates an avatar URL with default fallback. @param options URL format options. @returns Avatar or default avatar URL. */
45
- displayAvatarURL(options?: {
46
- extension?: "png" | "jpg" | "webp" | "gif";
47
- size?: number;
48
- }): string;
49
+ /** Returns the avatar URL if available, falling back to the default avatar URL. */
50
+ displayAvatarURL(options?: ImageURLOptions): string;
51
+ /** Returns the Discord mention string. Used automatically in template literals. */
52
+ toString(): string;
49
53
  }
50
- /** Represents a Discord channel. */
51
54
  export declare class Channel extends BaseStructure {
52
55
  #private;
53
- /** Discord channel type. */ type: number;
54
- /** Channel name. */ name?: string | null;
55
- /** Guild containing the channel. */ guildId?: string;
56
- /** Creates a channel from Discord API data. @param data Channel payload. @param context Optional owning resource context. @throws {TypeError|RangeError} If required channel data is invalid. */
56
+ type: number;
57
+ name?: string | null;
58
+ guildId?: string;
59
+ topic?: string | null;
60
+ parentId?: string | null;
61
+ nsfw?: boolean;
62
+ rateLimitPerUser?: number;
63
+ position?: number;
64
+ /** Creates a channel structure from Discord channel data. */
57
65
  constructor(data: import("@lunibee/types").APIChannel, context?: ResourceContext);
58
- /** Sends a message through the owning manager. @param options Message payload. @returns The created message. @throws {Error} If this channel is detached from a client. */
59
- sendMessage(options: {
66
+ /** Sends a message to this channel. @param options Message payload. @returns The created message. @throws {Error} If the channel is not attached to a client. */
67
+ sendMessage(options: Record<string, unknown> & {
68
+ content?: string;
69
+ }): Promise<import("./index.js").Message>;
70
+ /** Sends a message using Lunibee's concise channel API. @param options Message payload. @returns The created message. @throws {Error} If the channel is not attached to a client. */
71
+ send(options: Record<string, unknown> & {
60
72
  content?: string;
61
73
  }): Promise<import("./index.js").Message>;
74
+ /** Edits this channel. @param options Channel fields to change. @returns The updated channel. @throws {Error} If the channel is not attached to a client. */
75
+ edit(options: Record<string, unknown>): Promise<Channel>;
76
+ /** Changes only this channel's name. @param name New channel name. @returns The updated channel. @throws {TypeError} If the name is empty. @throws {Error} If the channel is not attached to a client. */
77
+ editName(name: string): Promise<Channel>;
78
+ /** Changes only this channel's topic. @param topic New topic, or null to clear it. @returns The updated channel. @throws {Error} If the channel is not attached to a client. */
79
+ editTopic(topic: string | null): Promise<Channel>;
80
+ /** Moves this channel to another parent category. @param parentId Parent category ID, or null to remove the parent. @returns The updated channel. @throws {Error} If the channel is not attached to a client. */
81
+ editParent(parentId: string | null): Promise<Channel>;
82
+ /** Deletes this channel. @returns A promise fulfilled when Discord confirms deletion. @throws {Error} If the channel is not attached to a client. */
83
+ delete(): Promise<void>;
84
+ /** Updates this channel using the same resource operation as edit. @param options Channel fields to change. @returns The updated channel. @throws {Error} If the channel is not attached to a client. */
85
+ update(options: Record<string, unknown>): Promise<Channel>;
86
+ /** Returns the Discord channel mention string. Used automatically in template literals. */
87
+ toString(): string;
62
88
  }
63
- /** Represents a Discord guild. */
64
89
  export declare class Guild extends BaseStructure {
65
- /** Guild name. */ name: string;
66
- /** Preferred guild locale. */ preferredLocale?: string;
67
- /** Guild owner ID. */ ownerId?: string;
68
- /** Creates a guild from Discord API data. @param data Guild payload. @throws {TypeError} If required data is invalid. */
69
- constructor(data: {
70
- id: string;
71
- name: string;
72
- preferred_locale?: string;
73
- owner_id?: string;
74
- });
90
+ name: string;
91
+ icon: string | null;
92
+ splash: string | null;
93
+ banner: string | null;
94
+ description: string | null;
95
+ preferredLocale: string;
96
+ ownerId?: string;
97
+ features: string[];
98
+ verificationLevel: number;
99
+ premiumTier: number;
100
+ premiumSubscriptionCount: number;
101
+ memberCount?: number;
102
+ approximateMemberCount?: number;
103
+ approximatePresenceCount?: number;
104
+ vanityUrlCode: string | null;
105
+ nsfwLevel: number;
106
+ discoverySplash: string | null;
107
+ constructor(data: import("@lunibee/types").APIGuild);
108
+ /** Returns the guild icon URL, or null if no icon is set. */
109
+ iconURL(options?: ImageURLOptions): string | null;
110
+ /** Returns the guild splash URL, or null if none. */
111
+ splashURL(options?: ImageURLOptions): string | null;
112
+ /** Returns the guild banner URL, or null if none. */
113
+ bannerURL(options?: ImageURLOptions): string | null;
114
+ /** Returns the guild discovery splash URL, or null if none. */
115
+ discoverySplashURL(options?: ImageURLOptions): string | null;
116
+ /** Whether the guild has a given feature flag. @param feature Feature string, e.g. "COMMUNITY". */
117
+ hasFeature(feature: string): boolean;
118
+ /** Whether the guild is a Community server. */
119
+ get isCommunity(): boolean;
120
+ /** Whether the guild has a vanity URL. */
121
+ get hasVanityUrl(): boolean;
122
+ /** Returns the guild's vanity invite URL, or null if none. */
123
+ get vanityURL(): string | null;
124
+ /** Returns a human-readable string representation. */
125
+ toString(): string;
75
126
  }
@@ -0,0 +1,65 @@
1
+ import type { APIEmbed, APIEmbedAuthor, APIEmbedField, APIEmbedFooter, APIEmbedMedia } from "@lunibee/types";
2
+ /**
3
+ * A rich Embed structure that wraps a Discord API embed object.
4
+ * Provides typed accessors and a fluent builder interface.
5
+ */
6
+ export declare class Embed {
7
+ #private;
8
+ /** Creates an Embed from raw Discord API data, or starts a blank embed. */
9
+ constructor(data?: APIEmbed);
10
+ /** Embed title. */
11
+ get title(): string | undefined;
12
+ /** Embed description. */
13
+ get description(): string | undefined;
14
+ /** Embed URL. */
15
+ get url(): string | undefined;
16
+ /** Embed color as an integer. */
17
+ get color(): number | undefined;
18
+ /** Embed timestamp ISO 8601 string. */
19
+ get timestamp(): string | undefined;
20
+ /** Embed timestamp as a Date object, or undefined. */
21
+ get createdAt(): Date | undefined;
22
+ /** Embed footer. */
23
+ get footer(): APIEmbedFooter | undefined;
24
+ /** Embed image. */
25
+ get image(): APIEmbedMedia | undefined;
26
+ /** Embed thumbnail. */
27
+ get thumbnail(): APIEmbedMedia | undefined;
28
+ /** Embed video. */
29
+ get video(): APIEmbedMedia | undefined;
30
+ /** Embed author. */
31
+ get author(): APIEmbedAuthor | undefined;
32
+ /** Embed fields (read-only copy). */
33
+ get fields(): readonly APIEmbedField[];
34
+ /** Sets the embed title. @param title Embed title text (max 256 chars). @throws {TypeError} If title exceeds 256 characters. */
35
+ setTitle(title: string): this;
36
+ /** Sets the embed description. @param description Embed description (max 4096 chars). @throws {TypeError} If description exceeds 4096 characters. */
37
+ setDescription(description: string): this;
38
+ /** Sets the embed URL. @param url A valid URL string. */
39
+ setURL(url: string): this;
40
+ /** Sets the embed color. Accepts a hex number (0xff0000), decimal integer, or hex string ("#ff0000"). @param color Color value. */
41
+ setColor(color: number | string): this;
42
+ /** Sets the embed timestamp. Accepts a Date, ISO string, or number (ms since epoch). Defaults to now. */
43
+ setTimestamp(timestamp?: Date | string | number): this;
44
+ /** Sets the embed footer. @param text Footer text (max 2048 chars). @param iconURL Optional footer icon URL. */
45
+ setFooter(text: string, iconURL?: string): this;
46
+ /** Sets the embed image. @param url Image URL. */
47
+ setImage(url: string): this;
48
+ /** Sets the embed thumbnail. @param url Thumbnail URL. */
49
+ setThumbnail(url: string): this;
50
+ /** Sets the embed author. @param name Author name (max 256 chars). @param options Optional URL and icon URL. */
51
+ setAuthor(name: string, options?: {
52
+ url?: string;
53
+ iconURL?: string;
54
+ }): this;
55
+ /** Adds one or more fields to the embed. @param fields Fields to add (max 25 total). @throws {TypeError} If adding exceeds 25 fields. */
56
+ addFields(...fields: APIEmbedField[]): this;
57
+ /** Removes all fields from the embed. */
58
+ clearFields(): this;
59
+ /** Splices the fields array, replacing, inserting, or deleting fields. @param index Start index. @param deleteCount Number of fields to remove. @param fields Replacement fields. */
60
+ spliceFields(index: number, deleteCount: number, ...fields: APIEmbedField[]): this;
61
+ /** Returns the raw Discord API embed payload. */
62
+ toJSON(): APIEmbed;
63
+ /** Creates an Embed from an existing raw API embed object. */
64
+ static from(data: APIEmbed): Embed;
65
+ }