-from twisted.web import resource, server, static\r
-from twisted.names import client\r
-from twisted.internet import reactor\r
-import simplejson, md5, sys, os, ircclient, time, config\r
-\r
-Sessions = {}\r
-\r
-def get_session_id():\r
- return md5.md5(os.urandom(16)).hexdigest()\r
- \r
-def jsondump(fn):\r
- def decorator(*args, **kwargs):\r
- x = fn(*args, **kwargs)\r
- if isinstance(x, list):\r
- return simplejson.dumps(x)\r
- return x\r
- return decorator\r
-\r
-class IRCSession:\r
- def __init__(self, id):\r
- self.id = id\r
- self.subscriptions = []\r
- self.buffer = []\r
- self.throttle = 0\r
- self.schedule = None\r
- \r
- def subscribe(self, channel):\r
- self.subscriptions.append(channel)\r
- self.flush()\r
- \r
- def flush(self, scheduled=False):\r
- if scheduled:\r
- self.schedule = None\r
- \r
- if not self.buffer or not self.subscriptions:\r
- return\r
- \r
- t = time.time()\r
- \r
- if t < self.throttle:\r
- if not self.schedule:\r
- self.schedule = reactor.callLater(self.throttle - t, self.flush, True)\r
- return\r
- else:\r
- # process the rest of the packet\r
- if not scheduled:\r
- if not self.schedule:\r
- self.schedule = reactor.callLater(0, self.flush, True)\r
- return\r
- \r
- self.throttle = t + config.UPDATE_FREQ\r
-\r
- encdata = simplejson.dumps(self.buffer)\r
- self.buffer = []\r
- \r
- newsubs = []\r
- for x in self.subscriptions:\r
- if x.write(encdata):\r
- newsubs.append(x)\r
-\r
- self.subscriptions = newsubs\r
- \r
- def event(self, data):\r
- self.buffer.append(data)\r
- self.flush()\r
- \r
- def push(self, data):\r
- self.client.write(data)\r
- \r
-class Channel:\r
- def __init__(self, request):\r
- self.request = request\r
- \r
-class SingleUseChannel(Channel):\r
- def write(self, data):\r
- self.request.write(data)\r
- self.request.finish()\r
- return False\r
- \r
-class MultipleUseChannel(Channel):\r
- def write(self, data):\r
- self.request.write(data)\r
- return True\r
-\r
-class AJAXEngine(resource.Resource):\r
- isLeaf = True\r
- \r
- def __init__(self, prefix):\r
- self.prefix = prefix\r
-\r
- @jsondump\r
- def render_GET(self, request):\r
- path = request.path[len(self.prefix):]\r
- if path == "/n":\r
- ip = request.transport.getPeer()\r
- ip = ip[1]\r
-\r
- nick, ident = request.args.get("nick"), "webchat"\r
- if not nick:\r
- return [False, "Nickname not supplied"]\r
- \r
- nick = nick[0]\r
- \r
- id = get_session_id()\r
- \r
- session = IRCSession(id)\r
-\r
- client = ircclient.createIRC(session, nick=nick, ident=ident, ip=ip, realname=nick)\r
- session.client = client\r
- \r
- Sessions[id] = session\r
- \r
- return [True, id]\r
- \r
- if path.startswith("/s/"):\r
- sessionid = path[3:]\r
- session = Sessions.get(sessionid)\r
- \r
- if not session:\r
- return [False, "Bad session ID"]\r
-\r
- session.subscribe(SingleUseChannel(request))\r
- return server.NOT_DONE_YET\r
- if path.startswith("/p/"):\r
- command = request.args.get("c")\r
- if not command:\r
- return [False, "No command specified"]\r
-\r
- command = command[0]\r
- \r
- sessionid = path[3:]\r
- session = Sessions.get(sessionid)\r
- if not session:\r
- return [False, "Bad session ID"]\r
-\r
- try:\r
- decoded = command.decode("utf-8")\r
- except UnicodeDecodeError:\r
- decoded = command.decode("iso-8859-1", "ignore")\r
- session.push(decoded)\r
- return [True]\r
-\r
- return [False, "404"]\r
-\r
+from twisted.web import resource, server, static
+from twisted.names import client
+from twisted.internet import reactor
+import simplejson, md5, sys, os, ircclient, time, config
+
+Sessions = {}
+
+def get_session_id():
+ return md5.md5(os.urandom(16)).hexdigest()
+
+def jsondump(fn):
+ def decorator(*args, **kwargs):
+ x = fn(*args, **kwargs)
+ if isinstance(x, list):
+ return simplejson.dumps(x)
+ return x
+ return decorator
+
+class IRCSession:
+ def __init__(self, id):
+ self.id = id
+ self.subscriptions = []
+ self.buffer = []
+ self.throttle = 0
+ self.schedule = None
+
+ def subscribe(self, channel):
+ self.subscriptions.append(channel)
+ self.flush()
+
+ def flush(self, scheduled=False):
+ if scheduled:
+ self.schedule = None
+
+ if not self.buffer or not self.subscriptions:
+ return
+
+ t = time.time()
+
+ if t < self.throttle:
+ if not self.schedule:
+ self.schedule = reactor.callLater(self.throttle - t, self.flush, True)
+ return
+ else:
+ # process the rest of the packet
+ if not scheduled:
+ if not self.schedule:
+ self.schedule = reactor.callLater(0, self.flush, True)
+ return
+
+ self.throttle = t + config.UPDATE_FREQ
+
+ encdata = simplejson.dumps(self.buffer)
+ self.buffer = []
+
+ newsubs = []
+ for x in self.subscriptions:
+ if x.write(encdata):
+ newsubs.append(x)
+
+ self.subscriptions = newsubs
+
+ def event(self, data):
+ self.buffer.append(data)
+ self.flush()
+
+ def push(self, data):
+ self.client.write(data)
+
+class Channel:
+ def __init__(self, request):
+ self.request = request
+
+class SingleUseChannel(Channel):
+ def write(self, data):
+ self.request.write(data)
+ self.request.finish()
+ return False
+
+class MultipleUseChannel(Channel):
+ def write(self, data):
+ self.request.write(data)
+ return True
+
+class AJAXEngine(resource.Resource):
+ isLeaf = True
+
+ def __init__(self, prefix):
+ self.prefix = prefix
+
+ @jsondump
+ def render_GET(self, request):
+ path = request.path[len(self.prefix):]
+ if path == "/n":
+ ip = request.transport.getPeer()
+ ip = ip[1]
+
+ nick, ident = request.args.get("nick"), "webchat"
+ if not nick:
+ return [False, "Nickname not supplied"]
+
+ nick = nick[0]
+
+ id = get_session_id()
+
+ session = IRCSession(id)
+
+ client = ircclient.createIRC(session, nick=nick, ident=ident, ip=ip, realname=nick)
+ session.client = client
+
+ Sessions[id] = session
+
+ return [True, id]
+
+ if path.startswith("/s/"):
+ sessionid = path[3:]
+ session = Sessions.get(sessionid)
+
+ if not session:
+ return [False, "Bad session ID"]
+
+ session.subscribe(SingleUseChannel(request))
+ return server.NOT_DONE_YET
+ if path.startswith("/p/"):
+ command = request.args.get("c")
+ if not command:
+ return [False, "No command specified"]
+
+ command = command[0]
+
+ sessionid = path[3:]
+ session = Sessions.get(sessionid)
+ if not session:
+ return [False, "Bad session ID"]
+
+ try:
+ decoded = command.decode("utf-8")
+ except UnicodeDecodeError:
+ decoded = command.decode("iso-8859-1", "ignore")
+ session.push(decoded)
+ return [True]
+
+ return [False, "404"]
+