From ee2e192204b8b3c408bcca9bfe8890fc492a841d Mon Sep 17 00:00:00 2001 From: hippoz <10706925-hippoz@users.noreply.gitlab.com> Date: Tue, 15 Feb 2022 14:24:46 +0200 Subject: [PATCH] improve login system on the server --- DiscordClient.js | 40 ++++++++++++++++++++++++++-------------- GatewayServer.js | 2 -- common.js | 32 +++++++++++++++++++++++++++++++- config.js | 17 +++++++++++++++++ index.js | 6 ++++-- routes/api.js | 14 ++++++++------ 6 files changed, 86 insertions(+), 25 deletions(-) diff --git a/DiscordClient.js b/DiscordClient.js index 6b5b2fe..4da82d1 100644 --- a/DiscordClient.js +++ b/DiscordClient.js @@ -2,11 +2,17 @@ import EventEmitter from "events"; import zlib from "zlib"; import { WebSocket } from "ws"; import fetch from "node-fetch"; +import { logger } from "./common.js"; + +const log = logger("log", "DiscordClient"); +const logError = logger("error", "DiscordClient"); +const logWarn = logger("warn", "DiscordClient"); const opcodes = { EVENT: 0, CLIENT_HEARTBEAT: 1, IDENTIFY: 2, + RECONNECT: 7, INVALID_SESSION: 9, HELLO: 10, HEARTBEAT_ACK: 11, @@ -82,7 +88,7 @@ class DiscordClient extends EventEmitter { try { message = JSON.parse(message); } catch(e) { - console.error("error: DiscordClient: on 'message': failed to parse incoming message as JSON", e); + logError("on 'message': failed to parse incoming message as JSON", e); return; } @@ -94,7 +100,7 @@ class DiscordClient extends EventEmitter { switch (message.op) { case opcodes.HELLO: { - console.log(`DiscordClient: HELLO; heartbeat_interval=${payload.heartbeat_interval}`); + log(`HELLO; heartbeat_interval=${payload.heartbeat_interval}`); this._setHeartbeat(payload.heartbeat_interval); ws.send(JSON.stringify({ @@ -107,7 +113,7 @@ class DiscordClient extends EventEmitter { case opcodes.EVENT: { switch (message.t) { case "READY": { - console.log("DiscordClient: READY"); + log("READY"); this.user = payload.user; this.sessionId = payload.session_id; this.guilds = payload.guilds; @@ -194,22 +200,28 @@ class DiscordClient extends EventEmitter { } case opcodes.INVALID_SESSION: { - console.error("DiscordClient: INVALID_SESSION - please check your authentication token"); - console.error("DiscordClient: INVALID_SESSION: will not reconnect"); + logError("INVALID_SESSION - please check your authentication token"); + logError("INVALID_SESSION: will not reconnect"); + break; + } + + case opcodes.RECONNECT: { + log("gateway is requesting reconnect (payload RECONNECT)"); + this.connect(); break; } default: { - console.warn(`warn: DiscordClient: got unhandled opcode "${message.op}"`); + logWarn(`got unhandled opcode "${message.op}"`); break; } } } connect() { - console.log("DiscordClient: connecting..."); + log("connecting..."); if (this.ws) { - console.log("DiscordClient: a websocket connection already exists, killing..."); + log("a websocket connection already exists, killing..."); this.ws.removeAllListeners(); this.ws.close(); this.ws = null; @@ -233,26 +245,26 @@ class DiscordClient extends EventEmitter { ws.on("open", () => { - console.log("DiscordClient: WebSocket 'open'") + log("WebSocket 'open'"); }); ws.on("close", (code, reason) => { reason = reason.toString(); - console.error(`DiscordClient: on 'close': disconnected from gateway: code '${code}', reason '${reason}'`); + logError(`on 'close': disconnected from gateway: code '${code}', reason '${reason}'`); this.emit("close", code, reason); this._setHeartbeat(-1); if (skipReconnectFor.includes(code)) { - console.error("DiscordClient: on 'close': the exit code above is in skipReconnectFor, and thus the server will not reconnect."); + logError("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..."); + log("on 'close': the client will now attempt to reconnect..."); this.connect(); } }); ws.on("error", (e) => { - console.error("DiscordClient: on 'error': websocket error:", e); - console.log("DiscordClient: on 'error': reconnecting due to previous websocket error..."); + logError("on 'error': websocket error:", e); + log("on 'error': reconnecting due to previous websocket error..."); this._setHeartbeat(-1); this.connect(); }); diff --git a/GatewayServer.js b/GatewayServer.js index 562f55a..8c0458b 100644 --- a/GatewayServer.js +++ b/GatewayServer.js @@ -99,7 +99,6 @@ class GatewayServer { try { message = JSON.parse(message.toString()); } catch (e) { - console.error("GatewayServer: payload decode error", e); return ws.close(4000, "Payload error."); } @@ -113,7 +112,6 @@ class GatewayServer { try { user = await decodeToken(message.d.token); } catch(e) { - console.error(e); ws.close(4001, "Bad token."); break; } diff --git a/common.js b/common.js index 1b62a2d..fe581bd 100644 --- a/common.js +++ b/common.js @@ -1,4 +1,4 @@ -import { discordToken, watchedGuildIds } from "./config.js"; +import { discordToken, logContextMap, watchedGuildIds } from "./config.js"; import DiscordClient from "./DiscordClient.js"; import WatchedGuild from "./WatchedGuild.js"; @@ -13,6 +13,36 @@ export function wait(time, shouldReject=false) { }); } +export function logger(sink, context) { + let sinkFunction; + switch (sink) { + case "log": { + sinkFunction = console.log; + break; + } + case "warn": { + sinkFunction = console.warn; + break; + } + case "error": { + sinkFunction = console.error; + break; + } + default: { + sinkFunction = () => {}; + break; + } + } + + if (logContextMap[context] && logContextMap[context][sink]) { + return (...e) => { + sinkFunction(`[${context}]`, ...e); + }; + } else { + return (...e) => {}; + } +} + bot.once("READY", () => { watchedGuildIds.forEach(id => { const watchedGuild = new WatchedGuild(); diff --git a/config.js b/config.js index 2158dca..52ec2e2 100644 --- a/config.js +++ b/config.js @@ -3,3 +3,20 @@ export const watchedGuildIds = ["822089558886842418", "736292509134749807"]; export const jwtSecret = process.env.JWT_SECRET; export const discordToken = process.env.DISCORD_TOKEN; export const dangerousAdminMode = true; +export const logContextMap = { + DiscordClient: { + log: true, + warn: true, + error: true, + }, + ServerMain: { + log: true, + warn: true, + error: true, + }, + API: { + log: true, + warn: true, + error: true, + } +}; diff --git a/index.js b/index.js index 0a0180a..cdfc8d4 100644 --- a/index.js +++ b/index.js @@ -2,9 +2,11 @@ import http from "node:http"; import express from "express"; import apiRoute from "./routes/api.js"; import { mainHttpListenPort } from "./config.js"; -import { bot } from "./common.js"; +import { bot, logger } from "./common.js"; import GatewayServer from "./GatewayServer.js"; +const log = logger("log", "ServerMain"); + // might introduce bugs and probably a bad idea Object.freeze(Object.prototype); Object.freeze(Object); @@ -21,6 +23,6 @@ app.use("/", express.static("frontend/public/")); app.use("/api/v1", apiRoute); httpServer.listen(mainHttpListenPort, () => { - console.log(`server main: listen on ${mainHttpListenPort}`); + log(`http listen on ${mainHttpListenPort}`); bot.connect(); }); \ No newline at end of file diff --git a/routes/api.js b/routes/api.js index 2f45474..3bc5003 100644 --- a/routes/api.js +++ b/routes/api.js @@ -1,8 +1,10 @@ import express from "express"; -import { guildMap, wait } from "../common.js"; +import { guildMap, logger } from "../common.js"; import { dangerousAdminMode } from "../config.js"; import { checkAuth, createToken } from "../tokens.js"; +const error = logger("error", "API"); + const router = express(); router.get("/", (req, res) => { @@ -69,7 +71,7 @@ router.post("/guilds/:guildId/channels/:channelId/messages/create", checkAuth(as await guild.discordSendMessage(messageContent, channelId, username, avatarURL); res.status(201).send({ error: false }); } catch(e) { - console.error("server main: api: message create: error: ", e); + error("[message create] [error]", e); res.status(500).send({ error: true, message: "ERROR_MESSAGE_SEND_FAILURE" }); } })); @@ -88,7 +90,7 @@ router.get("/guilds/:guildId/channels", checkAuth(async (req, res) => { try { res.status(200).send({ error: false, channels: guild.userFacingChannelList() }); } catch(e) { - console.error("server main: api: guild get channels: error: ", e); + error("[guild get channels] [error]", e); res.status(500).send({ error: true, message: "ERROR_CHANNELS_FETCH_FAILURE" }); } })); @@ -107,7 +109,7 @@ router.get("/guilds/:guildId", checkAuth(async (req, res) => { try { res.status(200).send({ error: false, guild: guild.guildObject }); } catch(e) { - console.error("server main: api: guild get info: error: ", e); + error("[guild get info]", e); res.status(500).send({ error: true, message: "ERROR_GUILD_INFO_FETCH_FAILURE" }); } })); @@ -133,7 +135,7 @@ router.get("/guilds/:guildId/events/poll", checkAuth(async (req, res) => { guild.holdForEvent(15000) .then(result => res.status(200).send({ error: false, event: result })); } catch(e) { - console.error("server main: api: guild poll events: error: ", e); + error("[guild poll events]", e); res.status(500).send({ error: true, message: "ERROR_POLL_FAILURE" }); } })); @@ -157,7 +159,7 @@ router.get("/events/poll", checkAuth(async (req, res) => { res.status(200).send({ error: false, event: e }) }); } catch(e) { - console.error("server main: api: guild poll events: error: ", e); + error("[guilds poll events]", e); res.status(500).send({ error: true, message: "ERROR_POLL_FAILURE" }); } }));