'update'
[vchess.git] / server / sockets.js
index 3a776d1..520b8b7 100644 (file)
@@ -1,7 +1,7 @@
-const url = require('url');
+const Discord = require('discord.js');
+const { token, channel } = require('./config/discord.json');
 
 // Node version in Ubuntu 16.04 does not know about URL class
-// NOTE: url is already transformed, without ?xxx=yyy... parts
 function getJsonFromUrl(url) {
   const query = url.substr(2); //starts with "/?"
   let result = {};
@@ -18,6 +18,12 @@ function send(socket, message) {
     socket.send(JSON.stringify(message));
 }
 
+// https://www.npmjs.com/package/ws - detect lost connections...
+function noop() {}
+function heartbeat() {
+  this.isAlive = true;
+}
+
 module.exports = function(wss) {
   // Associative array page --> sid --> tmpId --> socket
   // "page" is either "/" for hall or "/game/some_gid" for Game,
@@ -27,7 +33,17 @@ module.exports = function(wss) {
   // NOTE: only purpose of sidToPages = know when to delete keys in idToSid
   let sidToPages = {};
   let idToSid = {};
+  const discordClient = new Discord.Client();
+  let discordChannel = null;
+  if (token.length > 0) {
+    discordClient.login(token);
+    discordClient.once("ready", () => {
+      discordChannel = discordClient.channels.cache.get(channel);
+    });
+  }
   wss.on("connection", (socket, req) => {
+    socket.isAlive = true;
+    socket.on('pong', heartbeat);
     const query = getJsonFromUrl(req.url);
     const sid = query["sid"];
     const id = query["id"];
@@ -210,6 +226,21 @@ module.exports = function(wss) {
         case "rematchoffer":
         case "draw":
           // "newgame" message can provide a page (corr Game --> Hall)
+          if (obj.code == "newchallenge") {
+            // Filter out targeted challenges and correspondance games:
+            if (!obj.data.to && obj.data.cadence.indexOf('d') < 0) {
+              const challMsg = (
+                (obj.data.sender || "@nonymous") + " : " +
+                "**" + obj.data.vname + "** " +
+                "[" + obj.data.cadence + "] "
+              );
+              if (!!discordChannel) discordChannel.send(challMsg);
+              else
+                // Log when running locally (dev, debug):
+                console.log(challMsg);
+            }
+            delete obj.data["sender"];
+          }
           notifyRoom(
             obj.page || page, obj.code, {data: obj.data}, obj.excluded);
           break;
@@ -345,4 +376,15 @@ module.exports = function(wss) {
     socket.on("message", messageListener);
     socket.on("close", closeListener);
   });
+  const interval = setInterval(
+    () => {
+      wss.clients.forEach(ws => {
+        if (ws.isAlive === false) return ws.terminate();
+        ws.isAlive = false;
+        ws.ping(noop);
+      });
+    },
+    30000
+  );
+  wss.on('close', () => clearInterval(interval));
 }