]> jfr.im git - irc/quakenet/qwebirc.git/blame - qwebirc/ajaxengine.py
Fix part bug (thanks shadow).
[irc/quakenet/qwebirc.git] / qwebirc / ajaxengine.py
CommitLineData
9e769c12
CP
1from twisted.web import resource, server, static
2from twisted.names import client
3from twisted.internet import reactor
4import simplejson, md5, sys, os, ircclient, time, config
5
6Sessions = {}
7
8def get_session_id():
9 return md5.md5(os.urandom(16)).hexdigest()
10
11def jsondump(fn):
12 def decorator(*args, **kwargs):
13 x = fn(*args, **kwargs)
14 if isinstance(x, list):
15 return simplejson.dumps(x)
16 return x
17 return decorator
18
19class IRCSession:
20 def __init__(self, id):
21 self.id = id
22 self.subscriptions = []
23 self.buffer = []
24 self.throttle = 0
25 self.schedule = None
26
27 def subscribe(self, channel):
28 self.subscriptions.append(channel)
29 self.flush()
30
31 def flush(self, scheduled=False):
32 if scheduled:
33 self.schedule = None
34
35 if not self.buffer or not self.subscriptions:
36 return
37
38 t = time.time()
39
40 if t < self.throttle:
41 if not self.schedule:
42 self.schedule = reactor.callLater(self.throttle - t, self.flush, True)
43 return
44 else:
45 # process the rest of the packet
46 if not scheduled:
47 if not self.schedule:
48 self.schedule = reactor.callLater(0, self.flush, True)
49 return
50
51 self.throttle = t + config.UPDATE_FREQ
52
53 encdata = simplejson.dumps(self.buffer)
54 self.buffer = []
55
56 newsubs = []
57 for x in self.subscriptions:
58 if x.write(encdata):
59 newsubs.append(x)
60
61 self.subscriptions = newsubs
62
63 def event(self, data):
64 self.buffer.append(data)
65 self.flush()
66
67 def push(self, data):
68 self.client.write(data)
69
70class Channel:
71 def __init__(self, request):
72 self.request = request
73
74class SingleUseChannel(Channel):
75 def write(self, data):
76 self.request.write(data)
77 self.request.finish()
78 return False
79
80class MultipleUseChannel(Channel):
81 def write(self, data):
82 self.request.write(data)
83 return True
84
85class AJAXEngine(resource.Resource):
86 isLeaf = True
87
88 def __init__(self, prefix):
89 self.prefix = prefix
90
91 @jsondump
92 def render_GET(self, request):
93 path = request.path[len(self.prefix):]
94 if path == "/n":
95 ip = request.transport.getPeer()
96 ip = ip[1]
97
98 nick, ident = request.args.get("nick"), "webchat"
99 if not nick:
100 return [False, "Nickname not supplied"]
101
102 nick = nick[0]
103
104 id = get_session_id()
105
106 session = IRCSession(id)
107
108 client = ircclient.createIRC(session, nick=nick, ident=ident, ip=ip, realname=nick)
109 session.client = client
110
111 Sessions[id] = session
112
113 return [True, id]
114
115 if path.startswith("/s/"):
116 sessionid = path[3:]
117 session = Sessions.get(sessionid)
118
119 if not session:
120 return [False, "Bad session ID"]
121
122 session.subscribe(SingleUseChannel(request))
123 return server.NOT_DONE_YET
124 if path.startswith("/p/"):
125 command = request.args.get("c")
126 if not command:
127 return [False, "No command specified"]
128
129 command = command[0]
130
131 sessionid = path[3:]
132 session = Sessions.get(sessionid)
133 if not session:
134 return [False, "Bad session ID"]
135
136 try:
137 decoded = command.decode("utf-8")
138 except UnicodeDecodeError:
139 decoded = command.decode("iso-8859-1", "ignore")
140 session.push(decoded)
141 return [True]
142
143 return [False, "404"]
144