Mercurial > libervia-backend
comparison src/core/xmpp.py @ 466:448ce3c9e2ac
core: Roster cache refactoring: cache is now managed by client's SatRosterProtocol instance.
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 26 Mar 2012 00:22:49 +0200 |
parents | 4e361d295bca |
children | 47af60767013 |
comparison
equal
deleted
inserted
replaced
465:78e67a59d51d | 466:448ce3c9e2ac |
---|---|
118 class SatRosterProtocol(xmppim.RosterClientProtocol): | 118 class SatRosterProtocol(xmppim.RosterClientProtocol): |
119 | 119 |
120 def __init__(self, host): | 120 def __init__(self, host): |
121 xmppim.RosterClientProtocol.__init__(self) | 121 xmppim.RosterClientProtocol.__init__(self) |
122 self.host = host | 122 self.host = host |
123 self._groups=set() | 123 #XXX: the two following dicts keep a local copy of the roster |
124 self._groups = {} #map from groups to bare jids: key=group value=set of bare jids | |
125 self._jids = {} #map from bare jids to RosterItem: key=jid value=RosterItem | |
124 | 126 |
125 def rosterCb(self, roster): | 127 def rosterCb(self, roster): |
126 for raw_jid, item in roster.iteritems(): | 128 for raw_jid, item in roster.iteritems(): |
127 self.onRosterSet(item) | 129 self.onRosterSet(item) |
128 | 130 |
155 if roster_item.name: | 157 if roster_item.name: |
156 item['name'] = roster_item.name | 158 item['name'] = roster_item.name |
157 for group in roster_item.groups: | 159 for group in roster_item.groups: |
158 item.addElement('group', content=group) | 160 item.addElement('group', content=group) |
159 return iq.send() | 161 return iq.send() |
162 | |
163 def getAttributes(self, item): | |
164 """Return dictionary of attributes as used in bridge from a RosterItem | |
165 @param item: RosterItem | |
166 @return: dictionary of attributes""" | |
167 item_attr = {'to': str(item.subscriptionTo), | |
168 'from': str(item.subscriptionFrom), | |
169 'ask': str(item.ask) | |
170 } | |
171 if item.name: | |
172 item_attr['name'] = item.name | |
173 return item_attr | |
160 | 174 |
161 def onRosterSet(self, item): | 175 def onRosterSet(self, item): |
162 """Called when a new/update roster item is received""" | 176 """Called when a new/update roster item is received""" |
163 #TODO: send a signal to frontends | 177 #TODO: send a signal to frontends |
164 if not item.subscriptionTo and not item.subscriptionFrom and not item.ask: | 178 if not item.subscriptionTo and not item.subscriptionFrom and not item.ask: |
165 #XXX: current behaviour: we don't want contact in our roster list | 179 #XXX: current behaviour: we don't want contact in our roster list |
166 #if there is no presence subscription | 180 #if there is no presence subscription |
167 #may change in the future | 181 #may change in the future |
168 self.removeItem(item.jid) | 182 self.removeItem(item.jid) |
169 return | 183 return |
170 item_attr = {'to': str(item.subscriptionTo), | |
171 'from': str(item.subscriptionFrom), | |
172 'ask': str(item.ask) | |
173 } | |
174 if item.name: | |
175 item_attr['name'] = item.name | |
176 info (_("new contact in roster list: %s"), item.jid.full()) | 184 info (_("new contact in roster list: %s"), item.jid.full()) |
177 self.host.memory.addContact(item.jid, item_attr, item.groups, self.parent.profile) | 185 #self.host.memory.addContact(item.jid, item_attr, item.groups, self.parent.profile) |
178 self.host.bridge.newContact(item.jid.full(), item_attr, item.groups, self.parent.profile) | 186 |
179 self._groups.update(item.groups) | 187 bare_jid = item.jid.userhost() |
188 self._jids[bare_jid] = item | |
189 for group in item.groups: | |
190 self._groups.get(group,set()).add(bare_jid) | |
191 self.host.bridge.newContact(item.jid.full(), self.getAttributes(item), item.groups, self.parent.profile) | |
180 | 192 |
181 def onRosterRemove(self, entity): | 193 def onRosterRemove(self, entity): |
182 """Called when a roster removal event is received""" | 194 """Called when a roster removal event is received""" |
183 print _("removing %s from roster list") % entity.full() | 195 print _("removing %s from roster list") % entity.full() |
184 self.host.memory.delContact(entity, self.parent.profile) | 196 bare_jid = entity.userhost() |
197 | |
198 #we first remove item from local cache (self._groups and self._jids) | |
199 try: | |
200 item = self._jids.pop(bare_jid) | |
201 except KeyError: | |
202 log.warning("Received a roster remove event for an item not in cache") | |
203 return | |
204 for group in item.groups: | |
205 try: | |
206 jids_set = self._groups[group] | |
207 jids_set.remove(bare_jid) | |
208 if not jids_set: | |
209 del self._groups[group] | |
210 except KeyError: | |
211 log.warning("there is not cache for the group [%(groups)s] of the removed roster item [%(jid)s]" % | |
212 {"group": group, "jid": bare_jid}) | |
213 | |
214 #then we send the bridge signal | |
185 self.host.bridge.contactDeleted(entity.userhost(), self.parent.profile) | 215 self.host.bridge.contactDeleted(entity.userhost(), self.parent.profile) |
186 | 216 |
187 def getGroups(self): | 217 def getGroups(self): |
188 """Return a set of groups""" | 218 """Return a list of groups""" |
189 return self._groups | 219 return self._groups.keys() |
220 | |
221 def getItem(self, jid): | |
222 """Return RosterItem for a given jid | |
223 @param jid: jid of the contact | |
224 @return: RosterItem or None if contact is not in cache""" | |
225 return self._jids.get(jid.userhost(), None) | |
226 | |
227 def getItems(self): | |
228 """Return all items of the roster""" | |
229 return self._jids | |
230 | |
190 | 231 |
191 class SatPresenceProtocol(xmppim.PresenceClientProtocol): | 232 class SatPresenceProtocol(xmppim.PresenceClientProtocol): |
192 | 233 |
193 def __init__(self, host): | 234 def __init__(self, host): |
194 xmppim.PresenceClientProtocol.__init__(self) | 235 xmppim.PresenceClientProtocol.__init__(self) |
241 del statuses[None] | 282 del statuses[None] |
242 | 283 |
243 def subscribed(self, entity): | 284 def subscribed(self, entity): |
244 xmppim.PresenceClientProtocol.subscribed(self, entity) | 285 xmppim.PresenceClientProtocol.subscribed(self, entity) |
245 self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile) | 286 self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile) |
246 contact = self.host.memory.getContact(entity, self.parent.profile) | 287 item = self.parent.roster.getItem(entity) |
247 if not contact or contact[0]['to'] == 'False': #we automatically subscribe to 'to' presence | 288 if not item or not item.subscriptionTo: #we automatically subscribe to 'to' presence |
248 debug(_('sending automatic "from" subscription request')) | 289 debug(_('sending automatic "from" subscription request')) |
249 self.subscribe(entity) | 290 self.subscribe(entity) |
250 | 291 |
251 def unsubscribed(self, entity): | 292 def unsubscribed(self, entity): |
252 xmppim.PresenceClientProtocol.unsubscribed(self, entity) | 293 xmppim.PresenceClientProtocol.unsubscribed(self, entity) |
260 debug (_("unsubscription confirmed for [%s]") % entity.userhost()) | 301 debug (_("unsubscription confirmed for [%s]") % entity.userhost()) |
261 self.host.bridge.subscribe('unsubscribed', entity.userhost(), self.parent.profile) | 302 self.host.bridge.subscribe('unsubscribed', entity.userhost(), self.parent.profile) |
262 | 303 |
263 def subscribeReceived(self, entity): | 304 def subscribeReceived(self, entity): |
264 debug (_("subscription request from [%s]") % entity.userhost()) | 305 debug (_("subscription request from [%s]") % entity.userhost()) |
265 contact = self.host.memory.getContact(entity, self.parent.profile) | 306 item = self.parent.roster.getItem(entity) |
266 if contact and contact[0]['to'] == 'True': | 307 if item and item.subscriptionTo: |
267 #We automatically accept subscription if we are already subscribed to contact presence | 308 #We automatically accept subscription if we are already subscribed to contact presence |
268 debug(_('sending automatic subscription acceptance')) | 309 debug(_('sending automatic subscription acceptance')) |
269 self.subscribed(entity) | 310 self.subscribed(entity) |
270 else: | 311 else: |
271 self.host.memory.addWaitingSub('subscribe', entity.userhost(), self.parent.profile) | 312 self.host.memory.addWaitingSub('subscribe', entity.userhost(), self.parent.profile) |
272 self.host.bridge.subscribe('subscribe', entity.userhost(), self.parent.profile) | 313 self.host.bridge.subscribe('subscribe', entity.userhost(), self.parent.profile) |
273 | 314 |
274 def unsubscribeReceived(self, entity): | 315 def unsubscribeReceived(self, entity): |
275 debug (_("unsubscription asked for [%s]") % entity.userhost()) | 316 debug (_("unsubscription asked for [%s]") % entity.userhost()) |
276 contact = self.host.memory.getContact(entity, self.parent.profile) | 317 item = self.parent.roster.getItem(entity) |
277 if contact and contact[0]['from'] == 'True': #we automatically remove contact | 318 if item and item.subscriptionFrom: #we automatically remove contact |
278 debug(_('automatic contact deletion')) | 319 debug(_('automatic contact deletion')) |
279 self.host.delContact(entity.userhost(), self.parent.profile) | 320 self.host.delContact(entity.userhost(), self.parent.profile) |
280 self.host.bridge.subscribe('unsubscribe', entity.userhost(), self.parent.profile) | 321 self.host.bridge.subscribe('unsubscribe', entity.userhost(), self.parent.profile) |
281 | 322 |
282 class SatDiscoProtocol(disco.DiscoClientProtocol): | 323 class SatDiscoProtocol(disco.DiscoClientProtocol): |