#!/usr/bin/env node var fs=require("fs"), http=require("http"), WebSocketServer=require("ws").Server, CircularBuffer=require("circular-buffer"), Persist=require("node-persist"); var HTTPPORT=81,WSPORT=8000; ////////// WEBSOCKETS ////////// function uniqid(){ if(!uniqid.$)uniqid.$=1; return uniqid.$++; } function lobby_create(lname){ lobbies.push({id:uniqid(),name:lname,users:[],history:new CircularBuffer(10)}); } var __do_persist_users_timeout=null; function do_persist_users(){ if(__do_persist_users_timeout)return; __do_persist_users_timeout=setTimeout(function(){ __do_persist_users_timeout=null; Persist.setItem("users",users); },10*1000); } var __do_persist_lobbies_timeout=null; function do_persist_lobbies(){ if(__do_persist_lobbies_timeout)return; __do_persist_lobbies_timeout=setTimeout(function(){ __do_persist_lobbies_timeout=null; Persist.setItem("lobbies",lobbies); },10*1000); } Persist.initSync({}); users=Persist.getItemSync("users"); if(!users){ users=[]; } lobbies=Persist.getItemSync("lobbies"); if(!lobbies){ lobbies=[]; ["lobby_1","lobby_2"].forEach(lobby_create); } else { lobbies=lobbies.forEach(function(l){ l.history=new CircularBuffer(l.history); }); } new WebSocketServer({port:WSPORT}).on("connection",function(ws){ var uobj; (function(){ var nick="_user"+uniqid(); while(fnick(nick)!=-1)nick="_user"+uniqid(); uobj=new UserObject(nick,ws); })(); users.push(uobj); ws.send("#yournick "+uobj.nick); ws.on("message",function(msg,flags){ console.log("("+uobj.id+","+uobj.nick+"): "+msg); if(msg.match(/^#lobby /)){ var which=parseInt(msg.slice(7),10),lobidx=flob(which),oldlobidx; if(lobidx==-1){ ws.send("#error Invalid lobby"); return; } ws.send("#lobby "+which); if(uobj.lob!=null)leave_lobby(uobj); join_lobby(lobidx,uobj); send_history(lobidx,uobj); do_persist_lobbies(); } else if(msg.match(/^#mylobby/)){ if(uobj.lob==null)ws.send("#mylobby"); else ws.send("#mylobby "+uobj.lob); } else if(msg.match(/^#nick /)){ var choice=msg.slice(6).replace(/[\x00-\x20\x7F\x80-\xFF]/g,""); //all shitty characters including space (' ') var i; if(choice.length==0||choice.length>8){ ws.send("#error Invalid nick"); return; } if(uobj.lob!=null){ if(fnick(choice)!=-1){ i=1; while(fnick(choice+i)!=-1)i++; choice+=i; } lobbysend(lobbies[flob(uobj.lob)],"#nick "+uobj.nick+" "+choice); } uobj.nick=choice; do_persist_users(); do_persist_lobbies(); } else if(msg.match(/^#lobbylist/)){ ws.send("#lobbylist "+lobbies.map(function(lob){return lob.id+":"+lob.name;}).join(" ")); } else if(msg.match(/^#nicklist/)){ if(this.lob==null){ ws.send("#error Cannot request nicklist while not in a lobby"); return; } ws.send("#nicklist "+lobbies[flob(uobj.lob)].users.map(function(usr){ return users[fuser(usr)].nick; }).join(" ")); } else if(msg[0]==">"){ //message! var lobidx; if(uobj.lob==null){ ws.send("#error Cannot send message while not in a lobby"); return; } lobidx=flob(uobj.lob); lobbysend(lobbies[lobidx],"<"+uobj.nick+" "+msg.slice(1)); lobbies[lobidx].history.push([">",uobj.nick,msg.slice(1)]); do_persist_lobbies(); } else { ws.send("#error Invalid message starting with \""+msg.slice(0,10)+"\""); return; } }); ws.on("close",function(){ var lobidx; if(uobj.lob!=null){ lobidx=flob(uobj.lob); lobbysend(lobbies[lobidx],"#part "+uobj.nick,[uobj.id]); lobbies[lobidx].history.push(["part",uobj.nick]); lobbies[lobidx].users.splice(lobfuser(lobbies[lobidx],uobj.id),1); } users.splice(fuser(uobj.id),1); do_persist_users(); do_persist_lobbies(); }); }); console.log("Websocket server started on port "+WSPORT+"."); function UserObject(nick,ws){ if(!(this instanceof UserObject))return new UserObject(nick,ws); this.id=uniqid(); this.nick=nick; this.ws=ws; this.lob=null; } function lobbysend(lob,msg,exceptids){ var uidx; if(exceptids==undefined)exceptids=[]; for(var i=0;i