diff --git a/packages/gateway/src/Shard.ts b/packages/gateway/src/Shard.ts index b4892b672..2482e332c 100644 --- a/packages/gateway/src/Shard.ts +++ b/packages/gateway/src/Shard.ts @@ -2,7 +2,6 @@ import type { DiscordGatewayPayload, DiscordHello, DiscordReady } from '@discord import { GatewayCloseEventCodes, GatewayOpcodes } from '@discordeno/types' import { createLeakyBucket, delay } from '@discordeno/utils' import { inflateSync } from 'zlib' -import type { GatewayManager } from './manager.js' import type { BotStatusUpdate, ShardEvents, ShardGatewayConfig, ShardHeart, ShardSocketRequest } from './types.js' import { ShardSocketCloseCodes, ShardState } from './types.js' @@ -13,8 +12,8 @@ export const DEFAULT_HEARTBEAT_INTERVAL = 45000 export class Shard { /** The id of the shard */ id: number - /** The gateway manager that is responsible for this this. */ - manager: GatewayManager + /** The connection config details that this shard will used to connect to discord. */ + connection: ShardGatewayConfig /** This contains all the heartbeat information */ heart: ShardHeart /** The maximum of requests which can be send to discord per rate limit tick. Typically this value should not be changed. */ @@ -29,12 +28,14 @@ export class Shard { socket?: WebSocket /** Current internal state of the this. */ state = ShardState.Offline - /** The total amount of shards which are used to communicate with Discord. */ - // totalShards: number /** The url provided by discord to use when resuming a connection for this this. */ resumeGatewayUrl: string = '' /** The shard related event handlers. */ events: ShardEvents = {} + /** Cache for pending gateway requests which should have been send while the gateway went offline. */ + offlineSendQueue: Array<(_?: unknown) => void> = [] + /** Resolve internal waiting states. Mapped by SelectedEvents => ResolveFunction */ + resolves = new Map<'READY' | 'RESUMED' | 'INVALID_SESSION', (payload: DiscordGatewayPayload) => void>() /** Shard bucket. Only access this if you know what you are doing. Bucket for handling shard request rate limits. */ bucket = createLeakyBucket({ max: 120, @@ -42,16 +43,9 @@ export class Shard { refillAmount: 120 }) - /** Cache for pending gateway requests which should have been send while the gateway went offline. */ - offlineSendQueue: Array<(_?: unknown) => void> = [] - - /** Resolve internal waiting states. Mapped by SelectedEvents => ResolveFunction */ - resolves = new Map<'READY' | 'RESUMED' | 'INVALID_SESSION', (payload: DiscordGatewayPayload) => void>() - - constructor (manager: GatewayManager, shardId: number) { + constructor (shardId: number, connection: ShardGatewayConfig) { this.id = shardId - // TODO: can this be done without a manager? - this.manager = manager + this.connection = connection this.heart = { acknowledged: false, @@ -61,18 +55,7 @@ export class Shard { /** The gateway configuration which is used to connect to Discord. */ get gatewayConfig (): ShardGatewayConfig { - return { - compress: this.manager.compress, - intents: this.manager.intents, - properties: { - os: this.manager.properties.os, - browser: this.manager.properties.browser, - device: this.manager.properties.device - }, - token: this.manager.token, - url: this.manager.url, - version: this.manager.version - } + return this.connection } /** Calculate the amount of requests which can safely be made per rate limit interval, before the gateway gets disconnected due to an exceeded rate limit. */ @@ -174,7 +157,7 @@ export class Shard { compress: this.gatewayConfig.compress, properties: this.gatewayConfig.properties, intents: this.gatewayConfig.intents, - shard: [this.id, this.manager.totalShards], + shard: [this.id, this.gatewayConfig.totalShards], presence: await this.makePresence?.() } }, diff --git a/packages/gateway/src/types.ts b/packages/gateway/src/types.ts index 14903fbe0..ad5f80d08 100644 --- a/packages/gateway/src/types.ts +++ b/packages/gateway/src/types.ts @@ -4,15 +4,11 @@ import type Shard from './Shard.js' export enum ShardState { /** Shard is fully connected to the gateway and receiving events from Discord. */ Connected = 0, - /** Shard started to connect to the gateway. - * This is only used if the shard is not currently trying to identify or resume. - */ + /** Shard started to connect to the gateway. This is only used if the shard is not currently trying to identify or resume. */ Connecting = 1, /** Shard got disconnected and reconnection actions have been started. */ Disconnected = 2, - /** The shard is connected to the gateway but only heartbeating. - * At this state the shard has not been identified with discord. - */ + /** The shard is connected to the gateway but only heartbeating. At this state the shard has not been identified with discord. */ Unidentified = 3, /** Shard is trying to identify with the gateway to create a new session. */ Identifying = 4, @@ -24,45 +20,50 @@ export enum ShardState { export interface ShardGatewayConfig { /** Whether incoming payloads are compressed using zlib. - * - * @default false - */ + * + * @default false + */ compress: boolean /** The calculated intent value of the events which the shard should receive. - * - * @default 0 - */ + * + * @default 0 + */ intents: number /** Identify properties to use */ properties: { /** Operating system the shard runs on. - * - * @default "darwin" | "linux" | "windows" - */ + * + * @default "darwin" | "linux" | "windows" + */ os: string /** The "browser" where this shard is running on. - * - * @default "Discordeno" - */ + * + * @default "Discordeno" + */ browser: string /** The device on which the shard is running. - * - * @default "Discordeno" - */ + * + * @default "Discordeno" + */ device: string } /** Bot token which is used to connect to Discord */ token: string /** The URL of the gateway which should be connected to. - * - * @default "wss://gateway.discord.gg" - */ + * + * @default "wss://gateway.discord.gg" + */ url: string /** The gateway version which should be used. - * - * @default 10 - */ + * + * @default 10 + */ version: number + /** + * The total number of shards to connect to across the entire bot. + * @default 1 + */ + totalShards: number } export interface ShardHeart { @@ -77,9 +78,9 @@ export interface ShardHeart { /** Unix timestamp (in milliseconds) when the last heartbeat was sent. */ lastBeat?: number /** Round trip time (in milliseconds) from Shard to Discord and back. - * Calculated using the heartbeat system. - * Note: this value is undefined until the first heartbeat to Discord has happened. - */ + * Calculated using the heartbeat system. + * Note: this value is undefined until the first heartbeat to Discord has happened. + */ rtt?: number /** Id of the timeout which is used for sending the first heartbeat to Discord since it's "special". */ timeoutId?: NodeJS.Timeout @@ -120,8 +121,8 @@ export enum ShardSocketCloseCodes { /** A resume has been requested and therefore the old connection needs to be closed. */ ResumeClosingOldConnection = 3024, /** Did not receive a heartbeat ACK in time. - * Closing the shard and creating a new session. - */ + * Closing the shard and creating a new session. + */ ZombiedConnection = 3010, /** Discordeno's gateway tests hae been finished, therefore the Shard can be turned off. */ TestingFinished = 3064,