]>
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):
16 def decorator(*args
, **kwargs
):
17 x
= fn(*args
, **kwargs
)
18 if isinstance(x
, list):
19 return simplejson
.dumps(x
)
23 def cleanupSession(id):
30 def __init__(self
, id):
32 self
.subscriptions
= []
37 self
.cleanupschedule
= None
39 def subscribe(self
, channel
):
40 if len(self
.subscriptions
) >= config
.MAXSUBSCRIPTIONS
:
41 self
.subscriptions
.pop(0)
43 self
.subscriptions
.append(channel
)
46 def flush(self
, scheduled
=False):
50 if not self
.buffer or not self
.subscriptions
:
57 self
.schedule
= reactor
.callLater(self
.throttle
- t
, self
.flush
, True)
60 # process the rest of the packet
63 self
.schedule
= reactor
.callLater(0, self
.flush
, True)
66 self
.throttle
= t
+ config
.UPDATE_FREQ
68 encdata
= simplejson
.dumps(self
.buffer)
72 for x
in self
.subscriptions
:
76 self
.subscriptions
= newsubs
77 if self
.closed
and not self
.subscriptions
:
78 cleanupSession(self
.id)
80 def event(self
, data
):
81 bufferlen
= sum(map(len, self
.buffer))
82 if bufferlen
+ len(data
) > config
.MAXBUFLEN
:
84 self
.client
.error("Buffer overflow")
87 self
.buffer.append(data
)
92 self
.client
.write(data
)
95 # keep the session hanging around for a few seconds so the
96 # client has a chance to see what the issue was
99 reactor
.callLater(5, cleanupSession
, self
.id)
102 def __init__(self
, request
):
103 self
.request
= request
105 class SingleUseChannel(Channel
):
106 def write(self
, data
):
107 self
.request
.write(data
)
108 self
.request
.finish()
111 class MultipleUseChannel(Channel
):
112 def write(self
, data
):
113 self
.request
.write(data
)
116 class AJAXEngine(resource
.Resource
):
119 def __init__(self
, prefix
):
123 def render_POST(self
, request
):
124 path
= request
.path
[len(self
.prefix
):]
126 ip
= request
.transport
.getPeer()
129 nick
, ident
= request
.args
.get("nick"), "webchat"
131 return [False, "Nickname not supplied"]
135 id = get_session_id()
137 session
= IRCSession(id)
139 client
= ircclient
.createIRC(session
, nick
=nick
, ident
=ident
, ip
=ip
, realname
=nick
)
140 session
.client
= client
142 Sessions
[id] = session
145 return [False, "404"]
148 def render_GET(self
, request
):
149 path
= request
.path
[len(self
.prefix
):]
150 if path
.startswith("/s/"):
152 session
= Sessions
.get(sessionid
)
155 return [False, "Bad session ID"]
157 session
.subscribe(SingleUseChannel(request
))
158 return server
.NOT_DONE_YET
159 if path
.startswith("/p/"):
160 command
= request
.args
.get("c")
162 return [False, "No command specified"]
167 session
= Sessions
.get(sessionid
)
169 return [False, "Bad session ID"]
172 decoded
= command
.decode("utf-8")
173 except UnicodeDecodeError:
174 decoded
= command
.decode("iso-8859-1", "ignore")
177 session
.push(decoded
)
178 except AttributeError: # occurs when we haven't noticed an error
180 return [False, "Connection closed by server."]
181 except Exception, e
: # catch all
183 traceback
.print_exc(file=sys
.stderr
)
184 return [False, "Unknown error."]
188 return [False, "404"]