core: new discoFindFeatures method which return all server services/roster entities implementing a set of features.

This commit is contained in:
Goffi 2018-03-24 10:46:09 +01:00
commit b9e3707412
4 changed files with 91 additions and 0 deletions

View file

@ -209,6 +209,15 @@ class Bridge(object):
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

View file

@ -734,6 +734,27 @@ doc_param_2=use_cache: use cached data if available
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

View file

@ -233,6 +233,12 @@ class DbusObject(dbus.service.Object):
def delContact(self, entity_jid, profile_key="@DEFAULT@", callback=None, errback=None):
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'))

View file

@ -118,6 +118,7 @@ class SAT(service.Service):
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 @@ class SAT(service.Service):
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 ##