Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from tornado import websocket, web, ioloop
- from tornado.ioloop import PeriodicCallback
- import json
- import time
- import re
- import gc
- import sys
- INTRO_FILE = "intro.txt"
- PING_INTERVAL = 10.0
- default_room = "#default"
- rooms = {}
- bannedip = {}
- nicknames ={}
- clients = {}
- bots = {}
- def print_stat():
- for room in rooms:
- print "ROOM:",rooms[room].name,rooms[room].users
- def process_message(user,msg): #xss protecton
- if "script" in msg.lower() and "<" in msg and ">" in msg:
- MainServer.raw_to_user(user,"WARNING:XSS not allowed!")
- msg = msg.replace("<","<")
- msg = msg.replace(">",">")
- return msg
- class Room:
- #Test for name integrity and create empty room
- def __init__(self,name):
- if re.match("^#[A-Za-z0-9_-]+$",name):
- self.name = name
- self.users = {}
- print "Room %s is beeing made!"%name
- else:
- raise ValueError("The room name is not correctly formatted!")
- def join_room(self,user):
- if user.ron == True and user.nickname not in self.users :
- MainServer.raw_to_user(user,"JOINED:%s"%self.name)
- user.raw_message("%s:USERS:%s"%(self.name,json.dumps([u.nickname for u in self.users.values()])))
- self.users[user.nickname] = user
- for key in self.users: #let everyone in room know
- self.users[key].raw_message("%s:ADDUSR:%s"%(self.name,user.nickname))
- return True
- else:
- user.raw_message("WARNING:Already in a room")
- return False
- def leave_room(self,user,socket_closed=False):
- if user.nickname in self.users:
- if not socket_closed:
- MainServer.raw_to_user(user,"LEFT:%s"%self.name)
- del self.users[user.nickname]
- for i in self.users:
- self.users[i].raw_message("%s:REMUSR:%s"%(self.name,user.nickname))
- return True
- else:
- if not socket_closed:
- user.raw_message("WARNING:Not in room.." )
- return False
- #Send all users message from one of them.
- def user_message(self,user,msg):
- for client in self.users:
- self.users[client].raw_message("%s:MSG:<n> %s </n> : <msg> %s </msg>"%(self.name,user.nickname,msg))
- #Send all users message as is (ussualy used by server routines)
- def raw_message(self,msg):
- for client in self.users:
- self.users[client].raw_message(msg)
- class NickServ:
- return_info = {
- "nickname_changed":"NICKSERV:STAT:NICK_CHANGED:%s:%s",
- "nickname_exists":["NICKSERV:STAT:NICK_EXISTS:%s","WARNING:Nickname %s vec postoji"],
- "formatting_error":"WARNING:Nickname ne moze biti tako formatiran"
- }
- @staticmethod
- def nick_change(user,new_nick):
- global clients
- old_nick = user.nickname.lower()
- if not new_nick.lower() in nicknames and re.match("^[A-Za-z0-9_-]+$",new_nick):
- NickServ.nick_unset(old_nick)
- user.nickname=new_nick
- NickServ.nick_set(new_nick,user)
- if user.ron:
- MainServer.broadcast_raw_message(clients.values(),NickServ.return_info["nickname_changed"]%(old_nick,new_nick))
- return True
- else:
- if new_nick.lower() in nicknames:
- MainServer.raw_to_user(user,NickServ.return_info["nickname_exists"][0]%new_nick)
- else:
- MainServer.raw_to_user(user,NickServ.return_info["formatting_error"])
- return False
- @staticmethod
- def nick_unset(nick):
- nick = nick.lower().strip()
- if nick in nicknames:
- del nicknames[nick]
- @staticmethod
- def nick_set(nick,user):
- nicknames[nick.lower().strip()] = user
- class RoomServ:
- name = "ROOM_SERV"
- @staticmethod
- def join_user(user,room_name):
- global rooms
- room = None
- if room_name not in rooms:
- try:
- room = Room(room_name)
- rooms[room_name] = room
- except ValueError , e:
- MainServer.raw_to_user(user,"WARNING:%s"%str(e))
- return
- else:
- room = rooms[room_name]
- user.rooms.append(room)
- room.join_room(user)
- #Check for room exsistance before leaving it
- @staticmethod
- def leave_user(user,room_name,closed):
- if room_name in rooms:
- rooms[room_name].leave_room(user,closed)
- else:
- MainServer.raw_to_user(user,"WARNING:Ta soba ne postoji..")
- class UserServ:
- #Remove user from chat and do the cleanup
- @staticmethod
- def disconnected(socket):
- print "DISCONNECTED CALLED"
- if socket in clients:
- user = clients[socket]
- print "Client %s removed."%(user.nickname)
- user.leaveAllRooms()
- NickServ.nick_unset(user.nickname)
- print "NICKNAMES : "+str(nicknames)+"\n"
- del clients[socket]
- print "REFERENCES : %s \n"%gc.get_referrers(user)
- print "CLIENTS : %s \n"%clients
- #else:
- # print "Socket refferers:%s"%gc.get_referrers(socket)
- print_stat()
- class MainServer:
- @staticmethod
- def raw_to_user(user,msg):
- user.raw_message(msg)
- @staticmethod
- def broadcast_raw_message(client_list,msg):
- for client in client_list:
- if client.ron:
- client.raw_message(msg)
- #Send intro file to client
- @staticmethod
- def intro(user,file):
- with open(file) as f:
- for line in f:
- user.raw_message("MSG:%s"%line)
- @staticmethod
- def register_user(user,nickname):
- if NickServ.nick_change(user,nickname):
- user.raw_message("R_O_N:%s"%user.nickname)
- MainServer.intro(user,INTRO_FILE)
- user.ron = True
- #print "User joined chat with nickname : %s and ip : %s"%(self.nickname,self.ip)
- RoomServ.join_user(user,default_room)
- class User:
- nickname = ""
- rooms = []
- socket = None
- ron = False
- ip = ""
- timeout = 0
- callback = None
- def __init__(self,socket):
- self.socket = socket
- self.ip = str(socket.request.remote_ip)
- def leaveAllRooms(self):
- for room in list(self.rooms):
- if room.leave_room(self,True) == False:
- break
- else:
- self.rooms.remove(room)
- else:
- print "We're stuck.."
- def raw_message(self,msg):
- try:
- self.socket.write_message(msg)
- except:
- print "Connection lost %s"%self.nickname
- UserServ.disconnected(self.socket)
- print "OBJECT : "%self
- def destroy_client(self, code,reason):
- self.socket.close(code,reason)
- '''
- If client is not registered message in form
- "nick:user_nickname" must be recived to initialize
- chat, othrewise parse the message in form
- "msg: " + additional params splitted with :
- "command: " + -||-
- '''
- def message_recived(self,msg):
- #parse and route messages
- msg = process_message(self,msg)
- print "%s : %s"%(self.nickname,msg)
- if not self.ron:
- nickname_info = msg.split(":")
- if nickname_info[0].strip().lower() == "nick":
- nickname = nickname_info[1]
- MainServer.register_user(self,nickname)
- else:
- self.destroy_client(1008,"First 'nick:your_nickname' command must be sent.")
- else:
- msg_info = msg.split(":",1)
- if msg_info[0].lower() == "msg":
- msg_info = msg_info[1].split(":",1)
- if len(msg_info) == 2:
- msg = msg_info[1].strip()
- if msg_info[0].strip().startswith("#"):
- room = msg_info[0].strip()
- if room in rooms.keys():
- rooms[room].user_message(self,msg)
- else:
- receiver = msg_info[0].strip().lower()
- if receiver in nicknames:
- nicknames[receiver].user_message(self,msg)
- if msg_info[0].lower() == "command":
- msg_info = msg_info[1].split(" ")
- if len(msg_info)>1:
- if msg_info[0].lower() == "nick":
- NickServ.nick_change(self,msg_info[1])
- elif msg_info[0].lower() == "join":
- room_name = msg_info[1].lower()
- RoomServ.join_user(self,room_name)
- elif msg_info[0].lower() == "leave":
- room_name = msg_info[1].lower()
- RoomServ.leave_user(self,room_name,False)
- else:
- pass
- elif len(msg_info)==1:
- MainServer.raw_to_user(self,"WARNING:Not yet implemented...")
- def user_message(self,user,message):
- self.raw_message("USER:%s:MSG:%s"%(user.nickname,message))
- def __del__(self):
- print "Deleted user %s"%self.nickname
- class SocketHandler(websocket.WebSocketHandler):
- def check_origin(self, origin):
- return True
- def open(self):
- self.set_nodelay(True)
- if not self in clients:
- clients[self] = User(self)
- #clients[self].callback = PeriodicCallback(clients[self].keepalive,1000);
- #clients[self].callback.start()
- else:
- print "You're here..."
- def on_close(self):
- if self:
- UserServ.disconnected(self)
- print "Client list after close event %s"%clients.keys()
- def on_message(self,message):
- if self in clients:
- clients[self].message_recived(message.encode("utf-8"))
- app = web.Application([
- (r'/', SocketHandler),
- ])
- rooms[default_room] = Room(default_room)
- if __name__ == '__main__':
- app.listen(5000)
- ioloop.IOLoop.instance().start()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement