hopefully improve discordclient reconnecting

This commit is contained in:
hippoz 2022-02-14 22:18:33 +02:00
parent 742a46c708
commit 5ce0b81864
Signed by: hippoz
GPG key ID: 7C52899193467641

View file

@ -7,18 +7,17 @@ const opcodes = {
EVENT: 0,
CLIENT_HEARTBEAT: 1,
IDENTIFY: 2,
RESUME: 6,
INVALID_SESSION: 9,
HELLO: 10,
HEARTBEAT_ACK: 11,
};
const reconnectOnCloseCodes = [
1000, 1001, 4000, 4001, 4002, 4003, 4005, 4007, 4008, 4009
const skipReconnectFor = [
4004, 4010, 4011, 4012, 4013, 4014
];
class DiscordClient extends EventEmitter {
constructor(token, { intents, baseDomain="discord.com", gatewayUrl="wss://gateway.discord.gg/?v=9&encoding=json&compress=zlib-stream", apiBase="https://discord.com/api/v9" } = {}) {
constructor(token, { intents, gatewayUrl="wss://gateway.discord.gg/?v=9&encoding=json&compress=zlib-stream", apiBase="https://discord.com/api/v9" } = {}) {
super();
this.token = token;
@ -79,19 +78,11 @@ class DiscordClient extends EventEmitter {
};
}
_getResumePayload() {
return {
token: this.token,
session_id: this.sessionId,
seq: this.seq
};
}
_handleGatewayMessage(ws, message) {
try {
message = JSON.parse(message);
} catch(e) {
console.error("error: DiscordClient: on `message`: failed to parse incoming message as JSON", e);
console.error("error: DiscordClient: on 'message': failed to parse incoming message as JSON", e);
return;
}
@ -103,28 +94,20 @@ class DiscordClient extends EventEmitter {
switch (message.op) {
case opcodes.HELLO: {
console.log(`DiscordClient: HELLO; heartbeat_interval=${payload.heartbeat_interval}`);
this._setHeartbeat(payload.heartbeat_interval);
if (this.resuming) {
console.warn("DiscordClient: resuming...");
this.resuming = false;
ws.send(JSON.stringify({
op: opcodes.RESUME,
d: this._getResumePayload()
}));
} else {
ws.send(JSON.stringify({
op: opcodes.IDENTIFY,
d: this._getIdentifyPayload()
}));
}
ws.send(JSON.stringify({
op: opcodes.IDENTIFY,
d: this._getIdentifyPayload()
}));
break;
}
case opcodes.EVENT: {
switch (message.t) {
case "READY": {
console.log("DiscordClient: ready");
console.log("DiscordClient: READY");
this.user = payload.user;
this.sessionId = payload.session_id;
this.guilds = payload.guilds;
@ -211,19 +194,8 @@ class DiscordClient extends EventEmitter {
}
case opcodes.INVALID_SESSION: {
if (message.d) {
// connection is resumable, we are going to resume the connection
this.resuming = true;
this.connect();
} else {
// connection is not resumable, wait some time and then send a new IDENTIFY payload
setTimeout(() => {
ws.send(JSON.stringify({
op: opcodes.IDENTIFY,
d: this._getIdentifyPayload()
}));
}, 3500);
}
console.error("DiscordClient: INVALID_SESSION - please check your authentication token");
console.error("DiscordClient: INVALID_SESSION: will not reconnect");
break;
}
@ -235,7 +207,9 @@ class DiscordClient extends EventEmitter {
}
connect() {
console.log("DiscordClient: connecting...");
if (this.ws) {
console.log("DiscordClient: a websocket connection already exists, killing...");
this.ws.removeAllListeners();
this.ws.close();
this.ws = null;
@ -249,30 +223,37 @@ class DiscordClient extends EventEmitter {
});
// we decompressed the data, send it to the handler now
this.inflate.on("data", (message) => this._handleGatewayMessage(ws, message));
this.inflate.on("data", (message) =>
this._handleGatewayMessage(ws, message)
);
ws.on("message", (data, isBinary) => {
// pass the data to the decompressor
this.inflate.write(data);
});
ws.on("open", () => {
console.log("DiscordClient: WebSocket 'open'")
});
ws.on("close", (code, reason) => {
reason = reason.toString();
console.error(`DiscordClient: on \`close\`: disconnected from gateway: code \`${code}\`, reason \`${reason}\``);
console.error(`DiscordClient: on 'close': disconnected from gateway: code '${code}', reason '${reason}'`);
this.emit("close", code, reason);
this._setHeartbeat(-1);
if (reconnectOnCloseCodes.includes(code)) {
this.resuming = true;
if (skipReconnectFor.includes(code)) {
console.error("DiscordClient: on 'close': the exit code above is in skipReconnectFor, and thus the server will not reconnect.");
} else {
console.log("DiscordClient: on 'close': the client will now attempt to reconnect...");
this.connect();
}
});
ws.on("error", (e) => {
console.error("DiscordClient: websocket error:", e);
console.log("DiscordClient: reconnecting?");
console.error("DiscordClient: on 'error': websocket error:", e);
console.log("DiscordClient: on 'error': reconnecting due to previous websocket error...");
this._setHeartbeat(-1);
this.resuming = true;
this.connect();
});
}
@ -301,4 +282,4 @@ class DiscordClient extends EventEmitter {
}
}
export default DiscordClient;
export default DiscordClient;