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