diff --git a/packages/ws/src/discord/heartbeater.ts b/packages/ws/src/discord/heartbeater.ts index 9650cfa..aafde7b 100644 --- a/packages/ws/src/discord/heartbeater.ts +++ b/packages/ws/src/discord/heartbeater.ts @@ -30,7 +30,7 @@ export class ShardHeartBeater { interval: 30_000 }; // biome-ignore lint/nursery/noEmptyBlockStatements: - constructor(public shard: Shard) {} + constructor(public shard: Shard) { } acknowledge(ack = true) { this.heart.ack = ack; @@ -106,6 +106,12 @@ export class ShardHeartBeater { } this.startHeartBeating(); + + if (this.shard.data.session_id) { + this.shard.resume(); + } else { + this.shard.identify() + } } onpacket(packet: GatewayReceivePayload) { diff --git a/packages/ws/src/discord/shard.ts b/packages/ws/src/discord/shard.ts index 2080ec9..fbfc143 100644 --- a/packages/ws/src/discord/shard.ts +++ b/packages/ws/src/discord/shard.ts @@ -47,7 +47,6 @@ export class Shard { } isOpen() { - this.logger.fatal(`[Shard #${this.id}]`, "isOpen", this.websocket?.readyState === WebSocket.OPEN); return this.websocket?.readyState === WebSocket.OPEN; } @@ -67,7 +66,6 @@ export class Shard { } connect() { - this.logger.fatal(`[Shard #${this.id}]`, "Connect", this.state); if (![ShardState.Resuming, ShardState.Identifying].includes(this.state)) { this.state = ShardState.Connecting; } @@ -96,30 +94,17 @@ export class Shard { } checkOffline(priority: number) { - // biome-ignore lint/style/noArguments: - // biome-ignore lint/correctness/noUndeclaredVariables: - this.logger.fatal(`[Shard #${this.id}]`, "checkOffline", ...arguments); if (!this.isOpen()) { return new Promise((resolve) => this.offlineSendQueue.push(resolve, priority)); } return Promise.resolve(); } - async identify(justTry = false) { - this.logger.debug(`[Shard #${this.id}] ${justTry ? "Trying " : ""}on identify ${this.isOpen()}`); - - if (this.isOpen()) { - if (justTry) return; - this.logger.debug(`[Shard #${this.id}] CLOSING EXISTING SHARD`); - this.close(ShardSocketCloseCodes.ReIdentifying, "Re-identifying closure of old connection."); - } + async identify() { + this.logger.debug(`[Shard #${this.id}] on identify ${this.isOpen()}`); this.state = ShardState.Identifying; - if (!this.isOpen()) { - await this.connect(); - } - this.send(0, { op: GatewayOpcodes.Identify, d: { @@ -132,15 +117,19 @@ export class Shard { }); } + reconnect() { + this.heartbeater.stopHeartbeating() + this.disconnect(); + return this.connect(); + } + resume() { - this.logger.fatal(`[Shard #${this.id}]`, "Resuming"); this.state = ShardState.Resuming; const data = { seq: this.data.resumeSeq!, session_id: this.data.session_id!, token: `Bot ${this.options.token}`, }; - console.log({ data }); return this.send(0, { d: data, op: GatewayOpcodes.Resume }); } @@ -151,9 +140,6 @@ export class Shard { * in simpler terms, do not use where we don't want buckets */ async send(priority: number, message: T) { - // biome-ignore lint/style/noArguments: - // biome-ignore lint/correctness/noUndeclaredVariables: - this.logger.fatal(`[Shard #${this.id}]`, "Send", ...arguments); // Before acquiring a token from the bucket, check whether the shard is currently offline or not. // Else bucket and token wait time just get wasted. await this.checkOffline(priority); @@ -197,30 +183,19 @@ export class Shard { this.heartbeater.onpacket(packet); switch (packet.op) { - case GatewayOpcodes.Hello: - if (this.data.session_id) { - await this.resume(); - } else { - // await this.identify(true); - } - break; case GatewayOpcodes.Reconnect: - this.disconnect(); - await this.connect(); - // await this.resume(); + this.reconnect(); break; case GatewayOpcodes.InvalidSession: { - const resumable = packet.d as boolean; + const resumable = packet.d && this.data.session_id // We need to wait for a random amount of time between 1 and 5 // Reference: https://discord.com/developers/docs/topics/gateway#resuming - // el delay es el tipico timoeut promise, hazmelo pls - //yo con un import { setTimeout as delay } from 'node:timers/promises'; en la mochila await delay(Math.floor((Math.random() * 4 + 1) * 1000)); if (!resumable) { this.data.resumeSeq = 0; this.data.session_id = undefined; - await this.identify(true); + await this.connect(); break; } await this.resume(); @@ -254,8 +229,6 @@ export class Shard { } disconnect() { - // biome-ignore lint/style/noArguments: - // biome-ignore lint/correctness/noUndeclaredVariables: this.logger.info(`[Shard #${this.id}]`, "Disconnect", ...arguments); this.close(ShardSocketCloseCodes.Shutdown, "Shard down request"); this.state = ShardState.Offline; @@ -281,7 +254,8 @@ export class Shard { this.logger.debug(`[Shard #${this.id}] Gateway connection closing requiring re-identify. Code: ${close.code}`); this.state = ShardState.Identifying; - return this.identify(); + this.connect(); + break; case GatewayCloseCodes.AuthenticationFailed: case GatewayCloseCodes.InvalidShard: case GatewayCloseCodes.ShardingRequired: @@ -293,8 +267,7 @@ export class Shard { throw new Error(close.reason || "Discord gave no reason! GG! You broke Discord!"); // Gateway connection closes on which a resume is allowed. default: - console.log(close.code); - this.logger.info(`[Shard #${this.id}] closed shard #${this.id}. Resuming...`); + this.logger.info(`[Shard #${this.id}] (${close.code}) closed shard #${this.id}. Resuming...`); this.state = ShardState.Resuming; this.disconnect(); diff --git a/packages/ws/src/discord/sharder.ts b/packages/ws/src/discord/sharder.ts index a48258a..0acf244 100644 --- a/packages/ws/src/discord/sharder.ts +++ b/packages/ws/src/discord/sharder.ts @@ -72,7 +72,7 @@ export class ShardManager extends Collection { for (const shard of bucket) { if (!shard) break; this.logger.info(`${shard.id} add to connect queue`); - await this.connectQueue.push(shard.identify.bind(shard, false)); + await this.connectQueue.push(shard.connect.bind(shard)); } } }