Initial import to Tizen
[profile/ivi/python-twisted.git] / doc / core / howto / tutorial / listings / finger / finger19b.tac
1 # Do everything properly, and componentize
2 from twisted.application import internet, service
3 from twisted.internet import protocol, reactor, defer, utils
4 from twisted.words.protocols import irc
5 from twisted.protocols import basic
6 from twisted.python import components
7 from twisted.web import resource, server, static, xmlrpc
8 from zope.interface import Interface, implements
9 import cgi
10 import pwd
11
12 class IFingerService(Interface):
13
14     def getUser(user):
15         """
16         Return a deferred returning a string.
17         """
18
19     def getUsers():
20         """
21         Return a deferred returning a list of strings.
22         """
23
24
25 class IFingerSetterService(Interface):
26
27     def setUser(user, status):
28         """
29         Set the user's status to something.
30         """
31
32
33 class IFingerSetterService(Interface):
34
35     def setUser(user, status):
36         """
37         Set the user's status to something.
38         """
39
40
41 def catchError(err):
42     return "Internal error in server"
43
44
45 class FingerProtocol(basic.LineReceiver):
46
47     def lineReceived(self, user):
48         d = self.factory.getUser(user)
49         d.addErrback(catchError)
50         def writeValue(value):
51             self.transport.write(value+'\r\n')
52             self.transport.loseConnection()
53         d.addCallback(writeValue)
54
55
56 class IFingerFactory(Interface):
57
58     def getUser(user):
59         """
60         Return a deferred returning a string.
61         """
62
63     def buildProtocol(addr):
64         """
65         Return a protocol returning a string.
66         """
67
68
69 class FingerFactoryFromService(protocol.ServerFactory):
70
71     implements(IFingerFactory)
72
73     protocol = FingerProtocol
74
75     def __init__(self, service):
76         self.service = service
77
78     def getUser(self, user):
79         return self.service.getUser(user)
80
81 components.registerAdapter(FingerFactoryFromService,
82                            IFingerService,
83                            IFingerFactory)
84
85
86 class FingerSetterProtocol(basic.LineReceiver):
87
88     def connectionMade(self):
89         self.lines = []
90
91     def lineReceived(self, line):
92         self.lines.append(line)
93
94     def connectionLost(self, reason):
95         if len(self.lines) == 2:
96             self.factory.setUser(*self.lines)
97
98
99 class IFingerSetterFactory(Interface):
100
101     def setUser(user, status):
102         """
103         Return a deferred returning a string.
104         """
105
106     def buildProtocol(addr):
107         """
108         Return a protocol returning a string.
109         """
110
111
112 class FingerSetterFactoryFromService(protocol.ServerFactory):
113
114     implements(IFingerSetterFactory)
115
116     protocol = FingerSetterProtocol
117
118     def __init__(self, service):
119         self.service = service
120
121     def setUser(self, user, status):
122         self.service.setUser(user, status)
123
124
125 components.registerAdapter(FingerSetterFactoryFromService,
126                            IFingerSetterService,
127                            IFingerSetterFactory)
128
129 class IRCReplyBot(irc.IRCClient):
130
131     def connectionMade(self):
132         self.nickname = self.factory.nickname
133         irc.IRCClient.connectionMade(self)
134
135     def privmsg(self, user, channel, msg):
136         user = user.split('!')[0]
137         if self.nickname.lower() == channel.lower():
138             d = self.factory.getUser(msg)
139             d.addErrback(catchError)
140             d.addCallback(lambda m: "Status of %s: %s" % (msg, m))
141             d.addCallback(lambda m: self.msg(user, m))
142
143
144 class IIRCClientFactory(Interface):
145
146     """
147     @ivar nickname
148     """
149
150     def getUser(user):
151         """
152         Return a deferred returning a string.
153         """
154
155     def buildProtocol(addr):
156         """
157         Return a protocol.
158         """
159
160
161 class IRCClientFactoryFromService(protocol.ClientFactory):
162
163     implements(IIRCClientFactory)
164
165     protocol = IRCReplyBot
166     nickname = None
167
168     def __init__(self, service):
169         self.service = service
170
171     def getUser(self, user):
172         return self.service.getUser(user)
173
174 components.registerAdapter(IRCClientFactoryFromService,
175                            IFingerService,
176                            IIRCClientFactory)
177
178
179 class UserStatusTree(resource.Resource):
180
181     implements(resource.IResource)
182
183     def __init__(self, service):
184         resource.Resource.__init__(self)
185         self.service = service
186         self.putChild('RPC2', UserStatusXR(self.service))
187
188     def render_GET(self, request):
189         d = self.service.getUsers()
190         def formatUsers(users):
191             l = ['<li><a href="%s">%s</a></li>' % (user, user)
192                  for user in users]
193             return '<ul>'+''.join(l)+'</ul>'
194         d.addCallback(formatUsers)
195         d.addCallback(request.write)
196         d.addCallback(lambda _: request.finish())
197         return server.NOT_DONE_YET
198
199     def getChild(self, path, request):
200         if path=="":
201             return UserStatusTree(self.service)
202         else:
203             return UserStatus(path, self.service)
204
205 components.registerAdapter(UserStatusTree, IFingerService,
206                            resource.IResource)
207
208
209 class UserStatus(resource.Resource):
210
211     def __init__(self, user, service):
212         resource.Resource.__init__(self)
213         self.user = user
214         self.service = service
215
216     def render_GET(self, request):
217         d = self.service.getUser(self.user)
218         d.addCallback(cgi.escape)
219         d.addCallback(lambda m:
220                       '<h1>%s</h1>'%self.user+'<p>%s</p>'%m)
221         d.addCallback(request.write)
222         d.addCallback(lambda _: request.finish())
223         return server.NOT_DONE_YET
224
225
226 class UserStatusXR(xmlrpc.XMLRPC):
227
228     def __init__(self, service):
229         xmlrpc.XMLRPC.__init__(self)
230         self.service = service
231
232     def xmlrpc_getUser(self, user):
233         return self.service.getUser(user)
234
235
236 class FingerService(service.Service):
237
238     implements(IFingerService)
239
240     def __init__(self, filename):
241         self.filename = filename
242         self.users = {}
243
244     def _read(self):
245         self.users.clear()
246         for line in file(self.filename):
247             user, status = line.split(':', 1)
248             user = user.strip()
249             status = status.strip()
250             self.users[user] = status
251         self.call = reactor.callLater(30, self._read)
252
253     def getUser(self, user):
254         return defer.succeed(self.users.get(user, "No such user"))
255
256     def getUsers(self):
257         return defer.succeed(self.users.keys())
258
259     def startService(self):
260         self._read()
261         service.Service.startService(self)
262
263     def stopService(self):
264         service.Service.stopService(self)
265         self.call.cancel()
266
267
268 # Another back-end
269
270 class LocalFingerService(service.Service):
271
272     implements(IFingerService)
273
274     def getUser(self, user):
275     # need a local finger daemon running for this to work
276         return utils.getProcessOutput("finger", [user])
277
278     def getUsers(self):
279         return defer.succeed([])
280
281
282 application = service.Application('finger', uid=1, gid=1)
283 f = LocalFingerService()
284 serviceCollection = service.IServiceCollection(application)
285 internet.TCPServer(79, IFingerFactory(f)
286                    ).setServiceParent(serviceCollection)
287 internet.TCPServer(8000, server.Site(resource.IResource(f))
288                    ).setServiceParent(serviceCollection)
289 i = IIRCClientFactory(f)
290 i.nickname = 'fingerbot'
291 internet.TCPClient('irc.freenode.org', 6667, i
292                    ).setServiceParent(serviceCollection)