ソースを参照

Added/fixed Discord module, added module start logging

Kristian Vos 5 年 前
コミット
7e31203287
4 ファイル変更148 行追加48 行削除
  1. 31 48
      backend/index.js
  2. 84 0
      backend/logic/discord.js
  3. 32 0
      backend/package-lock.json
  4. 1 0
      backend/package.json

+ 31 - 48
backend/index.js

@@ -17,6 +17,7 @@ const stations = require('./logic/stations');
 const songs = require('./logic/songs');
 const playlists = require('./logic/playlists');
 const cache = require('./logic/cache');
+const discord = require('./logic/discord');
 const notifications = require('./logic/notifications');
 const punishments = require('./logic/punishments');
 const logger = require('./logic/logger');
@@ -42,51 +43,6 @@ const getError = (err) => {
 	return error;
 };
 
-/*client.on('ready', () => {
-	discordClientCBS.forEach((cb) => {
-		cb();
-	});
-	discordClientCBS = [];
-	console.log(`Logged in to Discord as ${client.user.username}#${client.user.discriminator}`);
-});
-
-client.on('disconnect', (err) => {
-	console.log(`Discord disconnected. Code: ${err.code}.`);
-});
-
-client.login(config.get('apis.discord.token'));
-
-let discordClientCBS = [];
-const getDiscordClient = (cb) => {
-	if (client.status === 0) return cb();
-	else discordClientCBS.push(cb);
-};
-
-const logToDiscord = (message, color, type, critical, extraFields, cb = ()=>{}) => {
-	getDiscordClient(() => {
-		let richEmbed = new Discord.RichEmbed();
-		richEmbed.setAuthor("Musare Logger", config.get("domain")+"/favicon-194x194.png", config.get("domain"));
-		richEmbed.setColor(color);
-		richEmbed.setDescription(message);
-		//richEmbed.setFooter("Footer", "https://musare.com/favicon-194x194.png");
-		//richEmbed.setImage("https://musare.com/favicon-194x194.png");
-		//richEmbed.setThumbnail("https://musare.com/favicon-194x194.png");
-		richEmbed.setTimestamp(new Date());
-		richEmbed.setTitle("MUSARE ALERT");
-		richEmbed.setURL(config.get("domain"));
-		richEmbed.addField("Type:", type, true);
-		richEmbed.addField("Critical:", (critical) ? 'True' : 'False', true);
-		extraFields.forEach((extraField) => {
-			richEmbed.addField(extraField.name, extraField.value, extraField.inline);
-		});
-		client.channels.get(config.get('apis.discord.loggingChannel')).sendEmbed(richEmbed).then(() => {
-			cb();
-		}).then((reason) => {
-			cb(reason);
-		});
-	});
-};*/
-
 function lockdown() {
 	if (lockdownB) return;
 	lockdownB = true;
@@ -99,14 +55,28 @@ function lockdown() {
 function errorCb(message, err, component) {
 	err = getError(err);
 	lockdown();
-	//logToDiscord(message, "#FF0000", message, true, [{name: "Error:", value: err, inline: false}, {name: "Component:", value: component, inline: true}]);
+	discord.sendAdminAlertMessage(message, "#FF0000", message, true, [{name: "Error:", value: err, inline: false}, {name: "Component:", value: component, inline: true}]); //TODO Maybe due to lockdown this won't work, and what if the Discord module was the one that failed?
+}
+
+function moduleStartFunction() {
+	logger.info("MODULE_START", `Starting to initialize component '${currentComponent}'`);
 }
 
 async.waterfall([
 
+	// setup our Discord module
+	(next) => {
+		currentComponent = 'Discord';
+		moduleStartFunction();
+		discord.init(config.get('apis.discord').token, config.get('apis.discord').loggingChannel, errorCb, () => {
+			next();
+		});
+	},
+
 	// setup our Redis cache
 	(next) => {
 		currentComponent = 'Cache';
+		moduleStartFunction();
 		cache.init(config.get('redis').url, config.get('redis').password, errorCb, () => {
 			next();
 		});
@@ -116,6 +86,7 @@ async.waterfall([
 	(next) => {
 		initializedComponents.push(cache);
 		currentComponent = 'DB';
+		moduleStartFunction();
 		db.init(config.get("mongo").url, errorCb, next);
 	},
 
@@ -123,6 +94,7 @@ async.waterfall([
 	(next) => {
 		initializedComponents.push(db);
 		currentComponent = 'App';
+		moduleStartFunction();
 		app.init(next);
 	},
 
@@ -130,6 +102,7 @@ async.waterfall([
 	(next) => {
 		initializedComponents.push(app);
 		currentComponent = 'Mail';
+		moduleStartFunction();
 		mail.init(next);
 	},
 
@@ -137,6 +110,7 @@ async.waterfall([
 	(next) => {
 		initializedComponents.push(mail);
 		currentComponent = 'IO';
+		moduleStartFunction();
 		io.init(next);
 	},
 
@@ -144,6 +118,7 @@ async.waterfall([
 	(next) => {
 		initializedComponents.push(io);
 		currentComponent = 'Punishments';
+		moduleStartFunction();
 		punishments.init(next);
 	},
 
@@ -151,6 +126,7 @@ async.waterfall([
 	(next) => {
 		initializedComponents.push(punishments);
 		currentComponent = 'Notifications';
+		moduleStartFunction();
 		notifications.init(config.get('redis').url, config.get('redis').password, errorCb, next);
 	},
 
@@ -158,6 +134,7 @@ async.waterfall([
 	(next) => {
 		initializedComponents.push(notifications);
 		currentComponent = 'Stations';
+		moduleStartFunction();
 		stations.init(next)
 	},
 
@@ -165,6 +142,7 @@ async.waterfall([
 	(next) => {
 		initializedComponents.push(stations);
 		currentComponent = 'Songs';
+		moduleStartFunction();
 		songs.init(next)
 	},
 
@@ -172,6 +150,7 @@ async.waterfall([
 	(next) => {
 		initializedComponents.push(songs);
 		currentComponent = 'Playlists';
+		moduleStartFunction();
 		playlists.init(next)
 	},
 
@@ -179,6 +158,7 @@ async.waterfall([
 	(next) => {
 		initializedComponents.push(playlists);
 		currentComponent = 'API';
+		moduleStartFunction();
 		api.init(next)
 	},
 
@@ -186,6 +166,7 @@ async.waterfall([
 	(next) => {
 		initializedComponents.push(api);
 		currentComponent = 'Logger';
+		moduleStartFunction();
 		logger.init(next)
 	},
 
@@ -193,6 +174,7 @@ async.waterfall([
 	(next) => {
 		initializedComponents.push(logger);
 		currentComponent = 'Tasks';
+		moduleStartFunction();
 		tasks.init(next)
 	},
 
@@ -200,6 +182,7 @@ async.waterfall([
 	(next) => {
 		initializedComponents.push(tasks);
 		currentComponent = 'Windows';
+		moduleStartFunction();
 		if (!config.get("isDocker")) {
 			const express = require('express');
 			const app = express();
@@ -223,10 +206,10 @@ async.waterfall([
 ], (err) => {
 	if (err && err !== true) {
 		lockdown();
-		//logToDiscord("An error occurred while initializing the backend server.", "#FF0000", "Startup error", true, [{name: "Error:", value: err, inline: false}, {name: "Component:", value: currentComponent, inline: true}]);
+		discord.sendAdminAlertMessage("An error occurred while initializing the backend server.", "#FF0000", "Startup error", true, [{name: "Error:", value: err, inline: false}, {name: "Component:", value: currentComponent, inline: true}]);
 		console.error('An error occurred while initializing the backend server');
 	} else {
-		//logToDiscord("The backend server started successfully.", "#00AA00", "Startup", false, []);
+		discord.sendAdminAlertMessage("The backend server started successfully.", "#00AA00", "Startup", false, []);
 		console.info('Backend server has been successfully started');
 	}
 });

+ 84 - 0
backend/logic/discord.js

@@ -0,0 +1,84 @@
+let lockdown = false;
+
+const Discord = require('discord.js');
+const logger = require('./logger');
+const config = require('config');
+
+const client = new Discord.Client();
+
+let messagesToSend = [];
+
+let connected = false;
+
+// TODO Maybe we need to only finish init when ready is called, or maybe we don't wait for it
+module.exports = {
+    adminAlertChannelId: "",
+
+	init: (discordToken, adminAlertChannelId, errorCb, cb) => {
+        this.adminAlertChannelId = adminAlertChannelId;
+
+        client.on('ready', () => {
+            logger.info("DISCORD_READY", `Logged in as ${client.user.tag}!`);
+            connected = true;
+            messagesToSend.forEach((message) => {
+                this.sendAdminAlertMessage(message);
+            });
+            messagesToSend = [];
+        });
+
+        client.on('invalidated', () => {
+            logger.info("DISCORD_INVALIDATED", `Discord client was invalidated.`);
+            connected = false;
+        });
+
+        client.on('disconnected', () => {
+            logger.info("DISCORD_DISCONNECTED", `Discord client was disconnected.`);
+            connected = false;
+        });
+
+        client.on('error', (err) => {
+            logger.info("DISCORD_ERROR", `Discord client encountered an error: ${err.message}.`);
+        });
+
+        client.login(discordToken);
+
+		if (lockdown) return this._lockdown();
+		cb();
+    },
+    
+    sendAdminAlertMessage: (message, color, type, critical, extraFields) => {
+        if (!connected) return messagesToSend.push(message);
+        else {
+            let channel = client.channels.find("id", this.adminAlertChannelId);
+            if (channel !== null) {
+
+                let richEmbed = new Discord.RichEmbed();
+                richEmbed.setAuthor("Musare Logger", config.get("domain")+"/favicon-194x194.png", config.get("domain"));
+                richEmbed.setColor(color);
+                richEmbed.setDescription(message);
+                //richEmbed.setFooter("Footer", "https://musare.com/favicon-194x194.png");
+                //richEmbed.setImage("https://musare.com/favicon-194x194.png");
+                //richEmbed.setThumbnail("https://musare.com/favicon-194x194.png");
+                richEmbed.setTimestamp(new Date());
+                richEmbed.setTitle("MUSARE ALERT");
+                richEmbed.setURL(config.get("domain"));
+                richEmbed.addField("Type:", type, true);
+                richEmbed.addField("Critical:", (critical) ? 'True' : 'False', true);
+                extraFields.forEach((extraField) => {
+                    richEmbed.addField(extraField.name, extraField.value, extraField.inline);
+                });
+
+
+                channel.send(message, { embed: richEmbed })                     
+                .then(message => logger.success("SEND_ADMIN_ALERT_MESSAGE", `Sent admin alert message: ${message}`))
+                .catch(() => logger.error("SEND_ADMIN_ALERT_MESSAGE", "Couldn't send admin alert message"));
+            } else {
+                logger.error("SEND_ADMIN_ALERT_MESSAGE", "Couldn't send admin alert message, channel was not found.");
+            }
+        }
+    },
+
+	_lockdown: () => {
+		lockdown = true;
+	}
+}

+ 32 - 0
backend/package-lock.json

@@ -413,6 +413,18 @@
       "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
       "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
     },
+    "discord.js": {
+      "version": "11.5.1",
+      "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-11.5.1.tgz",
+      "integrity": "sha512-tGhV5xaZXE3Z+4uXJb3hYM6gQ1NmnSxp9PClcsSAYFVRzH6AJH74040mO3afPDMWEAlj8XsoPXXTJHTxesqcGw==",
+      "requires": {
+        "long": "^4.0.0",
+        "prism-media": "^0.0.3",
+        "snekfetch": "^3.6.4",
+        "tweetnacl": "^1.0.0",
+        "ws": "^6.0.0"
+      }
+    },
     "double-ended-queue": {
       "version": "2.1.0-0",
       "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz",
@@ -1037,6 +1049,11 @@
       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz",
       "integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw=="
     },
+    "long": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
+      "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
+    },
     "lru-cache": {
       "version": "4.1.5",
       "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
@@ -1540,6 +1557,11 @@
       "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
       "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ="
     },
+    "prism-media": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-0.0.3.tgz",
+      "integrity": "sha512-c9KkNifSMU/iXT8FFTaBwBMr+rdVcN+H/uNv1o+CuFeTThNZNTOrQ+RgXA1yL/DeLk098duAeRPP3QNPNbhxYQ=="
+    },
     "process-nextick-args": {
       "version": "1.0.7",
       "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
@@ -1855,6 +1877,11 @@
       "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz",
       "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw=="
     },
+    "snekfetch": {
+      "version": "3.6.4",
+      "resolved": "https://registry.npmjs.org/snekfetch/-/snekfetch-3.6.4.tgz",
+      "integrity": "sha512-NjxjITIj04Ffqid5lqr7XdgwM7X61c/Dns073Ly170bPQHLm6jkmelye/eglS++1nfTWktpP6Y2bFXjdPlQqdw=="
+    },
     "socket.io": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.2.0.tgz",
@@ -2104,6 +2131,11 @@
         "safe-buffer": "^5.0.1"
       }
     },
+    "tweetnacl": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.1.tgz",
+      "integrity": "sha512-kcoMoKTPYnoeS50tzoqjPY3Uv9axeuuFAZY9M/9zFnhoVvRfxz9K29IMPD7jGmt2c8SW7i3gT9WqDl2+nV7p4A=="
+    },
     "type-check": {
       "version": "0.3.2",
       "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",

+ 1 - 0
backend/package.json

@@ -17,6 +17,7 @@
     "config": "^3.2.0",
     "cookie-parser": "^1.4.4",
     "cors": "^2.8.5",
+    "discord.js": "^11.5.1",
     "express": "^4.17.1",
     "mailgun-js": "^0.22.0",
     "moment": "^2.24.0",