diff options
Diffstat (limited to 'nbxmpp')
-rw-r--r-- | nbxmpp/dispatcher.py | 2 | ||||
-rw-r--r-- | nbxmpp/modules/discovery.py | 89 | ||||
-rw-r--r-- | nbxmpp/structs.py | 9 |
3 files changed, 99 insertions, 1 deletions
diff --git a/nbxmpp/dispatcher.py b/nbxmpp/dispatcher.py index bf42db3..6828d59 100644 --- a/nbxmpp/dispatcher.py +++ b/nbxmpp/dispatcher.py @@ -69,6 +69,7 @@ from nbxmpp.modules.muclumbus import Muclumbus from nbxmpp.modules.software_version import SoftwareVersion from nbxmpp.modules.adhoc import AdHoc from nbxmpp.modules.ibb import IBB +from nbxmpp.modules.discovery import Discovery from nbxmpp.modules.misc import unwrap_carbon from nbxmpp.modules.misc import unwrap_mam from nbxmpp.util import get_properties_struct @@ -206,6 +207,7 @@ class XMPPDispatcher(PlugIn): self._modules['SoftwareVersion'] = SoftwareVersion(self._owner) self._modules['AdHoc'] = AdHoc(self._owner) self._modules['IBB'] = IBB(self._owner) + self._modules['Discovery'] = Discovery(self._owner) for instance in self._modules.values(): for handler in instance.handlers: diff --git a/nbxmpp/modules/discovery.py b/nbxmpp/modules/discovery.py index 6e8ec24..8a775c6 100644 --- a/nbxmpp/modules/discovery.py +++ b/nbxmpp/modules/discovery.py @@ -18,13 +18,100 @@ import logging from nbxmpp.protocol import Iq +from nbxmpp.protocol import NS_DISCO_INFO +from nbxmpp.protocol import NS_DISCO_ITEMS +from nbxmpp.protocol import NS_DATA +from nbxmpp.protocol import isResultNode +from nbxmpp.modules.dataforms import extend_form +from nbxmpp.structs import DiscoIdentity +from nbxmpp.structs import DiscoInfo +from nbxmpp.structs import DiscoItems +from nbxmpp.structs import DiscoItem +from nbxmpp.util import call_on_response +from nbxmpp.util import callback +from nbxmpp.util import raise_error log = logging.getLogger('nbxmpp.m.discovery') +class Discovery: + def __init__(self, client): + self._client = client + self.handlers = [] + + @call_on_response('_disco_info_received') + def disco_info(self, jid, node=None): + log.info('Disco info: %s, node: %s', jid, node) + return get_disco_request(NS_DISCO_INFO, jid, node) + + @callback + def _disco_info_received(self, stanza): + if not isResultNode(stanza): + return raise_error(log.info, stanza) + + idenities = [] + features = [] + dataforms = [] + + query = stanza.getQuery() + for node in query.getTags('identity'): + attrs = node.getAttrs() + try: + idenities.append( + DiscoIdentity(category=attrs['category'], + type=attrs['type'], + name=attrs.get('name'), + lang=attrs.get('xml:lang'))) + except Exception: + return raise_error(log.warning, stanza, 'stanza-malformed') + + for node in query.getTags('feature'): + try: + features.append(node.getAttr('var')) + except Exception: + return raise_error(log.warning, stanza, 'stanza-malformed') + + for node in query.getTags('x', namespace=NS_DATA): + dataforms.append(extend_form(node)) + + return DiscoInfo(jid=stanza.getFrom(), + node=query.getAttr('node'), + identities=idenities, + features=features, + dataforms=dataforms) + + @call_on_response('_disco_items_received') + def disco_items(self, jid, node=None): + log.info('Disco items: %s, node: %s', jid, node) + return get_disco_request(NS_DISCO_ITEMS, jid, node) + + @callback + def _disco_items_received(self, stanza): + if not isResultNode(stanza): + return raise_error(log.info, stanza) + + items = [] + + query = stanza.getQuery() + for node in query.getTags('item'): + attrs = node.getAttrs() + try: + items.append( + DiscoItem(jid=attrs['jid'], + name=attrs.get('name'), + node=attrs.get('node'))) + except Exception: + return raise_error(log.warning, stanza, 'stanza-malformed') + + return DiscoItems(jid=stanza.getFrom(), + node=query.getAttr('node'), + items=items) + + + def get_disco_request(namespace, jid, node=None): iq = Iq('get', to=jid, queryNS=namespace) - if node is not None: + if node: iq.getQuery().setAttr('node', node) return iq diff --git a/nbxmpp/structs.py b/nbxmpp/structs.py index dd2dcc7..c33f422 100644 --- a/nbxmpp/structs.py +++ b/nbxmpp/structs.py @@ -112,6 +112,15 @@ AdHocCommandNote = namedtuple('AdHocCommandNote', 'text type') IBBData = namedtuple('IBBData', 'block_size sid seq type data') IBBData.__new__.__defaults__ = (None, None, None, None, None) +DiscoInfo = namedtuple('DiscoInfo', 'jid node identities features dataforms') +DiscoIdentity = namedtuple('DiscoIdentity', 'category type name lang') +DiscoIdentity.__new__.__defaults__ = (None, None) + +DiscoItems = namedtuple('DiscoItems', 'jid node items') +DiscoItem = namedtuple('DiscoItem', 'jid name node') +DiscoItem.__new__.__defaults__ = (None, None) + + class AdHocCommand(namedtuple('AdHocCommand', 'jid node name sessionid status data actions notes')): __slots__ = [] |