core, bridge: new devicesInfosGet method to get infos on known devices of an entity
This commit is contained in:
parent
1883dbd3ab
commit
5a467b15d5
7 changed files with 139 additions and 11 deletions
|
|
@ -56,3 +56,22 @@ example
|
|||
Get session informations::
|
||||
|
||||
$ jp info session
|
||||
|
||||
devices
|
||||
-------
|
||||
|
||||
List known devices for an entity. You'll get resource name, and data such as presence
|
||||
data, and identities (i.e. name and type of the client used).
|
||||
|
||||
If entity's bare jid is not specified, a list of your own devices is returned.
|
||||
|
||||
example
|
||||
-------
|
||||
|
||||
List known devices of Louise::
|
||||
|
||||
$ jp info devices louise@example.org
|
||||
|
||||
Check if we have other devices connected::
|
||||
|
||||
$ jp info devices
|
||||
|
|
|
|||
|
|
@ -944,6 +944,19 @@ doc_return=session informations, with at least the following keys:
|
|||
jid: current full jid
|
||||
started: date of creation of the session (Epoch time)
|
||||
|
||||
[devicesInfosGet]
|
||||
async=
|
||||
type=method
|
||||
category=core
|
||||
sig_in=ss
|
||||
sig_out=s
|
||||
doc=Get various informations on an entity devices
|
||||
doc_param_0=bare_jid: get data on known devices from this entity
|
||||
empty string to get devices of the profile
|
||||
doc_param_1=%(doc_profile_key)s
|
||||
doc_return=list of known devices, where each item is a dict with a least following keys:
|
||||
resource: device resource
|
||||
|
||||
[namespacesGet]
|
||||
type=method
|
||||
category=core
|
||||
|
|
|
|||
|
|
@ -258,6 +258,12 @@ class DbusObject(dbus.service.Object):
|
|||
def delContact(self, entity_jid, profile_key="@DEFAULT@", callback=None, errback=None):
|
||||
return self._callback("delContact", str(entity_jid), str(profile_key), callback=callback, errback=errback)
|
||||
|
||||
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
||||
in_signature='ss', out_signature='s',
|
||||
async_callbacks=('callback', 'errback'))
|
||||
def devicesInfosGet(self, bare_jid, profile_key, callback=None, errback=None):
|
||||
return self._callback("devicesInfosGet", str(bare_jid), str(profile_key), callback=callback, errback=errback)
|
||||
|
||||
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
||||
in_signature='asa(ss)bbbbbs', out_signature='(a{sa(sss)}a{sa(sss)}a{sa(sss)})',
|
||||
async_callbacks=('callback', 'errback'))
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import sys
|
|||
import os.path
|
||||
import uuid
|
||||
import hashlib
|
||||
import copy
|
||||
from pathlib import Path
|
||||
import sat
|
||||
from sat.core.i18n import _, D_, languageSwitch
|
||||
|
|
@ -172,6 +173,7 @@ class SAT(service.Service):
|
|||
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)
|
||||
self.bridge.register_method("devicesInfosGet", self._getDevicesInfos)
|
||||
self.bridge.register_method("namespacesGet", self.getNamespaces)
|
||||
self.bridge.register_method("imageCheck", self._imageCheck)
|
||||
self.bridge.register_method("imageResize", self._imageResize)
|
||||
|
|
@ -676,6 +678,65 @@ class SAT(service.Service):
|
|||
}
|
||||
return defer.succeed(data)
|
||||
|
||||
def _getDevicesInfos(self, bare_jid, profile_key):
|
||||
client = self.getClient(profile_key)
|
||||
if not bare_jid:
|
||||
bare_jid = None
|
||||
d = defer.ensureDeferred(self.getDevicesInfos(client, bare_jid))
|
||||
d.addCallback(lambda data: data_format.serialise(data))
|
||||
return d
|
||||
|
||||
async def getDevicesInfos(self, client, bare_jid=None):
|
||||
"""compile data on an entity devices
|
||||
|
||||
@param bare_jid(jid.JID, None): bare jid of entity to check
|
||||
None to use client own jid
|
||||
@return (list[dict]): list of data, one item per resource.
|
||||
Following keys can be set:
|
||||
- resource(str): resource name
|
||||
"""
|
||||
own_jid = client.jid.userhostJID()
|
||||
if bare_jid is None:
|
||||
bare_jid = own_jid
|
||||
else:
|
||||
bare_jid = jid.JID(bare_jid)
|
||||
resources = self.memory.getAllResources(client, bare_jid)
|
||||
if bare_jid == own_jid:
|
||||
# our own jid is not stored in memory's cache
|
||||
resources.add(client.jid.resource)
|
||||
ret_data = []
|
||||
for resource in resources:
|
||||
res_jid = copy.copy(bare_jid)
|
||||
res_jid.resource = resource
|
||||
cache_data = self.memory.getEntityData(res_jid, profile_key=client.profile)
|
||||
res_data = {
|
||||
"resource": resource,
|
||||
}
|
||||
try:
|
||||
presence = cache_data['presence']
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
res_data['presence'] = {
|
||||
"show": presence.show,
|
||||
"priority": presence.priority,
|
||||
"statuses": presence.statuses,
|
||||
}
|
||||
|
||||
disco = await self.getDiscoInfos(client, res_jid)
|
||||
|
||||
for (category, type_), name in disco.identities.items():
|
||||
identities = res_data.setdefault('identities', [])
|
||||
identities.append({
|
||||
"name": name,
|
||||
"category": category,
|
||||
"type": type_,
|
||||
})
|
||||
|
||||
ret_data.append(res_data)
|
||||
|
||||
return ret_data
|
||||
|
||||
# images
|
||||
|
||||
def _imageCheck(self, path):
|
||||
|
|
|
|||
|
|
@ -17,19 +17,18 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from sat.core.i18n import _
|
||||
|
||||
from sat.core.log import getLogger
|
||||
|
||||
log = getLogger(__name__)
|
||||
|
||||
import os.path
|
||||
import copy
|
||||
from collections import namedtuple
|
||||
import shortuuid
|
||||
import mimetypes
|
||||
import time
|
||||
from uuid import uuid4
|
||||
from collections import namedtuple
|
||||
from twisted.python import failure
|
||||
from twisted.internet import defer, reactor, error
|
||||
from twisted.words.protocols.jabber import jid
|
||||
from sat.core.i18n import _
|
||||
from sat.core.log import getLogger
|
||||
from sat.core import exceptions
|
||||
from sat.core.constants import Const as C
|
||||
from sat.memory.sqlite import SqliteStorage
|
||||
|
|
@ -40,9 +39,9 @@ from sat.memory.crypto import BlockCipher
|
|||
from sat.memory.crypto import PasswordHasher
|
||||
from sat.tools import config as tools_config
|
||||
from sat.tools.common import data_format
|
||||
import shortuuid
|
||||
import mimetypes
|
||||
import time
|
||||
|
||||
|
||||
log = getLogger(__name__)
|
||||
|
||||
|
||||
PresenceTuple = namedtuple("PresenceTuple", ("show", "priority", "statuses"))
|
||||
|
|
@ -690,7 +689,7 @@ class Memory(object):
|
|||
"""Return all resource from jid for which we have had data in this session
|
||||
|
||||
@param entity_jid: bare jid of the entity
|
||||
return (list[unicode]): list of resources
|
||||
return (set[unicode]): set of resources
|
||||
|
||||
@raise exceptions.UnknownEntityError: if entity is not in cache
|
||||
@raise ValueError: entity_jid has a resource
|
||||
|
|
|
|||
|
|
@ -217,6 +217,15 @@ class Bridge:
|
|||
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 devicesInfosGet(self, bare_jid, profile_key, 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 str(self.db_core_iface.devicesInfosGet(bare_jid, profile_key, timeout=const_TIMEOUT, reply_handler=callback, error_handler=error_handler))
|
||||
|
||||
def discoFindByFeatures(self, namespaces, identities, bare_jid=False, service=True, roster=True, own_jid=True, local_device=False, profile_key="@DEFAULT@", callback=None, errback=None):
|
||||
if callback is None:
|
||||
error_handler = None
|
||||
|
|
@ -974,6 +983,14 @@ class AIOBridge(Bridge):
|
|||
self.db_core_iface.delContact(entity_jid, profile_key, timeout=const_TIMEOUT, reply_handler=reply_handler, error_handler=error_handler)
|
||||
return fut
|
||||
|
||||
def devicesInfosGet(self, bare_jid, profile_key):
|
||||
loop = asyncio.get_running_loop()
|
||||
fut = loop.create_future()
|
||||
reply_handler = lambda ret=None: loop.call_soon_threadsafe(fut.set_result, ret)
|
||||
error_handler = lambda err: loop.call_soon_threadsafe(fut.set_exception, dbus_to_bridge_exception(err))
|
||||
self.db_core_iface.devicesInfosGet(bare_jid, profile_key, timeout=const_TIMEOUT, reply_handler=reply_handler, error_handler=error_handler)
|
||||
return fut
|
||||
|
||||
def discoFindByFeatures(self, namespaces, identities, bare_jid=False, service=True, roster=True, own_jid=True, local_device=False, profile_key="@DEFAULT@"):
|
||||
loop = asyncio.get_running_loop()
|
||||
fut = loop.create_future()
|
||||
|
|
|
|||
|
|
@ -199,6 +199,14 @@ class Bridge(object):
|
|||
errback = self._generic_errback
|
||||
d.addErrback(errback)
|
||||
|
||||
def devicesInfosGet(self, bare_jid, profile_key, callback=None, errback=None):
|
||||
d = self.root.callRemote("devicesInfosGet", bare_jid, profile_key)
|
||||
if callback is not None:
|
||||
d.addCallback(callback)
|
||||
if errback is None:
|
||||
errback = self._generic_errback
|
||||
d.addErrback(errback)
|
||||
|
||||
def discoFindByFeatures(self, namespaces, identities, bare_jid=False, service=True, roster=True, own_jid=True, local_device=False, profile_key="@DEFAULT@", callback=None, errback=None):
|
||||
d = self.root.callRemote("discoFindByFeatures", namespaces, identities, bare_jid, service, roster, own_jid, local_device, profile_key)
|
||||
if callback is not None:
|
||||
|
|
@ -711,6 +719,11 @@ class AIOBridge(Bridge):
|
|||
d.addErrback(self._errback)
|
||||
return d.asFuture(asyncio.get_event_loop())
|
||||
|
||||
def devicesInfosGet(self, bare_jid, profile_key):
|
||||
d = self.root.callRemote("devicesInfosGet", bare_jid, profile_key)
|
||||
d.addErrback(self._errback)
|
||||
return d.asFuture(asyncio.get_event_loop())
|
||||
|
||||
def discoFindByFeatures(self, namespaces, identities, bare_jid=False, service=True, roster=True, own_jid=True, local_device=False, profile_key="@DEFAULT@"):
|
||||
d = self.root.callRemote("discoFindByFeatures", namespaces, identities, bare_jid, service, roster, own_jid, local_device, profile_key)
|
||||
d.addErrback(self._errback)
|
||||
|
|
|
|||
Loading…
Reference in a new issue