3
from twisted.application import internet, service, strports
4
from twisted.internet import protocol, reactor, defer
5
from twisted.protocols import basic, irc
6
from twisted.python import components
7
from twisted.web import resource, server, static, xmlrpc, microdom
8
from twisted.web.woven import page, model, interfaces
9
from twisted.spread import pb
10
from OpenSSL import SSL
13
class IFingerService(components.Interface):
15
def getUser(self, user):
16
"""Return a deferred returning a string"""
19
"""Return a deferred returning a list of strings"""
21
class IFingerSetterService(components.Interface):
23
def setUser(self, user, status):
24
"""Set the user's status to something"""
27
return "Internal error in server"
29
class FingerProtocol(basic.LineReceiver):
31
def lineReceived(self, user):
32
d = self.factory.getUser(user)
33
d.addErrback(catchError)
34
def writeValue(value):
35
self.transport.write(value+'\n')
36
self.transport.loseConnection()
37
d.addCallback(writeValue)
40
class IFingerFactory(components.Interface):
42
def getUser(self, user):
43
"""Return a deferred returning a string"""
45
def buildProtocol(self, addr):
46
"""Return a protocol returning a string"""
49
class FingerFactoryFromService(protocol.ServerFactory):
50
__implements__ = protocol.ServerFactory.__implements__, IFingerFactory
52
protocol = FingerProtocol
54
def __init__(self, service):
55
self.service = service
57
def getUser(self, user):
58
return self.service.getUser(user)
60
components.registerAdapter(FingerFactoryFromService,
64
class FingerSetterProtocol(basic.LineReceiver):
66
def connectionMade(self):
69
def lineReceived(self, line):
70
self.lines.append(line)
72
def connectionLost(self, reason):
73
if len(self.lines) == 2:
74
self.factory.setUser(*self.lines)
77
class IFingerSetterFactory(components.Interface):
79
def setUser(self, user, status):
80
"""Return a deferred returning a string"""
82
def buildProtocol(self, addr):
83
"""Return a protocol returning a string"""
86
class FingerSetterFactoryFromService(protocol.ServerFactory):
88
__implements__ = protocol.ServerFactory.__implements__,IFingerSetterFactory
90
protocol = FingerSetterProtocol
92
def __init__(self, service):
93
self.service = service
95
def setUser(self, user, status):
96
self.service.setUser(user, status)
99
components.registerAdapter(FingerSetterFactoryFromService,
100
IFingerSetterService,
101
IFingerSetterFactory)
103
class IRCReplyBot(irc.IRCClient):
105
def connectionMade(self):
106
self.nickname = self.factory.nickname
107
irc.IRCClient.connectionMade(self)
109
def privmsg(self, user, channel, msg):
110
user = user.split('!')[0]
111
if self.nickname.lower() == channel.lower():
112
d = self.factory.getUser(msg)
113
d.addErrback(catchError)
114
d.addCallback(lambda m: "Status of %s: %s" % (msg, m))
115
d.addCallback(lambda m: self.msg(user, m))
118
class IIRCClientFactory(components.Interface):
124
def getUser(self, user):
125
"""Return a deferred returning a string"""
127
def buildProtocol(self, addr):
128
"""Return a protocol"""
131
class IRCClientFactoryFromService(protocol.ClientFactory):
133
__implements__ = protocol.ClientFactory.__implements__, IIRCClientFactory
135
protocol = IRCReplyBot
138
def __init__(self, service):
139
self.service = service
141
def getUser(self, user):
142
return self.service.getUser(user)
144
components.registerAdapter(IRCClientFactoryFromService,
148
class UsersModel(model.MethodModel):
150
def initialize(self, *args, **kwargs):
153
def wmfactory_users(self, request):
154
return self.service.getUsers()
156
components.registerAdapter(UsersModel, IFingerService, interfaces.IModel)
158
class UserStatusTree(page.Page):
160
template = """<html><head><title>Users</title></head><body>
162
<ul model="users" view="List">
163
<li pattern="listItem"><a view="Anchor" /></li>
164
</ul></body></html>"""
166
def initialize(self, *args, **kwargs):
169
def getDynamicChild(self, path, request):
170
return UserStatus(user=path, service=self.service)
172
def wchild_RPC2 (self, request):
173
return UserStatusXR(self.service)
175
components.registerAdapter(UserStatusTree, IFingerService, resource.IResource)
178
class UserStatus(page.Page):
180
template='''<html><head><title view="Text" model="user"/></head>
181
<body><h1 view="Text" model="user"/>
182
<p model="status" view="Text" />
185
def initialize(self, **kwargs):
186
self.user = kwargs['user']
187
self.service = kwargs['service']
189
def wmfactory_user(self, request):
192
def wmfactory_status(self, request):
193
return self.service.getUser(self.user)
196
class UserStatusXR(xmlrpc.XMLRPC):
198
def __init__(self, service):
199
xmlrpc.XMLRPC.__init__(self)
200
self.service = service
202
def xmlrpc_getUser(self, user):
203
return self.service.getUser(user)
205
def xmlrpc_getUsers(self):
206
return self.service.getUsers()
209
class IPerspectiveFinger(components.Interface):
211
def remote_getUser(self, username):
212
"""return a user's status"""
214
def remote_getUsers(self):
215
"""return a user's status"""
217
class PerspectiveFingerFromService(pb.Root):
219
__implements__ = pb.Root.__implements__, IPerspectiveFinger
221
def __init__(self, service):
222
self.service = service
224
def remote_getUser(self, username):
225
return self.service.getUser(username)
227
def remote_getUsers(self):
228
return self.service.getUsers()
230
components.registerAdapter(PerspectiveFingerFromService,
235
class FingerService(service.Service):
237
__implements__ = service.Service.__implements__, IFingerService
239
def __init__(self, filename):
240
self.filename = filename
245
for line in file(self.filename):
246
user, status = line.split(':', 1)
248
status = status.strip()
249
self.users[user] = status
250
self.call = reactor.callLater(30, self._read)
252
def getUser(self, user):
253
return defer.succeed(self.users.get(user, "No such user"))
256
return defer.succeed(self.users.keys())
259
class ServerContextFactory:
261
def getContext(self):
262
"""Create an SSL context.
264
This is a sample implementation that loads a certificate from a file
265
called 'server.pem'."""
266
ctx = SSL.Context(SSL.SSLv23_METHOD)
267
ctx.use_certificate_file('server.pem')
268
ctx.use_privatekey_file('server.pem')
276
def makeService(config):
278
s = service.MultiService()
279
f = FingerService(config['file'])
280
h = internet.TCPServer(79, IFingerFactory(f))
281
h.setServiceParent(s)
284
# website on port 8000
285
r = resource.IResource(f)
286
r.templateDirectory = config['templates']
287
site = server.Site(r)
288
j = internet.TCPServer(8000, site)
289
j.setServiceParent(s)
292
# if config.get('ssl'):
293
# k = internet.SSLServer(443, site, ServerContextFactory())
294
# k.setServiceParent(s)
297
if config.has_key('ircnick'):
298
i = IIRCClientFactory(f)
299
i.nickname = config['ircnick']
300
ircserver = config['ircserver']
301
b = internet.TCPClient(ircserver, 6667, i)
302
b.setServiceParent(s)
304
# Pespective Broker on port 8889
305
if config.has_key('pbport'):
306
m = internet.TCPServer(
307
int(config['pbport']),
308
pb.PBServerFactory(IPerspectiveFinger(f)))
309
m.setServiceParent(s)