hopefully make the DiscordClient connection more robust
This commit is contained in:
parent
fe04b99c35
commit
0950241d3b
2 changed files with 84 additions and 34 deletions
111
DiscordClient.js
111
DiscordClient.js
|
@ -7,10 +7,16 @@ const opcodes = {
|
||||||
EVENT: 0,
|
EVENT: 0,
|
||||||
CLIENT_HEARTBEAT: 1,
|
CLIENT_HEARTBEAT: 1,
|
||||||
IDENTIFY: 2,
|
IDENTIFY: 2,
|
||||||
|
RESUME: 6,
|
||||||
|
INVALID_SESSION: 9,
|
||||||
HELLO: 10,
|
HELLO: 10,
|
||||||
HEARTBEAT_ACK: 11,
|
HEARTBEAT_ACK: 11,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const reconnectOnCloseCodes = [
|
||||||
|
1000, 1001, 4000, 4001, 4002, 4003, 4005, 4007, 4008, 4009
|
||||||
|
];
|
||||||
|
|
||||||
class DiscordClient extends EventEmitter {
|
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, baseDomain="discord.com", gatewayUrl="wss://gateway.discord.gg/?v=9&encoding=json&compress=zlib-stream", apiBase="https://discord.com/api/v9" } = {}) {
|
||||||
super();
|
super();
|
||||||
|
@ -50,6 +56,37 @@ class DiscordClient extends EventEmitter {
|
||||||
}, this._heartbeatIntervalTime);
|
}, this._heartbeatIntervalTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_getIdentifyPayload() {
|
||||||
|
return {
|
||||||
|
token: this.token,
|
||||||
|
intents: this.intents,
|
||||||
|
properties: {
|
||||||
|
"$os": "linux",
|
||||||
|
"$browser": "generic",
|
||||||
|
"$device": "generic"
|
||||||
|
},
|
||||||
|
presence: {
|
||||||
|
since: Date.now(),
|
||||||
|
activities: [
|
||||||
|
{
|
||||||
|
type: 2, // LISTENING
|
||||||
|
name: "the voices"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
status: "online",
|
||||||
|
afk: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
_getResumePayload() {
|
||||||
|
return {
|
||||||
|
token: this.token,
|
||||||
|
session_id: this.sessionId,
|
||||||
|
seq: this.seq
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
_handleGatewayMessage(ws, message) {
|
_handleGatewayMessage(ws, message) {
|
||||||
try {
|
try {
|
||||||
message = JSON.parse(message);
|
message = JSON.parse(message);
|
||||||
|
@ -68,29 +105,18 @@ class DiscordClient extends EventEmitter {
|
||||||
case opcodes.HELLO: {
|
case opcodes.HELLO: {
|
||||||
this._setHeartbeat(payload.heartbeat_interval);
|
this._setHeartbeat(payload.heartbeat_interval);
|
||||||
|
|
||||||
ws.send(JSON.stringify({
|
if (this.resuming) {
|
||||||
op: opcodes.IDENTIFY,
|
console.warn("DiscordClient: resuming...");
|
||||||
d: {
|
ws.send(JSON.stringify({
|
||||||
token: this.token,
|
op: opcodes.RESUME,
|
||||||
intents: this.intents,
|
d: this._getResumePayload()
|
||||||
properties: {
|
}));
|
||||||
"$os": "linux",
|
} else {
|
||||||
"$browser": "generic",
|
ws.send(JSON.stringify({
|
||||||
"$device": "generic"
|
op: opcodes.IDENTIFY,
|
||||||
},
|
d: this._getIdentifyPayload()
|
||||||
presence: {
|
}));
|
||||||
since: Date.now(),
|
}
|
||||||
activities: [
|
|
||||||
{
|
|
||||||
type: 2, // LISTENING
|
|
||||||
name: "the voices"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
status: "online",
|
|
||||||
afk: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,6 +209,23 @@ class DiscordClient extends EventEmitter {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
console.warn(`warn: DiscordClient: got unhandled opcode "${message.op}"`);
|
console.warn(`warn: DiscordClient: got unhandled opcode "${message.op}"`);
|
||||||
break;
|
break;
|
||||||
|
@ -191,6 +234,12 @@ class DiscordClient extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
|
if (this.ws) {
|
||||||
|
this.ws.removeAllListeners();
|
||||||
|
this.ws.close();
|
||||||
|
this.ws = null;
|
||||||
|
}
|
||||||
|
|
||||||
const ws = new WebSocket(this.gatewayUrl);
|
const ws = new WebSocket(this.gatewayUrl);
|
||||||
|
|
||||||
this.ws = ws;
|
this.ws = ws;
|
||||||
|
@ -208,16 +257,22 @@ class DiscordClient extends EventEmitter {
|
||||||
|
|
||||||
ws.on("close", (code, reason) => {
|
ws.on("close", (code, reason) => {
|
||||||
reason = reason.toString();
|
reason = reason.toString();
|
||||||
this.emit("close", code, reason);
|
|
||||||
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;
|
||||||
|
this.connect();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ws.on("error", (e) => {
|
ws.on("error", (e) => {
|
||||||
console.error("DiscordClient: websocket error:", e);
|
console.error("DiscordClient: websocket error:", e);
|
||||||
console.log("DiscordClient: reconnecting in a couple of miliseconds");
|
console.log("DiscordClient: reconnecting?");
|
||||||
setTimeout(() => {
|
this._setHeartbeat(-1);
|
||||||
this.connect();
|
this.resuming = true;
|
||||||
}, 400);
|
this.connect();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ export function wait(time, shouldReject=false) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bot.on("READY", () => {
|
bot.once("READY", () => {
|
||||||
watchedGuildIds.forEach(id => {
|
watchedGuildIds.forEach(id => {
|
||||||
const watchedGuild = new WatchedGuild();
|
const watchedGuild = new WatchedGuild();
|
||||||
watchedGuild.upstreamGuildId = id;
|
watchedGuild.upstreamGuildId = id;
|
||||||
|
@ -21,8 +21,3 @@ bot.on("READY", () => {
|
||||||
guildMap.set(id, watchedGuild);
|
guildMap.set(id, watchedGuild);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
bot.on("close", (code, reason) => {
|
|
||||||
console.log("bot: connection closed, reconnecting...");
|
|
||||||
bot.connect();
|
|
||||||
});
|
|
||||||
|
|
Loading…
Reference in a new issue