aboutsummaryrefslogtreecommitdiff
path: root/chatserver.js
diff options
context:
space:
mode:
Diffstat (limited to 'chatserver.js')
-rwxr-xr-xchatserver.js165
1 files changed, 165 insertions, 0 deletions
diff --git a/chatserver.js b/chatserver.js
new file mode 100755
index 0000000..0529630
--- /dev/null
+++ b/chatserver.js
@@ -0,0 +1,165 @@
+#!/usr/bin/env node
+var fs=require("fs"),
+ http=require("http"),
+ WebSocketServer=require("ws").Server,
+ CircularBuffer=require("circular-buffer");
+var HTTPPORT=81,WSPORT=8000;
+
+
+////////// WEBSOCKETS //////////
+
+function uniqid(){
+ if(!uniqid.$)uniqid.$=1;
+ return uniqid.$++;
+}
+
+var users=[];
+var lobbies=[];
+
+function lobby_create(lname){
+ lobbies.push({id:uniqid(),name:lname,users:[],history:new CircularBuffer(10)});
+}
+
+["a_lobby","lobby_2"].forEach(lobby_create);
+
+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){
+ oldlobidx=flob(uobj.lob);
+ lobbies[oldlobidx].users.splice(lobfuser(lobbies[oldlobidx],uobj.id),1);
+ lobbysend(lobbies[oldlobidx],"#part "+uobj.nick);
+ lobbies[oldlobidx].history.push(["part",uobj.nick]);
+ }
+ uobj.lob=which;
+ lobbies[lobidx].users.push(uobj.id);
+ lobbysend(lobbies[lobidx],"#join "+uobj.nick);
+ lobbies[lobidx].history.push(["join",uobj.nick]);
+ uobj.ws.send("#historystart");
+ lobbies[lobidx].history.toarray().forEach(function(h){
+ uobj.ws.send("#history "+h.join(" "));
+ });
+ uobj.ws.send("#historyend");
+ } 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){
+ 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;
+ } 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)]);
+ } 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);
+ });
+});
+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<lob.users.length;i++){
+ if(exceptids.indexOf(lob.users[i])==-1){
+ uidx=fuser(lob.users[i]);
+ users[uidx].ws.send(msg);
+ }
+ }
+}
+
+function lobfuser(lob,id){
+ for(var i=0;i<lob.users.length;i++)if(users[fuser(lob.users[i])].id==id)return i;
+ return -1;
+}
+
+function fuser(id){
+ for(var i=0;i<users.length;i++)if(users[i].id==id)return i;
+ return -1;
+}
+function fnick(nick){
+ for(var i=0;i<users.length;i++)if(users[i].nick==nick)return i;
+ return -1;
+}
+
+function flob(lobid){
+ for(var i=0;i<lobbies.length;i++)if(lobbies[i].id==lobid)return i;
+ return -1;
+}
+
+
+////////// HTTP //////////
+
+var pagehtml;
+try{
+ pagehtml=fs.readFileSync("chatserver.html").toString();
+} catch(e){
+ console.log("Could not read file 'chatserver.html'.");
+ console.log(e);
+ process.exit();
+}
+
+http.createServer(function(req,res){
+ res.writeHead(200,{"Content-Type":"text/html"});
+ res.end(pagehtml);
+}).listen(HTTPPORT);
+console.log("HTTP server started on port "+HTTPPORT+".");