# HG changeset patch # User Goffi # Date 1521884769 -3600 # Node ID 7da86e1633a5e0ccd1178c228678db8aa6d2d0a7 # Parent 8d82a62fa098233497ac2ae4bf0dfa73c53d4502 core: new discoFindFeatures method which return all server services/roster entities implementing a set of features. diff -r 8d82a62fa098 -r 7da86e1633a5 frontends/src/bridge/dbus_bridge.py --- a/frontends/src/bridge/dbus_bridge.py Sat Mar 24 10:44:37 2018 +0100 +++ b/frontends/src/bridge/dbus_bridge.py Sat Mar 24 10:46:09 2018 +0100 @@ -209,6 +209,15 @@ error_handler = lambda err:errback(dbus_to_bridge_exception(err)) return self.db_core_iface.delContact(entity_jid, profile_key, timeout=const_TIMEOUT, reply_handler=callback, error_handler=error_handler) + def discoFindByFeatures(self, namespaces, service=True, roster=True, own_jid=True, profile_key=u"@DEFAULT@", callback=None, errback=None): + if callback is None: + error_handler = None + else: + if errback is None: + errback = log.error + error_handler = lambda err:errback(dbus_to_bridge_exception(err)) + return self.db_core_iface.discoFindByFeatures(namespaces, service, roster, own_jid, profile_key, timeout=const_TIMEOUT, reply_handler=callback, error_handler=error_handler) + def discoInfos(self, entity_jid, node=u'', use_cache=True, profile_key=u"@DEFAULT@", callback=None, errback=None): if callback is None: error_handler = None diff -r 8d82a62fa098 -r 7da86e1633a5 src/bridge/bridge_constructor/bridge_template.ini --- a/src/bridge/bridge_constructor/bridge_template.ini Sat Mar 24 10:44:37 2018 +0100 +++ b/src/bridge/bridge_constructor/bridge_template.ini Sat Mar 24 10:46:09 2018 +0100 @@ -734,6 +734,27 @@ doc_param_3=%(doc_profile_key)s doc_return=array of tuple (entity, node identifier, name) +[discoFindByFeatures] +async= +type=method +category=core +sig_in=asbbbs +sig_out=(a{sa(sss)}a{sa(sss)}a{sa(sss)}) +param_1_default=True +param_2_default=True +param_3_default=True +param_4_default=u"@DEFAULT@" +doc=Discover items of an entity +doc_param_0=namespaces: namespaces of the features to check +doc_param_1=service: True to check server's services +doc_param_2=roster: True to check connected devices from people in roster +doc_param_3=own_jid: True to check profile's jid +doc_param_4=%(doc_profile_key)s +doc_return=tuple of maps of found entities full jids to their identities. Maps are in this order: + - services entities + - own entities (i.e. entities linked to profile's jid) + - roster entities + [saveParamsTemplate] type=method category=core diff -r 8d82a62fa098 -r 7da86e1633a5 src/bridge/dbus_bridge.py --- a/src/bridge/dbus_bridge.py Sat Mar 24 10:44:37 2018 +0100 +++ b/src/bridge/dbus_bridge.py Sat Mar 24 10:46:09 2018 +0100 @@ -234,6 +234,12 @@ return self._callback("delContact", unicode(entity_jid), unicode(profile_key), callback=callback, errback=errback) @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, + in_signature='asbbbs', out_signature='(a{sa(sss)}a{sa(sss)}a{sa(sss)})', + async_callbacks=('callback', 'errback')) + def discoFindByFeatures(self, namespaces, service=True, roster=True, own_jid=True, profile_key=u"@DEFAULT@", callback=None, errback=None): + return self._callback("discoFindByFeatures", namespaces, service, roster, own_jid, unicode(profile_key), callback=callback, errback=errback) + + @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, in_signature='ssbs', out_signature='(asa(sss)a{sa(a{ss}as)})', async_callbacks=('callback', 'errback')) def discoInfos(self, entity_jid, node=u'', use_cache=True, profile_key=u"@DEFAULT@", callback=None, errback=None): diff -r 8d82a62fa098 -r 7da86e1633a5 src/core/sat_main.py --- a/src/core/sat_main.py Sat Mar 24 10:44:37 2018 +0100 +++ b/src/core/sat_main.py Sat Mar 24 10:46:09 2018 +0100 @@ -118,6 +118,7 @@ self.bridge.register_method("menuLaunch", self._launchMenu) self.bridge.register_method("discoInfos", self.memory.disco._discoInfos) self.bridge.register_method("discoItems", self.memory.disco._discoItems) + self.bridge.register_method("discoFindByFeatures", self._findByFeatures) self.bridge.register_method("saveParamsTemplate", self.memory.save_xml) self.bridge.register_method("loadParamsTemplate", self.memory.load_xml) self.bridge.register_method("sessionInfosGet", self.getSessionInfos) @@ -670,6 +671,60 @@ def findFeaturesSet(self, *args, **kwargs): return self.memory.disco.findFeaturesSet(*args, **kwargs) + def _findByFeatures(self, namespace, service, roster, own_jid, profile_key): + client = self.getClient(profile_key) + return self.findByFeatures(client, namespace, service, roster, own_jid) + + @defer.inlineCallbacks + def findByFeatures(self, client, namespaces, service, roster, own_jid): + """retrieve all services or contacts managing a set a features + + @param namespaces(list[unicode]): features which must be handled + @param service(bool): if True return service from our roster + @param roster(bool): if True, return entities in roster + full jid of all matching resources available will be returned + @param own_jid(bool): if True, return profile's jid resources + @return (tuple(dict[jid.JID(), tuple[unicode, unicode, unicode]]*3)): found entities in a tuple with: + - service entities + - own entities + - roster entities + """ + if not namespaces: + raise exceptions.DataError("namespaces must not be empty") + found_service = {} + found_own = {} + found_roster = {} + if service: + services_jids = yield self.findFeaturesSet(client, namespaces) + for service_jid in services_jids: + infos = yield self.getDiscoInfos(client, service_jid) + identities = [(cat, type_, name or u'') for (cat, type_), name in infos.identities.iteritems()] + found_service[service_jid.full()] = identities + + jids = [] + if roster: + jids.extend(client.roster.getJids()) + if own_jid: + jids.append(client.jid.userhostJID()) + + for found, jids in ((found_own, [client.jid.userhostJID()]), + (found_roster, client.roster.getJids())): + for jid_ in jids: + if jid_.resource: + resources = [jid_.resource] + else: + try: + resources = self.memory.getAllResources(client, jid_) + except exceptions.UnknownEntityError: + continue + for resource in resources: + full_jid = jid.JID(tuple=(jid_.user, jid_.host, resource)) + infos = yield self.getDiscoInfos(client, full_jid) + if infos.features.issuperset(namespaces): + identities = [(cat, type_, name or u'') for (cat, type_), name in infos.identities.iteritems()] + found[full_jid.full()] = identities + + defer.returnValue((found_service, found_own, found_roster)) ## Generic HMI ##