Imported Upstream version 12.1.0
[contrib/python-twisted.git] / doc / core / howto / tutorial / listings / finger / finger16.tac
1 # Read from file, announce on the web, irc
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
7
8 import cgi
9
10 class FingerProtocol(basic.LineReceiver):
11     def lineReceived(self, user):
12         d = self.factory.getUser(user)
13
14         def onError(err):
15             return 'Internal error in server'
16         d.addErrback(onError)
17
18         def writeResponse(message):
19             self.transport.write(message + '\r\n')
20             self.transport.loseConnection()
21         d.addCallback(writeResponse)
22
23
24 class IRCReplyBot(irc.IRCClient):
25     def connectionMade(self):
26         self.nickname = self.factory.nickname
27         irc.IRCClient.connectionMade(self)
28
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
34             def onError(err):
35                 return 'Internal error in server'
36             d.addErrback(onError)
37
38             def writeResponse(message):
39                 irc.IRCClient.msg(self, user, msg+': '+message)
40             d.addCallback(writeResponse)
41
42
43 class FingerService(service.Service):
44     def __init__(self, filename):
45         self.filename = filename
46         self.users = {}
47
48     def _read(self):
49         self.users.clear()
50         for line in file(self.filename):
51             user, status = line.split(':', 1)
52             user = user.strip()
53             status = status.strip()
54             self.users[user] = status
55         self.call = reactor.callLater(30, self._read)
56
57     def getUser(self, user):
58         return defer.succeed(self.users.get(user, "No such user"))
59
60     def getFingerFactory(self):
61         f = protocol.ServerFactory()
62         f.protocol = FingerProtocol
63         f.getUser = self.getUser
64         return f
65
66     def getResource(self):
67         r = resource.Resource()
68         r.getChild = (lambda path, request:
69                       static.Data('<h1>%s</h1><p>%s</p>' %
70                       tuple(map(cgi.escape,
71                       [path,self.users.get(path,
72                       "No such user <p/> usage: site/user")])),
73                       'text/html'))
74         return r
75
76     def getIRCBot(self, nickname):
77         f = protocol.ReconnectingClientFactory()
78         f.protocol = IRCReplyBot
79         f.nickname = nickname
80         f.getUser = self.getUser
81         return f
82
83     def startService(self):
84         self._read()
85         service.Service.startService(self)
86
87     def stopService(self):
88         service.Service.stopService(self)
89         self.call.cancel()
90
91
92 application = service.Application('finger', uid=1, gid=1)
93 f = FingerService('/etc/users')
94 serviceCollection = service.IServiceCollection(application)
95 f.setServiceParent(serviceCollection)
96 internet.TCPServer(79, f.getFingerFactory()
97                    ).setServiceParent(serviceCollection)
98 internet.TCPServer(8000, server.Site(f.getResource())
99                    ).setServiceParent(serviceCollection)
100 internet.TCPClient('irc.freenode.org', 6667, f.getIRCBot('fingerbot')
101                    ).setServiceParent(serviceCollection)