-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhandlers.py
124 lines (96 loc) · 3.41 KB
/
handlers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# coding:utf-8
import json
import time
import uuid
from tornado.web import RequestHandler, authenticated
from tornado.escape import to_basestring
from tornado.websocket import WebSocketHandler
class BaseHandler(RequestHandler):
@property
def redis(self):
return self.application.redis
def get_current_user(self):
return self.get_secure_cookie("user")
class IndexHandler(BaseHandler):
@authenticated
def get(self):
users = self.redis.smembers("users")
if self.current_user in users:
users.remove(self.current_user)
self.render("index.html", users=users)
class LoginHandler(BaseHandler):
def get(self):
self.render("login.html")
def post(self):
uid = self.get_argument("uid")
self.set_secure_cookie("user", uid, expires_days=None)
self.redis.sadd("users", uid)
self.redirect("/")
class ChatHandler(BaseHandler):
@authenticated
def get(self):
obj = {
'src': self.current_user,
'dst': self.get_argument('dst'),
'messages': []
}
self.render("chat.html", obj=obj)
class BaseSockHandler(WebSocketHandler):
@property
def redis(self):
return self.application.redis
def get_current_user(self):
return self.get_secure_cookie("user")
class MainSockHandler(BaseSockHandler):
main_pool = {}
def open(self):
print("User login with sock %s" % self.current_user)
keys = "message:*->%s" % self.current_user
for key in self.redis.keys(keys):
name = key.split("->")[0].split(":")[-1]
num = self.redis.zcard(key)
self.write_message(json.dumps({'name': name, 'num': num}))
MainSockHandler.main_pool[self.current_user] = self
def on_close(self):
del MainSockHandler.main_pool[self.current_user]
class PipHandler(BaseSockHandler):
user_pool = {}
def open(self):
dst = self.get_argument('dst')
self.tunnel = (self.current_user, dst)
print("User joined with tunnel %s->%s" % self.tunnel)
self.load_unread()
PipHandler.user_pool["%s->%s" % self.tunnel] = self
def load_unread(self):
key = "message:%s->%s" % self.tunnel[::-1]
for message in self.redis.zrange(key, 0, -1):
PipHandler.send(self, json.loads(message))
self.redis.zrem(key, message)
def on_message(self, message):
# Message construct
# {'src': 'david', 'dst': 'allen', 'body': 'hello world!'}
msg = json.loads(message)
dst = PipHandler.user_pool.get("%s->%s" % self.tunnel[::-1])
msg['id'] = str(uuid.uuid4())
PipHandler.send(self, msg)
if dst:
PipHandler.send(dst, msg)
else:
self.redis.zadd(
"message:%s->%s" % self.tunnel,
json.dumps(msg), time.time()
)
main_dst = MainSockHandler.main_pool.get(msg['dst'])
if main_dst:
main_dst.write_message(
json.dumps({'name': self.current_user, 'num': 1})
)
@staticmethod
def send(obj, msg):
msg["html"] = to_basestring(
obj.render_string("message.html", message=msg)
)
obj.write_message(msg)
def on_close(self):
del PipHandler.user_pool["%s->%s" % self.tunnel]
print("User quit with tunnel %s->%s" % self.tunnel)