piano/server.js

79 lines
2.4 KiB
JavaScript

var express = require("express");
var qs = require("qs");
var proxyaddr = require("proxy-addr");
var {WebSocketServer} = require("ws");
var app = express();
app.set("trust proxy", "loopback");
app.use(express.static("frontend"));
var server = app.listen(process.env.PORT || 924, process.env.ADDRESS);
var wss = new WebSocketServer({server, clientTracking: true});
var chatlog = [];
wss.on("connection", (ws, req) => {
req.ip = proxyaddr(req, app.get("trust proxy"));
req.query = qs.parse(req.url.substr(req.url.indexOf('?')+1));
function broadcast(msg, excludeSelf) {
if (typeof msg == "object" && !(msg instanceof Buffer)) msg = JSON.stringify(msg);
for (let ows of wss.clients) if (!(ows == ws && excludeSelf)) ows.send(msg);
}
function broadcastChat(message) {
broadcast({type: "chat", message});
chatlog.push(message);
if (chatlog.length >= 100) chatlog.shift();
}
ws.user = {
uid: req.ip,
nick: req.query.nick || req.ip,
color: [Math.floor(Math.random()*256),Math.floor(Math.random()*256),Math.floor(Math.random()*256)]
}
let t = Array.from(wss.clients).map(ws => ws.user.id);
for (let i = 0; i < 256; i++) if (!t.includes(i)) { ws.user.id = i; break; }
if (ws.user.id == null) return ws.close();
console.log("join", ws.user);
ws.send(JSON.stringify({
type: "load",
id: ws.user.id,
uid: ws.user.uid,
users: Array.from(wss.clients).map(x => x.user),
chatlog
}));
broadcast({type: "join", id: ws.user.id, uid: ws.user.uid, nick: ws.user.nick, color: ws.user.color}, true);
broadcastChat({type: "join", id: ws.user.id, uid: ws.user.uid, nick: ws.user.nick});
ws.on("close", () => {
console.log("leave", ws.user);
broadcast({type: "leave", id: ws.user.id, uid: ws.user.uid, nick: ws.user.nick, color: ws.user.color}, true);
broadcastChat({type: "leave", id: ws.user.id, uid: ws.user.uid, nick: ws.user.nick})
});
ws.on("message", (msg, isBinary) => {
if (isBinary) {
broadcast(Buffer.concat([msg, Buffer.from([ws.user.id])]), true);
} else {
msg = msg.toString();
try {
msg = JSON.parse(msg);
} catch (error) { return }
console.log(msg);
switch (msg.type) {
case "chat":
broadcastChat({type: "message", content: msg.message, user: ws.user});
break;
case "nick":
ws.user.nick = msg.nick;
broadcast({type: "nick", nick: ws.user.nick, id: ws.user.id, uid: ws.user.uid});
broadcastChat({type: "nick", nick: ws.user.nick, id: ws.user.id});
break;
}
}
});
});