Mercurial > libervia-backend
diff src/core/xmpp.py @ 1367:f71a0fc26886
merged branch frontends_multi_profiles
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 18 Mar 2015 10:52:28 +0100 |
parents | 56adf73bedeb be3a301540c0 |
children | 069ad98b360d |
line wrap: on
line diff
--- a/src/core/xmpp.py Thu Feb 05 11:59:26 2015 +0100 +++ b/src/core/xmpp.py Wed Mar 18 10:52:28 2015 +0100 @@ -174,14 +174,42 @@ def __init__(self, host): xmppim.RosterClientProtocol.__init__(self) self.host = host - self.got_roster = defer.Deferred() + self.got_roster = defer.Deferred() # called when roster is received and ready #XXX: the two following dicts keep a local copy of the roster - self._groups = {} # map from groups to bare jids: key=group value=set of bare jids - self._jids = {} # map from bare jids to RosterItem: key=jid value=RosterItem + self._groups = {} # map from groups to jids: key=group value=set of jids + self._jids = None # map from jids to RosterItem: key=jid value=RosterItem def rosterCb(self, roster): - for raw_jid, item in roster.iteritems(): - self.onRosterSet(item) + assert roster is not None # FIXME: must be managed with roster versioning + self._jids = roster + for roster_item in roster.itervalues(): + self._registerItem(roster_item) + + def _registerItem(self, item): + """Register item in local cache + + item must be already registered in self._jids before this method is called + @param item (RosterIem): item added + """ + log.debug(u"registering item: {}".format(item.jid.full())) + if item.entity.resource: + log.warning(u"Received a roster item with a resource, this is not common but not restricted by RFC 6121, this case may be not well tested.") + if not item.subscriptionTo and not item.subscriptionFrom and not item.ask: + #XXX: current behaviour: we don't want contact in our roster list + # if there is no presence subscription + # may change in the future + self.removeItem(item.jid) # FIXME: to be checked + return + if not item.subscriptionTo: + if not item.subscriptionFrom: + log.info(_(u"There's no subscription between you and [{}]!").format(item.jid.full())) + else: + log.info(_(u"You are not subscribed to [{}]!").format(item.jid.full())) + if not item.subscriptionFrom: + log.info(_(u"[{}] is not subscribed to you!").format(item.jid.full())) + + for group in item.groups: + self._groups.setdefault(group, set()).add(item.entity) def requestRoster(self): """ ask the server for Roster list """ @@ -192,31 +220,9 @@ def removeItem(self, to_jid): """Remove a contact from roster list @param to_jid: a JID instance - """ - xmppim.RosterClientProtocol.removeItem(self, to_jid) - #TODO: check IQ result - - #XXX: disabled (cf http://wokkel.ik.nu/ticket/56)) - #def addItem(self, to): - #"""Add a contact to roster list""" - #xmppim.RosterClientProtocol.addItem(self, to) - #TODO: check IQ result""" - - def updateItem(self, roster_item): + @return: Deferred """ - Update an item of the contact list. - - @param roster_item: item to update - """ - iq = compat.IQ(self.xmlstream, 'set') - iq.addElement((xmppim.NS_ROSTER, 'query')) - item = iq.query.addElement('item') - item['jid'] = roster_item.jid.userhost() - if roster_item.name: - item['name'] = roster_item.name - for group in roster_item.groups: - item.addElement('group', content=group) - return iq.send() + return xmppim.RosterClientProtocol.removeItem(self, to_jid) def getAttributes(self, item): """Return dictionary of attributes as used in bridge from a RosterItem @@ -230,72 +236,54 @@ item_attr['name'] = item.name return item_attr - def onRosterSet(self, item): - """Called when a new/update roster item is received""" - #TODO: send a signal to frontends - if not item.subscriptionTo and not item.subscriptionFrom and not item.ask: - #XXX: current behaviour: we don't want contact in our roster list - # if there is no presence subscription - # may change in the future - self.removeItem(item.jid) - return - log.debug(_("New contact in roster list: %s") % item.jid.full()) - if not item.subscriptionTo: - if not item.subscriptionFrom: - log.info(_("There's no subscription between you and [%s]!") % item.jid.full()) - else: - log.info(_("You are not subscribed to [%s]!") % item.jid.full()) - if not item.subscriptionFrom: - log.info(_("[%s] is not subscribed to you!") % item.jid.full()) - #self.host.memory.addContact(item.jid, item_attr, item.groups, self.parent.profile) - - bare_jid = item.jid.userhostJID() - self._jids[bare_jid] = item - for group in item.groups: - self._groups.setdefault(group, set()).add(bare_jid) + def setReceived(self, request): + #TODO: implement roster versioning (cf RFC 6121 ยง2.6) + item = request.item + self._jids[item.entity] = item self.host.bridge.newContact(item.jid.full(), self.getAttributes(item), item.groups, self.parent.profile) - def onRosterRemove(self, entity): - """Called when a roster removal event is received""" - print _("removing %s from roster list") % entity.full() - bare_jid = entity.userhostJID() + def removeReceived(self, request): + entity = request.item.entity + log.info(u"removing %s from roster list" % entity.full()) # we first remove item from local cache (self._groups and self._jids) try: - item = self._jids.pop(bare_jid) + item = self._jids.pop(entity) except KeyError: - log.warning("Received a roster remove event for an item not in cache") + log.error("Received a roster remove event for an item not in cache ({})".format(entity)) return for group in item.groups: try: jids_set = self._groups[group] - jids_set.remove(bare_jid) + jids_set.remove(entity) if not jids_set: del self._groups[group] except KeyError: log.warning("there is not cache for the group [%(groups)s] of the removed roster item [%(jid)s]" % - {"group": group, "jid": bare_jid}) + {"group": group, "jid": entity}) # then we send the bridge signal - self.host.bridge.contactDeleted(entity.userhost(), self.parent.profile) + self.host.bridge.contactDeleted(entity.full(), self.parent.profile) def getGroups(self): """Return a list of groups""" return self._groups.keys() - def getItem(self, jid): + def getItem(self, entity_jid): """Return RosterItem for a given jid - @param jid: jid of the contact - @return: RosterItem or None if contact is not in cache""" - return self._jids.get(jid.userhostJID(), None) - def getBareJids(self): - """Return all bare jids (as unicode) of the roster""" + @param entity_jid: jid of the contact + @return: RosterItem or None if contact is not in cache + """ + return self._jids.get(entity_jid, None) + + def getJids(self): + """Return all jids of the roster""" return self._jids.keys() def isJidInRoster(self, entity_jid): """Return True if jid is in roster""" - return entity_jid.userhostJID() in self._jids + return entity_jid in self._jids def getItems(self): """Return all items of the roster""" @@ -305,7 +293,7 @@ try: return self._groups[group] except KeyError: - raise exceptions.UnknownGroupError + raise exceptions.UnknownGroupError(group) class SatPresenceProtocol(xmppim.PresenceClientProtocol): @@ -320,7 +308,7 @@ super(SatPresenceProtocol, self).send(obj) def availableReceived(self, entity, show=None, statuses=None, priority=0): - log.debug(_("presence update for [%(entity)s] (available, show=%(show)s statuses=%(statuses)s priority=%(priority)d)") % {'entity': entity, 'show': show, 'statuses': statuses, 'priority': priority}) + log.debug(_("presence update for [%(entity)s] (available, show=%(show)s statuses=%(statuses)s priority=%(priority)d)") % {'entity': entity, C.PRESENCE_SHOW: show, C.PRESENCE_STATUSES: statuses, C.PRESENCE_PRIORITY: priority}) if not statuses: statuses = {} @@ -333,17 +321,13 @@ int(priority), statuses, self.parent.profile) - # uncomment these two lines if you need the trigger - #if not self.host.trigger.point("presenceReceived", entity, "unavailable", 0, statuses, self.parent.profile): - # return - # now it's time to notify frontends self.host.bridge.presenceUpdate(entity.full(), show or "", int(priority), statuses, self.parent.profile) def unavailableReceived(self, entity, statuses=None): - log.debug(_("presence update for [%(entity)s] (unavailable, statuses=%(statuses)s)") % {'entity': entity, 'statuses': statuses}) + log.debug(_("presence update for [%(entity)s] (unavailable, statuses=%(statuses)s)") % {'entity': entity, C.PRESENCE_STATUSES: statuses}) if not statuses: statuses = {}