Initial import to Tizen
[profile/ivi/python-twisted.git] / doc / core / howto / tutorial / listings / finger / finger / finger.py
1 # finger.py module
2
3 from zope.interface import Interface, implements
4
5 from twisted.application import internet, service
6 from twisted.internet import protocol, reactor, defer
7 from twisted.words.protocols import irc
8 from twisted.protocols import basic
9 from twisted.python import components, log
10 from twisted.web import resource, server, xmlrpc
11 from twisted.spread import pb
12
13 from OpenSSL import SSL
14
15 class IFingerService(Interface):
16
17     def getUser(user):
18         """
19         Return a deferred returning a string.
20         """
21
22     def getUsers():
23         """
24         Return a deferred returning a list of strings.
25         """
26
27
28 class IFingerSetterService(Interface):
29
30     def setUser(user, status):
31         """
32         Set the user's status to something.
33         """
34
35
36 def catchError(err):
37     return "Internal error in server"
38
39
40 class FingerProtocol(basic.LineReceiver):
41
42     def lineReceived(self, user):
43         d = self.factory.getUser(user)
44         d.addErrback(catchError)
45         def writeValue(value):
46             self.transport.write(value+'\n')
47             self.transport.loseConnection()
48         d.addCallback(writeValue)
49
50
51 class IFingerFactory(Interface):
52
53     def getUser(user):
54         """
55         Return a deferred returning a string.
56         """
57
58     def buildProtocol(addr):
59         """
60         Return a protocol returning a string.
61         """
62
63
64 class FingerFactoryFromService(protocol.ServerFactory):
65     implements(IFingerFactory)
66
67     protocol = FingerProtocol
68
69     def __init__(self, service):
70         self.service = service
71
72     def getUser(self, user):
73         return self.service.getUser(user)
74
75 components.registerAdapter(FingerFactoryFromService,
76                            IFingerService,
77                            IFingerFactory)
78
79
80 class FingerSetterProtocol(basic.LineReceiver):
81
82     def connectionMade(self):
83         self.lines = []
84
85     def lineReceived(self, line):
86         self.lines.append(line)
87
88     def connectionLost(self, reason):
89         if len(self.lines) == 2:
90             self.factory.setUser(*self.lines)
91
92
93 class IFingerSetterFactory(Interface):
94
95     def setUser(user, status):
96         """
97         Return a deferred returning a string.
98         """
99
100     def buildProtocol(addr):
101         """
102         Return a protocol returning a string.
103         """
104
105
106 class FingerSetterFactoryFromService(protocol.ServerFactory):
107
108     implements(IFingerSetterFactory)
109
110     protocol = FingerSetterProtocol
111
112     def __init__(self, service):
113         self.service = service
114
115     def setUser(self, user, status):
116         self.service.setUser(user, status)
117
118
119 components.registerAdapter(FingerSetterFactoryFromService,
120                            IFingerSetterService,
121                            IFingerSetterFactory)
122
123
124 class IRCReplyBot(irc.IRCClient):
125
126     def connectionMade(self):
127         self.nickname = self.factory.nickname
128         irc.IRCClient.connectionMade(self)
129
130     def privmsg(self, user, channel, msg):
131         user = user.split('!')[0]
132         if self.nickname.lower() == channel.lower():
133             d = self.factory.getUser(msg)
134             d.addErrback(catchError)
135             d.addCallback(lambda m: "Status of %s: %s" % (msg, m))
136             d.addCallback(lambda m: self.msg(user, m))
137
138
139 class IIRCClientFactory(Interface):
140
141     """
142     @ivar nickname
143     """
144
145     def getUser(user):
146         """
147         Return a deferred returning a string.
148         """
149
150     def buildProtocol(addr):
151         """
152         Return a protocol.
153         """
154
155
156 class IRCClientFactoryFromService(protocol.ClientFactory):
157
158     implements(IIRCClientFactory)
159
160     protocol = IRCReplyBot
161     nickname = None
162
163     def __init__(self, service):
164         self.service = service
165
166     def getUser(self, user):
167         return self.service.getUser(user)
168
169 components.registerAdapter(IRCClientFactoryFromService,
170                            IFingerService,
171                            IIRCClientFactory)
172
173
174 class UserStatusTree(resource.Resource):
175
176     template = """<html><head><title>Users</title></head><body>
177     <h1>Users</h1>
178     <ul>
179     %(users)s
180     </ul>
181     </body>
182     </html>"""
183
184     def __init__(self, service):
185         resource.Resource.__init__(self)
186         self.service = service
187
188     def getChild(self, path, request):
189         if path == '':
190             return self
191         elif path == 'RPC2':
192             return UserStatusXR(self.service)
193         else:
194             return UserStatus(path, self.service)
195
196     def render_GET(self, request):
197         users = self.service.getUsers()
198         def cbUsers(users):
199             request.write(self.template % {'users': ''.join([
200                     # Name should be quoted properly these uses.
201                     '<li><a href="%s">%s</a></li>' % (name, name)
202                     for name in users])})
203             request.finish()
204         users.addCallback(cbUsers)
205         def ebUsers(err):
206             log.err(err, "UserStatusTree failed")
207             request.finish()
208         users.addErrback(ebUsers)
209         return server.NOT_DONE_YET
210
211 components.registerAdapter(UserStatusTree, IFingerService, resource.IResource)
212
213
214 class UserStatus(resource.Resource):
215
216     template='''<html><head><title>%(title)s</title></head>
217     <body><h1>%(name)s</h1><p>%(status)s</p></body></html>'''
218
219     def __init__(self, user, service):
220         resource.Resource.__init__(self)
221         self.user = user
222         self.service = service
223
224     def render_GET(self, request):
225         status = self.service.getUser(self.user)
226         def cbStatus(status):
227             request.write(self.template % {
228                 'title': self.user,
229                 'name': self.user,
230                 'status': status})
231             request.finish()
232         status.addCallback(cbStatus)
233         def ebStatus(err):
234             log.err(err, "UserStatus failed")
235             request.finish()
236         status.addErrback(ebStatus)
237         return server.NOT_DONE_YET
238
239
240 class UserStatusXR(xmlrpc.XMLRPC):
241
242     def __init__(self, service):
243         xmlrpc.XMLRPC.__init__(self)
244         self.service = service
245
246     def xmlrpc_getUser(self, user):
247         return self.service.getUser(user)
248
249     def xmlrpc_getUsers(self):
250         return self.service.getUsers()
251
252
253 class IPerspectiveFinger(Interface):
254
255     def remote_getUser(username):
256         """
257         Return a user's status.
258         """
259
260     def remote_getUsers():
261         """
262         Return a user's status.
263         """
264
265
266 class PerspectiveFingerFromService(pb.Root):
267
268     implements(IPerspectiveFinger)
269
270     def __init__(self, service):
271         self.service = service
272
273     def remote_getUser(self, username):
274         return self.service.getUser(username)
275
276     def remote_getUsers(self):
277         return self.service.getUsers()
278
279 components.registerAdapter(PerspectiveFingerFromService,
280                            IFingerService,
281                            IPerspectiveFinger)
282
283
284 class FingerService(service.Service):
285
286     implements(IFingerService)
287
288     def __init__(self, filename):
289         self.filename = filename
290
291     def _read(self):
292         self.users = {}
293         for line in file(self.filename):
294             user, status = line.split(':', 1)
295             user = user.strip()
296             status = status.strip()
297             self.users[user] = status
298         self.call = reactor.callLater(30, self._read)
299
300     def getUser(self, user):
301         return defer.succeed(self.users.get(user, "No such user"))
302
303     def getUsers(self):
304         return defer.succeed(self.users.keys())
305
306     def startService(self):
307         self._read()
308         service.Service.startService(self)
309
310     def stopService(self):
311         service.Service.stopService(self)
312         self.call.cancel()
313
314
315 class ServerContextFactory:
316
317     def getContext(self):
318         """
319         Create an SSL context.
320
321         This is a sample implementation that loads a certificate from a file
322         called 'server.pem'.
323         """
324         ctx = SSL.Context(SSL.SSLv23_METHOD)
325         ctx.use_certificate_file('server.pem')
326         ctx.use_privatekey_file('server.pem')
327         return ctx
328
329
330
331 # Easy configuration
332
333 def makeService(config):
334     # finger on port 79
335     s = service.MultiService()
336     f = FingerService(config['file'])
337     h = internet.TCPServer(1079, IFingerFactory(f))
338     h.setServiceParent(s)
339
340
341     # website on port 8000
342     r = resource.IResource(f)
343     r.templateDirectory = config['templates']
344     site = server.Site(r)
345     j = internet.TCPServer(8000, site)
346     j.setServiceParent(s)
347
348     # ssl on port 443
349 #    if config.get('ssl'):
350 #        k = internet.SSLServer(443, site, ServerContextFactory())
351 #        k.setServiceParent(s)
352
353     # irc fingerbot
354     if config.has_key('ircnick'):
355         i = IIRCClientFactory(f)
356         i.nickname = config['ircnick']
357         ircserver = config['ircserver']
358         b = internet.TCPClient(ircserver, 6667, i)
359         b.setServiceParent(s)
360
361     # Pespective Broker on port 8889
362     if config.has_key('pbport'):
363         m = internet.TCPServer(
364             int(config['pbport']),
365             pb.PBServerFactory(IPerspectiveFinger(f)))
366         m.setServiceParent(s)
367
368     return s