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,
const discordClient = new Discord.Client();
let discordChannel = null;
if (token.length > 0) {
- discordClient.login(token).then( () => {
+ 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"];
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);
- if (!!discordChannel && obj.code == "newchallenge") {
- discordChannel.send("New challenge: " +
- obj.data.vname +
- " [" + obj.data.cadence + "]" +
- " - https://vchess.club");
- }
break;
case "rnewgame":
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));
}