Downgrade to v13
[vi] cảm giác đau khổ
This commit is contained in:
@@ -1,13 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const EventEmitter = require('node:events');
|
||||
const { setTimeout, setInterval, clearTimeout, clearInterval } = require('node:timers');
|
||||
const { GatewayDispatchEvents, GatewayIntentBits, GatewayOpcodes } = require('discord-api-types/v9');
|
||||
const { setTimeout, setInterval } = require('node:timers');
|
||||
const WebSocket = require('../../WebSocket');
|
||||
const Events = require('../../util/Events');
|
||||
const IntentsBitField = require('../../util/IntentsBitField');
|
||||
const ShardEvents = require('../../util/ShardEvents');
|
||||
const Status = require('../../util/Status');
|
||||
const { Status, Events, ShardEvents, Opcodes, WSEvents } = require('../../util/Constants');
|
||||
const Intents = require('../../util/Intents');
|
||||
|
||||
const STATUS_KEYS = Object.keys(Status);
|
||||
const CONNECTION_STATE = Object.keys(WebSocket.WebSocket);
|
||||
@@ -41,7 +38,7 @@ class WebSocketShard extends EventEmitter {
|
||||
* The current status of the shard
|
||||
* @type {Status}
|
||||
*/
|
||||
this.status = Status.Idle;
|
||||
this.status = Status.IDLE;
|
||||
|
||||
/**
|
||||
* The current sequence of the shard
|
||||
@@ -180,17 +177,17 @@ class WebSocketShard extends EventEmitter {
|
||||
connect() {
|
||||
const { gateway, client } = this.manager;
|
||||
|
||||
if (this.connection?.readyState === WebSocket.OPEN && this.status === Status.Ready) {
|
||||
if (this.connection?.readyState === WebSocket.OPEN && this.status === Status.READY) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const cleanup = () => {
|
||||
this.removeListener(ShardEvents.Close, onClose);
|
||||
this.removeListener(ShardEvents.Ready, onReady);
|
||||
this.removeListener(ShardEvents.Resumed, onResumed);
|
||||
this.removeListener(ShardEvents.InvalidSession, onInvalidOrDestroyed);
|
||||
this.removeListener(ShardEvents.Destroyed, onInvalidOrDestroyed);
|
||||
this.removeListener(ShardEvents.CLOSE, onClose);
|
||||
this.removeListener(ShardEvents.READY, onReady);
|
||||
this.removeListener(ShardEvents.RESUMED, onResumed);
|
||||
this.removeListener(ShardEvents.INVALID_SESSION, onInvalidOrDestroyed);
|
||||
this.removeListener(ShardEvents.DESTROYED, onInvalidOrDestroyed);
|
||||
};
|
||||
|
||||
const onReady = () => {
|
||||
@@ -214,11 +211,11 @@ class WebSocketShard extends EventEmitter {
|
||||
reject();
|
||||
};
|
||||
|
||||
this.once(ShardEvents.Ready, onReady);
|
||||
this.once(ShardEvents.Resumed, onResumed);
|
||||
this.once(ShardEvents.Close, onClose);
|
||||
this.once(ShardEvents.InvalidSession, onInvalidOrDestroyed);
|
||||
this.once(ShardEvents.Destroyed, onInvalidOrDestroyed);
|
||||
this.once(ShardEvents.READY, onReady);
|
||||
this.once(ShardEvents.RESUMED, onResumed);
|
||||
this.once(ShardEvents.CLOSE, onClose);
|
||||
this.once(ShardEvents.INVALID_SESSION, onInvalidOrDestroyed);
|
||||
this.once(ShardEvents.DESTROYED, onInvalidOrDestroyed);
|
||||
|
||||
if (this.connection?.readyState === WebSocket.OPEN) {
|
||||
this.debug('An open connection was found, attempting an immediate identify.');
|
||||
@@ -251,7 +248,7 @@ class WebSocketShard extends EventEmitter {
|
||||
Compression: ${zlib ? 'zlib-stream' : 'none'}`,
|
||||
);
|
||||
|
||||
this.status = this.status === Status.Disconnected ? Status.Reconnecting : Status.Connecting;
|
||||
this.status = this.status === Status.DISCONNECTED ? Status.RECONNECTING : Status.CONNECTING;
|
||||
this.setHelloTimeout();
|
||||
|
||||
this.connectedAt = Date.now();
|
||||
@@ -270,7 +267,7 @@ class WebSocketShard extends EventEmitter {
|
||||
*/
|
||||
onOpen() {
|
||||
this.debug(`[CONNECTED] Took ${Date.now() - this.connectedAt}ms`);
|
||||
this.status = Status.Nearly;
|
||||
this.status = Status.NEARLY;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -296,11 +293,11 @@ class WebSocketShard extends EventEmitter {
|
||||
try {
|
||||
packet = WebSocket.unpack(raw);
|
||||
} catch (err) {
|
||||
this.manager.client.emit(Events.ShardError, err, this.id);
|
||||
this.manager.client.emit(Events.SHARD_ERROR, err, this.id);
|
||||
return;
|
||||
}
|
||||
this.manager.client.emit(Events.Raw, packet, this.id);
|
||||
if (packet.op === GatewayOpcodes.Dispatch) this.manager.emit(packet.t, packet.d, this.id);
|
||||
this.manager.client.emit(Events.RAW, packet, this.id);
|
||||
if (packet.op === Opcodes.DISPATCH) this.manager.emit(packet.t, packet.d, this.id);
|
||||
this.onPacket(packet);
|
||||
}
|
||||
|
||||
@@ -319,7 +316,7 @@ class WebSocketShard extends EventEmitter {
|
||||
* @param {Error} error The encountered error
|
||||
* @param {number} shardId The shard that encountered this error
|
||||
*/
|
||||
this.manager.client.emit(Events.ShardError, error, this.id);
|
||||
this.manager.client.emit(Events.SHARD_ERROR, error, this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -356,7 +353,7 @@ class WebSocketShard extends EventEmitter {
|
||||
// If we still have a connection object, clean up its listeners
|
||||
if (this.connection) this._cleanupConnection();
|
||||
|
||||
this.status = Status.Disconnected;
|
||||
this.status = Status.DISCONNECTED;
|
||||
|
||||
/**
|
||||
* Emitted when a shard's WebSocket closes.
|
||||
@@ -364,7 +361,7 @@ class WebSocketShard extends EventEmitter {
|
||||
* @event WebSocketShard#close
|
||||
* @param {CloseEvent} event The received event
|
||||
*/
|
||||
this.emit(ShardEvents.Close, event);
|
||||
this.emit(ShardEvents.CLOSE, event);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -379,28 +376,28 @@ class WebSocketShard extends EventEmitter {
|
||||
}
|
||||
|
||||
switch (packet.t) {
|
||||
case GatewayDispatchEvents.Ready:
|
||||
case WSEvents.READY:
|
||||
/**
|
||||
* Emitted when the shard receives the READY payload and is now waiting for guilds
|
||||
* @event WebSocketShard#ready
|
||||
*/
|
||||
this.emit(ShardEvents.Ready);
|
||||
this.emit(ShardEvents.READY);
|
||||
|
||||
this.sessionId = packet.d.session_id;
|
||||
this.expectedGuilds = new Set(packet.d.guilds.map(d => d.id));
|
||||
this.status = Status.WaitingForGuilds;
|
||||
this.status = Status.WAITING_FOR_GUILDS;
|
||||
this.debug(`[READY] Session ${this.sessionId}.`);
|
||||
this.lastHeartbeatAcked = true;
|
||||
this.sendHeartbeat('ReadyHeartbeat');
|
||||
break;
|
||||
case GatewayDispatchEvents.Resumed: {
|
||||
case WSEvents.RESUMED: {
|
||||
/**
|
||||
* Emitted when the shard resumes successfully
|
||||
* @event WebSocketShard#resumed
|
||||
*/
|
||||
this.emit(ShardEvents.Resumed);
|
||||
this.emit(ShardEvents.RESUMED);
|
||||
|
||||
this.status = Status.Ready;
|
||||
this.status = Status.READY;
|
||||
const replayed = packet.s - this.closeSequence;
|
||||
this.debug(`[RESUMED] Session ${this.sessionId} | Replayed ${replayed} events.`);
|
||||
this.lastHeartbeatAcked = true;
|
||||
@@ -412,16 +409,16 @@ class WebSocketShard extends EventEmitter {
|
||||
if (packet.s > this.sequence) this.sequence = packet.s;
|
||||
|
||||
switch (packet.op) {
|
||||
case GatewayOpcodes.Hello:
|
||||
case Opcodes.HELLO:
|
||||
this.setHelloTimeout(-1);
|
||||
this.setHeartbeatTimer(packet.d.heartbeat_interval);
|
||||
this.identify();
|
||||
break;
|
||||
case GatewayOpcodes.Reconnect:
|
||||
case Opcodes.RECONNECT:
|
||||
this.debug('[RECONNECT] Discord asked us to reconnect');
|
||||
this.destroy({ closeCode: 4_000 });
|
||||
break;
|
||||
case GatewayOpcodes.InvalidSession:
|
||||
case Opcodes.INVALID_SESSION:
|
||||
this.debug(`[INVALID SESSION] Resumable: ${packet.d}.`);
|
||||
// If we can resume the session, do so immediately
|
||||
if (packet.d) {
|
||||
@@ -433,19 +430,19 @@ class WebSocketShard extends EventEmitter {
|
||||
// Reset the session id as it's invalid
|
||||
this.sessionId = null;
|
||||
// Set the status to reconnecting
|
||||
this.status = Status.Reconnecting;
|
||||
this.status = Status.RECONNECTING;
|
||||
// Finally, emit the INVALID_SESSION event
|
||||
this.emit(ShardEvents.InvalidSession);
|
||||
this.emit(ShardEvents.INVALID_SESSION);
|
||||
break;
|
||||
case GatewayOpcodes.HeartbeatAck:
|
||||
case Opcodes.HEARTBEAT_ACK:
|
||||
this.ackHeartbeat();
|
||||
break;
|
||||
case GatewayOpcodes.Heartbeat:
|
||||
case Opcodes.HEARTBEAT:
|
||||
this.sendHeartbeat('HeartbeatRequest', true);
|
||||
break;
|
||||
default:
|
||||
this.manager.handlePacket(packet, this);
|
||||
if (this.status === Status.WaitingForGuilds && packet.t === GatewayDispatchEvents.GuildCreate) {
|
||||
if (this.status === Status.WAITING_FOR_GUILDS && packet.t === WSEvents.GUILD_CREATE) {
|
||||
this.expectedGuilds.delete(packet.d.id);
|
||||
this.checkReady();
|
||||
}
|
||||
@@ -465,7 +462,7 @@ class WebSocketShard extends EventEmitter {
|
||||
// Step 1. If we don't have any other guilds pending, we are ready
|
||||
if (!this.expectedGuilds.size) {
|
||||
this.debug('Shard received all its guilds. Marking as fully ready.');
|
||||
this.status = Status.Ready;
|
||||
this.status = Status.READY;
|
||||
|
||||
/**
|
||||
* Emitted when the shard is fully ready.
|
||||
@@ -475,10 +472,10 @@ class WebSocketShard extends EventEmitter {
|
||||
* @event WebSocketShard#allReady
|
||||
* @param {?Set<string>} unavailableGuilds Set of unavailable guilds, if any
|
||||
*/
|
||||
this.emit(ShardEvents.AllReady);
|
||||
this.emit(ShardEvents.ALL_READY);
|
||||
return;
|
||||
}
|
||||
const hasGuildsIntent = new IntentsBitField(this.manager.client.options.intents).has(GatewayIntentBits.Guilds);
|
||||
const hasGuildsIntent = new Intents(this.manager.client.options.intents).has(Intents.FLAGS.GUILDS);
|
||||
// Step 2. Create a timeout that will mark the shard as ready if there are still unavailable guilds
|
||||
// * The timeout is 15 seconds by default
|
||||
// * This can be optionally changed in the client options via the `waitGuildTimeout` option
|
||||
@@ -497,11 +494,11 @@ class WebSocketShard extends EventEmitter {
|
||||
|
||||
this.readyTimeout = null;
|
||||
|
||||
this.status = Status.Ready;
|
||||
this.status = Status.READY;
|
||||
|
||||
this.emit(ShardEvents.AllReady, this.expectedGuilds);
|
||||
this.emit(ShardEvents.ALL_READY, this.expectedGuilds);
|
||||
},
|
||||
0,
|
||||
hasGuildsIntent ? waitGuildTimeout : 0,
|
||||
).unref();
|
||||
}
|
||||
|
||||
@@ -555,7 +552,7 @@ class WebSocketShard extends EventEmitter {
|
||||
*/
|
||||
sendHeartbeat(
|
||||
tag = 'HeartbeatTimer',
|
||||
ignoreHeartbeatAck = [Status.WaitingForGuilds, Status.Identifying, Status.Resuming].includes(this.status),
|
||||
ignoreHeartbeatAck = [Status.WAITING_FOR_GUILDS, Status.IDENTIFYING, Status.RESUMING].includes(this.status),
|
||||
) {
|
||||
if (ignoreHeartbeatAck && !this.lastHeartbeatAcked) {
|
||||
this.debug(`[${tag}] Didn't process heartbeat ack yet but we are still connected. Sending one now.`);
|
||||
@@ -574,7 +571,7 @@ class WebSocketShard extends EventEmitter {
|
||||
this.debug(`[${tag}] Sending a heartbeat.`);
|
||||
this.lastHeartbeatAcked = false;
|
||||
this.lastPingTimestamp = Date.now();
|
||||
this.send({ op: GatewayOpcodes.Heartbeat, d: this.sequence }, true);
|
||||
this.send({ op: Opcodes.HEARTBEAT, d: this.sequence }, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -608,16 +605,18 @@ class WebSocketShard extends EventEmitter {
|
||||
return;
|
||||
}
|
||||
|
||||
this.status = Status.Identifying;
|
||||
this.status = Status.IDENTIFYING;
|
||||
|
||||
// Clone the identify payload and assign the token and shard info
|
||||
const d = {
|
||||
...client.options.ws,
|
||||
intents: Intents.resolve(client.options.intents),
|
||||
token: client.token,
|
||||
shard: [this.id, Number(client.options.shardCount)],
|
||||
};
|
||||
|
||||
this.debug(`[IDENTIFY] Shard ${this.id}/${client.options.shardCount} with intents: 32767`);
|
||||
this.send({ op: GatewayOpcodes.Identify, d }, true);
|
||||
this.debug(`[IDENTIFY] Shard ${this.id}/${client.options.shardCount} with intents: ${d.intents}`);
|
||||
this.send({ op: Opcodes.IDENTIFY, d }, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -631,7 +630,7 @@ class WebSocketShard extends EventEmitter {
|
||||
return;
|
||||
}
|
||||
|
||||
this.status = Status.Resuming;
|
||||
this.status = Status.RESUMING;
|
||||
|
||||
this.debug(`[RESUME] Session ${this.sessionId}, sequence ${this.closeSequence}`);
|
||||
|
||||
@@ -641,7 +640,7 @@ class WebSocketShard extends EventEmitter {
|
||||
seq: this.closeSequence,
|
||||
};
|
||||
|
||||
this.send({ op: GatewayOpcodes.Resume, d }, true);
|
||||
this.send({ op: Opcodes.RESUME, d }, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -671,7 +670,7 @@ class WebSocketShard extends EventEmitter {
|
||||
}
|
||||
|
||||
this.connection.send(WebSocket.pack(data), err => {
|
||||
if (err) this.manager.client.emit(Events.ShardError, err, this.id);
|
||||
if (err) this.manager.client.emit(Events.SHARD_ERROR, err, this.id);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -741,8 +740,8 @@ class WebSocketShard extends EventEmitter {
|
||||
// Step 2: Null the connection object
|
||||
this.connection = null;
|
||||
|
||||
// Step 3: Set the shard status to Disconnected
|
||||
this.status = Status.Disconnected;
|
||||
// Step 3: Set the shard status to DISCONNECTED
|
||||
this.status = Status.DISCONNECTED;
|
||||
|
||||
// Step 4: Cache the old sequence (use to attempt a resume)
|
||||
if (this.sequence !== -1) this.closeSequence = this.sequence;
|
||||
@@ -780,7 +779,7 @@ class WebSocketShard extends EventEmitter {
|
||||
* @private
|
||||
* @event WebSocketShard#destroyed
|
||||
*/
|
||||
this.emit(ShardEvents.Destroyed);
|
||||
this.emit(ShardEvents.DESTROYED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user