from __future__ import division
import md5, urllib, time, sys, math, socket
from sets import Set
from twisted.application import internet, service
from twisted.internet import task
from twisted.python import log, util
from twisted.python.components import registerAdapter
from zope.interface import Interface
import nevow
from nevow import appserver
from nevow import loaders, rend, static, tags as T, athena, inevow
from nevow.vhost import VHostMonsterResource
from louie import dispatcher
from twisted.web.http import HTTPFactory
def shortLog(self, request):
if hasattr(self, "logFile"):
# if request.uri != "/":
# return
line = '"%s %s" %s %s (%s)\n' % (
self._escape(request.method),
self._escape(request.uri),
request.code,
request.sentLength or "-",
self._escape(request.getHeader("referer") or "-"))
self.logFile.write(line)
HTTPFactory.log = shortLog
position = [0, 0] # out in the ocean :)
key = open("access.key").read().strip()
class GpsClient(rend.Page):
docFactory = loaders.xmlstr("")
def renderHTTP(self, ctx):
if ctx.arg('key') != key:
raise ValueError("key must be set to the contents of access.key")
position[:] = [float(ctx.arg('lat')), float(ctx.arg('long'))]
dispatcher.send("updatePosition")
return rend.Page.renderHTTP(self, ctx)
class MapWatch(athena.LivePage):
addSlash = True
def child_(self, ctx):
return MapWatch()
def renderHTTP(self, ctx):
self.client = inevow.IRequest(ctx).getClient()
headers = inevow.IRequest(ctx).getAllHeaders()
if 'x-forwarded-for' in headers:
try:
(self.client, _, _) = socket.gethostbyaddr(headers['x-forwarded-for'])
except socket.herror:
self.client = headers['x-forwarded-for']
self.displayedWatchers = []
ret = athena.LivePage.renderHTTP(self, ctx)
dispatcher.connect(self.updatePosition, "client connected")
dispatcher.connect(self.updatePosition, "client disconnected")
dispatcher.connect(self.addMsg, "addMsg")
dispatcher.send("client connected")
d = self.notifyOnDisconnect()
def discon(result, whichClient):
dispatcher.send("client disconnected", clientJustLeft=whichClient)
return result
d.addErrback(discon, self)
return ret
def nick(self):
return unicode("%s-%s" % (self.client, hex(id(self))[-4:]))
def __repr__(self):
return "" % self.nick()
def child_gpsClient(self, ctx):
return GpsClient()
docFactory = loaders.xmlfile("main.html")
# def __init__(self, *args, **kw):
# super(MapWatch, self).__init__(*args, **kw)
def locateMethod(self, ctx, methodName):
# this is overridden from LivePage.
# i can't figure out what iface or rootObject are for, so i'll
# do my own simple dispatching
meth = getattr(self, methodName)
if meth.expose:
return meth
raise NameError("%s not exposed" % methodName)
def startUpdates(self):
self.updatePosition()
dispatcher.connect(self.updatePosition, "updatePosition")
startUpdates.expose = True
def findGps(self):
self.callRemote('panTo', position)
findGps.expose = True
def updatePosition(self, clientJustLeft=None):
watchers = self.factory.clients.values()
if clientJustLeft in watchers:
watchers.remove(clientJustLeft)
deadWatchers = self.displayedWatchers[:]
for w in watchers:
if w not in deadWatchers:
if w not in self.displayedWatchers:
d = self.callRemote('addWatcher', w.nick(), w is self)
self.displayedWatchers.append(w)
else:
deadWatchers.remove(w)
for w in deadWatchers:
d = self.callRemote('removeWatcher', w.nick())
self.displayedWatchers.remove(w)
self.callRemote('placeGps', position)
def submitMsg(self, clientMsg):
print "%s writes %s" % (self.nick(), clientMsg)
dispatcher.send("addMsg", client=self, msg=clientMsg)
submitMsg.expose = True
def addMsg(self, client, msg):
self.callRemote('addMsg', client.nick(), msg)
for f in ['rings.png', 'MochiKit.js']:
setattr(MapWatch, 'child_' + f, static.File(f))
print "nevow", nevow.__version__
main = MapWatch()
main.putChild('vhost', VHostMonsterResource())
application = service.Application('maps')
webServer = internet.TCPServer(8084, appserver.NevowSite(main))
webServer.setServiceParent(application)