]>
jfr.im git - irc/quakenet/qwebirc.git/blob - qwebirc/ajaxengine.py
1 from twisted
.web
import resource
, server
, static
2 from twisted
.names
import client
3 from twisted
.internet
import reactor
5 import simplejson
, md5
, sys
, os
, ircclient
, time
, config
, weakref
10 return md5
.md5(os
.urandom(16)).hexdigest()[:10]
12 class BufferOverflowException(Exception):
15 class IDGenerationException(Exception):
19 def decorator(*args
, **kwargs
):
20 x
= fn(*args
, **kwargs
)
21 if isinstance(x
, list):
22 return simplejson
.dumps(x
)
26 def cleanupSession(id):
33 def __init__(self
, id):
35 self
.subscriptions
= []
40 self
.cleanupschedule
= None
42 def subscribe(self
, channel
):
43 if len(self
.subscriptions
) >= config
.MAXSUBSCRIPTIONS
:
44 self
.subscriptions
.pop(0)
46 self
.subscriptions
.append(channel
)
49 def flush(self
, scheduled
=False):
53 if not self
.buffer or not self
.subscriptions
:
60 self
.schedule
= reactor
.callLater(self
.throttle
- t
, self
.flush
, True)
63 # process the rest of the packet
66 self
.schedule
= reactor
.callLater(0, self
.flush
, True)
69 self
.throttle
= t
+ config
.UPDATE_FREQ
71 encdata
= simplejson
.dumps(self
.buffer)
75 for x
in self
.subscriptions
:
79 self
.subscriptions
= newsubs
80 if self
.closed
and not self
.subscriptions
:
81 cleanupSession(self
.id)
83 def event(self
, data
):
84 bufferlen
= sum(map(len, self
.buffer))
85 if bufferlen
+ len(data
) > config
.MAXBUFLEN
:
87 self
.client
.error("Buffer overflow")
90 self
.buffer.append(data
)
95 self
.client
.write(data
)
98 # keep the session hanging around for a few seconds so the
99 # client has a chance to see what the issue was
102 reactor
.callLater(5, cleanupSession
, self
.id)
105 def __init__(self
, request
):
106 self
.request
= request
108 class SingleUseChannel(Channel
):
109 def write(self
, data
):
110 self
.request
.write(data
)
111 self
.request
.finish()
114 class MultipleUseChannel(Channel
):
115 def write(self
, data
):
116 self
.request
.write(data
)
119 class AJAXEngine(resource
.Resource
):
122 def __init__(self
, prefix
):
126 def render_POST(self
, request
):
127 path
= request
.path
[len(self
.prefix
):]
129 ip
= request
.transport
.getPeer()
132 nick
, ident
= request
.args
.get("nick"), "webchat"
134 return [False, "Nickname not supplied"]
139 id = get_session_id()
140 if not Sessions
.get(id):
143 raise IDGenerationException()
145 session
= IRCSession(id)
147 client
= ircclient
.createIRC(session
, nick
=nick
, ident
=ident
, ip
=ip
, realname
=config
.REALNAME
)
148 session
.client
= client
150 Sessions
[id] = session
153 return [False, "404"]
156 def render_GET(self
, request
):
157 path
= request
.path
[len(self
.prefix
):]
158 if path
.startswith("/s/"):
160 session
= Sessions
.get(sessionid
)
163 return [False, "Bad session ID"]
165 session
.subscribe(SingleUseChannel(request
))
166 return server
.NOT_DONE_YET
167 if path
.startswith("/p/"):
168 command
= request
.args
.get("c")
170 return [False, "No command specified"]
175 session
= Sessions
.get(sessionid
)
177 return [False, "Bad session ID"]
180 decoded
= command
.decode("utf-8")
181 except UnicodeDecodeError:
182 decoded
= command
.decode("iso-8859-1", "ignore")
185 session
.push(decoded
)
186 except AttributeError: # occurs when we haven't noticed an error
188 return [False, "Connection closed by server."]
189 except Exception, e
: # catch all
191 traceback
.print_exc(file=sys
.stderr
)
192 return [False, "Unknown error."]
196 return [False, "404"]