1
# Do everything properly
2
from twisted.application import internet, service
3
from twisted.internet import protocol, reactor, defer
4
from twisted.words.protocols import irc
5
from twisted.protocols import basic
6
from twisted.web import resource, server, static, xmlrpc
10
return "Internal error in server"
12
class FingerProtocol(basic.LineReceiver):
14
def lineReceived(self, user):
15
d = self.factory.getUser(user)
16
d.addErrback(catchError)
17
def writeValue(value):
18
self.transport.write(value+'\r\n')
19
self.transport.loseConnection()
20
d.addCallback(writeValue)
23
class IRCReplyBot(irc.IRCClient):
25
def connectionMade(self):
26
self.nickname = self.factory.nickname
27
irc.IRCClient.connectionMade(self)
29
def privmsg(self, user, channel, msg):
30
user = user.split('!')[0]
31
if self.nickname.lower() == channel.lower():
32
d = self.factory.getUser(msg)
33
d.addErrback(catchError)
34
d.addCallback(lambda m: "Status of %s: %s" % (msg, m))
35
d.addCallback(lambda m: self.msg(user, m))
38
class UserStatusTree(resource.Resource):
39
def __init__(self, service):
40
resource.Resource.__init__(self)
41
self.service = service
43
def render_GET(self, request):
44
d = self.service.getUsers()
45
def formatUsers(users):
46
l = ['<li><a href="%s">%s</a></li>' % (user, user)
48
return '<ul>'+''.join(l)+'</ul>'
49
d.addCallback(formatUsers)
50
d.addCallback(request.write)
51
d.addCallback(lambda _: request.finish())
52
return server.NOT_DONE_YET
54
def getChild(self, path, request):
56
return UserStatusTree(self.service)
58
return UserStatus(path, self.service)
60
class UserStatus(resource.Resource):
62
def __init__(self, user, service):
63
resource.Resource.__init__(self)
65
self.service = service
67
def render_GET(self, request):
68
d = self.service.getUser(self.user)
69
d.addCallback(cgi.escape)
70
d.addCallback(lambda m:
71
'<h1>%s</h1>'%self.user+'<p>%s</p>'%m)
72
d.addCallback(request.write)
73
d.addCallback(lambda _: request.finish())
74
return server.NOT_DONE_YET
77
class UserStatusXR(xmlrpc.XMLRPC):
79
def __init__(self, service):
80
xmlrpc.XMLRPC.__init__(self)
81
self.service = service
83
def xmlrpc_getUser(self, user):
84
return self.service.getUser(user)
87
class FingerService(service.Service):
89
def __init__(self, filename):
90
self.filename = filename
96
for line in file(self.filename):
97
user, status = line.split(':', 1)
99
status = status.strip()
100
self.users[user] = status
101
self.call = reactor.callLater(30, self._read)
103
def getUser(self, user):
104
return defer.succeed(self.users.get(user, "No such user"))
107
return defer.succeed(self.users.keys())
109
def getFingerFactory(self):
110
f = protocol.ServerFactory()
111
f.protocol = FingerProtocol
112
f.getUser = self.getUser
115
def getResource(self):
116
r = UserStatusTree(self)
117
x = UserStatusXR(self)
118
r.putChild('RPC2', x)
121
def getIRCBot(self, nickname):
122
f = protocol.ReconnectingClientFactory()
123
f.protocol = IRCReplyBot
124
f.nickname = nickname
125
f.getUser = self.getUser
129
application = service.Application('finger', uid=1, gid=1)
130
f = FingerService('/etc/users')
131
serviceCollection = service.IServiceCollection(application)
132
internet.TCPServer(79, f.getFingerFactory()
133
).setServiceParent(serviceCollection)
134
internet.TCPServer(8000, server.Site(f.getResource())
135
).setServiceParent(serviceCollection)
136
internet.TCPClient('irc.freenode.org', 6667, f.getIRCBot('fingerbot')
137
).setServiceParent(serviceCollection)