root / trunk / twisted / words / im / pbsupport.py

Revision 17451, 9.4 kB (checked in by foom, 3 years ago)

Remove twisted.components.Interface completely.

Merges: killtpc-1636-2
Authors: glyph, therve, jknight
Reviewer: exarkun

Remove deprecated twisted.python.components functionality:
MetaInterface?, Interface, getAdapterClass, and
getAdapterClassWithInheritance.

Also convert all twisted interfaces to use zope.interface directly
(including removing "self" argument), and remove redundant tests.

Line 
1 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4
5 """L{twisted.words} support for Instance Messenger."""
6
7 from __future__ import nested_scopes
8
9 from twisted.internet import defer
10 from twisted.internet import error
11 from twisted.python import log
12 from twisted.python.failure import Failure
13 from twisted.spread import pb
14
15 from twisted.words.im.locals import ONLINE, OFFLINE, AWAY
16
17 from twisted.words.im import basesupport, interfaces
18 from zope.interface import implements
19
20
21 class TwistedWordsPerson(basesupport.AbstractPerson):
22     """I a facade for a person you can talk to through a twisted.words service.
23     """
24     def __init__(self, name, wordsAccount):
25         basesupport.AbstractPerson.__init__(self, name, wordsAccount)
26         self.status = OFFLINE
27
28     def isOnline(self):
29         return ((self.status == ONLINE) or
30                 (self.status == AWAY))
31
32     def getStatus(self):
33         return self.status
34
35     def sendMessage(self, text, metadata):
36         """Return a deferred...
37         """
38         if metadata:
39             d=self.account.client.perspective.directMessage(self.name,
40                                                             text, metadata)
41             d.addErrback(self.metadataFailed, "* "+text)
42             return d
43         else:
44             return self.account.client.perspective.callRemote('directMessage',self.name, text)
45
46     def metadataFailed(self, result, text):
47         print "result:",result,"text:",text
48         return self.account.client.perspective.directMessage(self.name, text)
49
50     def setStatus(self, status):
51         self.status = status
52         self.chat.getContactsList().setContactStatus(self)
53
54 class TwistedWordsGroup(basesupport.AbstractGroup):
55     implements(interfaces.IGroup)
56     def __init__(self, name, wordsClient):
57         basesupport.AbstractGroup.__init__(self, name, wordsClient)
58         self.joined = 0
59
60     def sendGroupMessage(self, text, metadata=None):
61         """Return a deferred.
62         """
63         #for backwards compatibility with older twisted.words servers.
64         if metadata:
65             d=self.account.client.perspective.callRemote(
66                 'groupMessage', self.name, text, metadata)
67             d.addErrback(self.metadataFailed, "* "+text)
68             return d
69         else:
70             return self.account.client.perspective.callRemote('groupMessage',
71                                                               self.name, text)
72
73     def setTopic(self, text):
74         self.account.client.perspective.callRemote(
75             'setGroupMetadata',
76             {'topic': text, 'topic_author': self.client.name},
77             self.name)
78
79     def metadataFailed(self, result, text):
80         print "result:",result,"text:",text
81         return self.account.client.perspective.callRemote('groupMessage',
82                                                           self.name, text)
83
84     def joining(self):
85         self.joined = 1
86
87     def leaving(self):
88         self.joined = 0
89
90     def leave(self):
91         return self.account.client.perspective.callRemote('leaveGroup',
92                                                           self.name)
93
94
95
96 class TwistedWordsClient(pb.Referenceable, basesupport.AbstractClientMixin):
97     """In some cases, this acts as an Account, since it a source of text
98     messages (multiple Words instances may be on a single PB connection)
99     """
100     def __init__(self, acct, serviceName, perspectiveName, chatui,
101                  _logonDeferred=None):
102         self.accountName = "%s (%s:%s)" % (acct.accountName, serviceName, perspectiveName)
103         self.name = perspectiveName
104         print "HELLO I AM A PB SERVICE", serviceName, perspectiveName
105         self.chat = chatui
106         self.account = acct
107         self._logonDeferred = _logonDeferred
108
109     def getPerson(self, name):
110         return self.chat.getPerson(name, self)
111
112     def getGroup(self, name):
113         return self.chat.getGroup(name, self)
114
115     def getGroupConversation(self, name):
116         return self.chat.getGroupConversation(self.getGroup(name))
117
118     def addContact(self, name):
119         self.perspective.callRemote('addContact', name)
120
121     def remote_receiveGroupMembers(self, names, group):
122         print 'received group members:', names, group
123         self.getGroupConversation(group).setGroupMembers(names)
124
125     def remote_receiveGroupMessage(self, sender, group, message, metadata=None):
126         print 'received a group message', sender, group, message, metadata
127         self.getGroupConversation(group).showGroupMessage(sender, message, metadata)
128
129     def remote_memberJoined(self, member, group):
130         print 'member joined', member, group
131         self.getGroupConversation(group).memberJoined(member)
132
133     def remote_memberLeft(self, member, group):
134         print 'member left'
135         self.getGroupConversation(group).memberLeft(member)
136
137     def remote_notifyStatusChanged(self, name, status):
138         self.chat.getPerson(name, self).setStatus(status)
139
140     def remote_receiveDirectMessage(self, name, message, metadata=None):
141         self.chat.getConversation(self.chat.getPerson(name, self)).showMessage(message, metadata)
142
143     def remote_receiveContactList(self, clist):
144         for name, status in clist:
145             self.chat.getPerson(name, self).setStatus(status)
146
147     def remote_setGroupMetadata(self, dict_, groupName):
148         if dict_.has_key("topic"):
149             self.getGroupConversation(groupName).setTopic(dict_["topic"], dict_.get("topic_author", None))
150
151     def joinGroup(self, name):
152         self.getGroup(name).joining()
153         return self.perspective.callRemote('joinGroup', name).addCallback(self._cbGroupJoined, name)
154
155     def leaveGroup(self, name):
156         self.getGroup(name).leaving()
157         return self.perspective.callRemote('leaveGroup', name).addCallback(self._cbGroupLeft, name)
158
159     def _cbGroupJoined(self, result, name):
160         groupConv = self.chat.getGroupConversation(self.getGroup(name))
161         groupConv.showGroupMessage("sys", "you joined")
162         self.perspective.callRemote('getGroupMembers', name)
163
164     def _cbGroupLeft(self, result, name):
165         print 'left',name
166         groupConv = self.chat.getGroupConversation(self.getGroup(name), 1)
167         groupConv.showGroupMessage("sys", "you left")
168
169     def connected(self, perspective):
170         print 'Connected Words Client!', perspective
171         if self._logonDeferred is not None:
172             self._logonDeferred.callback(self)
173         self.perspective = perspective
174         self.chat.getContactsList()
175
176
177 pbFrontEnds = {
178     "twisted.words": TwistedWordsClient,
179     "twisted.reality": None
180     }
181
182
183 class PBAccount(basesupport.AbstractAccount):
184     implements(interfaces.IAccount)
185     gatewayType = "PB"
186     _groupFactory = TwistedWordsGroup
187     _personFactory = TwistedWordsPerson
188
189     def __init__(self, accountName, autoLogin, username, password, host, port,
190                  services=None):
191         """
192         @param username: The name of your PB Identity.
193         @type username: string
194         """
195         basesupport.AbstractAccount.__init__(self, accountName, autoLogin,
196                                              username, password, host, port)
197         self.services = []
198         if not services:
199             services = [('twisted.words', 'twisted.words', username)]
200         for serviceType, serviceName, perspectiveName in services:
201             self.services.append([pbFrontEnds[serviceType], serviceName,
202                                   perspectiveName])
203
204     def logOn(self, chatui):
205         """
206         @returns: this breaks with L{interfaces.IAccount}
207         @returntype: DeferredList of L{interfaces.IClient}s
208         """
209         # Overriding basesupport's implementation on account of the
210         # fact that _startLogOn tends to return a deferredList rather
211         # than a simple Deferred, and we need to do registerAccountClient.
212         if (not self._isConnecting) and (not self._isOnline):
213             self._isConnecting = 1
214             d = self._startLogOn(chatui)
215             d.addErrback(self._loginFailed)
216             def registerMany(results):
217                 for success, result in results:
218                     if success:
219                         chatui.registerAccountClient(result)
220                         self._cb_logOn(result)
221                     else:
222                         log.err(result)
223             d.addCallback(registerMany)
224             return d
225         else:
226             raise error.ConnectionError("Connection in progress")
227
228
229     def _startLogOn(self, chatui):
230         print 'Connecting...',
231         d = pb.getObjectAt(self.host, self.port)
232         d.addCallbacks(self._cbConnected, self._ebConnected,
233                        callbackArgs=(chatui,))
234         return d
235
236     def _cbConnected(self, root, chatui):
237         print 'Connected!'
238         print 'Identifying...',
239         d = pb.authIdentity(root, self.username, self.password)
240         d.addCallbacks(self._cbIdent, self._ebConnected,
241                        callbackArgs=(chatui,))
242         return d
243
244     def _cbIdent(self, ident, chatui):
245         if not ident:
246             print 'falsely identified.'
247             return self._ebConnected(Failure(Exception("username or password incorrect")))
248         print 'Identified!'
249         dl = []
250         for handlerClass, sname, pname in self.services:
251             d = defer.Deferred()
252             dl.append(d)
253             handler = handlerClass(self, sname, pname, chatui, d)
254             ident.callRemote('attach', sname, pname, handler).addCallback(handler.connected)
255         return defer.DeferredList(dl)
256
257     def _ebConnected(self, error):
258         print 'Not connected.'
259         return error
260
Note: See TracBrowser for help on using the browser.