diff --git a/DiscordClient.js b/DiscordClient.js index 7aa4293..3bed32b 100644 --- a/DiscordClient.js +++ b/DiscordClient.js @@ -11,6 +11,7 @@ const opcodes = { EVENT: 0, CLIENT_HEARTBEAT: 1, IDENTIFY: 2, + UPDATE_PRESENCE: 3, RECONNECT: 7, INVALID_SESSION: 9, HELLO: 10, @@ -24,7 +25,7 @@ const skipReconnectFor = [ const CLOSE_CONNECTION_ON_NO_ACK = false; class DiscordClient extends EventEmitter { - constructor(token, { intents, gatewayUrl="wss://gateway.discord.gg/?v=10&encoding=json", apiBase="https://discord.com/api/v10" } = {}) { + constructor(token, { intents, gatewayUrl="wss://gateway.discord.gg/?v=10&encoding=json", apiBase="https://discord.com/api/v10", presence = { activities: [{name: "the voices", type: 2}], status: "online", afk: false } } = {}) { super(); this.token = token; @@ -38,6 +39,8 @@ class DiscordClient extends EventEmitter { this.sessionId = null; this.seq = null; this.gotServerHeartbeatACK = true; + this.defaultPresence = presence; + this.connectEnabled = true; } _setHeartbeat(interval) { @@ -71,17 +74,7 @@ class DiscordClient extends EventEmitter { "$browser": "generic", "$device": "generic" }, - presence: { - since: Date.now(), - activities: [ - { - type: 2, // LISTENING - name: "the voices" - } - ], - status: "online", - afk: false - } + presence: this.defaultPresence }; } @@ -220,6 +213,10 @@ class DiscordClient extends EventEmitter { } connect() { + if (!this.connectEnabled) { + return; + } + log("connecting..."); if (this.ws) { log("a websocket connection already exists, killing..."); @@ -264,6 +261,12 @@ class DiscordClient extends EventEmitter { }); } + close() { + this.connectEnabled = false; + this._setHeartbeat(-1); + this.ws.close(); + } + async api(method, path, body=undefined, throwOnError=true) { const options = { method, diff --git a/index.js b/index.js index e1f5792..1920e0e 100644 --- a/index.js +++ b/index.js @@ -33,7 +33,7 @@ const createServerChildProcess = () => { class Bridge { constructor() { this.gatewayConnection = new DiscordClient(DISCORD_TOKEN, { - intents: 0 | (1 << 0) | (1 << 9) | (1 << 15) // GUILDS | GUILD_MESSAGES | MESSAGE_CONTENT + intents: 0 | (1 << 0) | (1 << 9) | (1 << 15), // GUILDS | GUILD_MESSAGES | MESSAGE_CONTENT }); this.process = null; this.rconConnection = null; @@ -56,7 +56,8 @@ class Bridge { `${this.serverStartedAt ? `Started: ` : "Started: [server is closed]"}\n` + `\n` + `:busts_in_silhouette: **Players** (${this.players.length})\n` + - this.players.length > 0 ? this.players.map(p => `${p}\n`) : "[no players]\n" + + (this.players.length > 0 ? this.players.map(p => `${p}\n`) : "[no players]\n") + + "\n" + `:gear: **Runtime Information**\n` + `process exists: \`${!!this.process}\`\n` + `gatewayConnection.user exists: \`${!!this.gatewayConnection.user}\``; @@ -142,7 +143,7 @@ class Bridge { this.process.on("spawn", () => { log("server process: spawn"); - this.serverStartedAt = performance.now(); + this.serverStartedAt = Date.now(); this.process.stdout.resume(); this.process.stderr.resume(); this.sendExternalMessage(":zap: Server started. It might take some time before it fully initializes."); @@ -262,7 +263,6 @@ class Bridge { } } - function main() { for (const [name, value] of Object.entries(requiredEnv)) { if (value === undefined) { @@ -276,6 +276,7 @@ function main() { ["exit", "SIGINT", "SIGUSR1", "SIGUSR2", "uncaughtException", "SIGTERM"].forEach((eventType) => { process.on(eventType, () => { bridge.stopProcess(); + bridge.gatewayConnection.close(); process.exit(); }); });