Commit 7d1b7f39 authored by Philipp Hörist's avatar Philipp Hörist

Add Muclumbus API module

parent 8f08104b
......@@ -290,6 +290,12 @@ class BookmarkStoreType(Enum):
PRIVATE = 'private'
class AnonymityMode(Enum):
UNKNOWN = None
SEMI = 'semi'
NONE = 'none'
MOODS = [
'afraid',
'amazed',
......
......@@ -66,6 +66,7 @@ from nbxmpp.modules.bookmarks import Bookmarks
from nbxmpp.modules.openpgp import OpenPGP
from nbxmpp.modules.omemo import OMEMO
from nbxmpp.modules.annotations import Annotations
from nbxmpp.modules.muclumbus import Muclumbus
from nbxmpp.modules.misc import unwrap_carbon
from nbxmpp.modules.misc import unwrap_mam
from nbxmpp.util import get_properties_struct
......@@ -199,6 +200,7 @@ class XMPPDispatcher(PlugIn):
self._modules['OpenPGP'] = OpenPGP(self._owner)
self._modules['OMEMO'] = OMEMO(self._owner)
self._modules['Annotations'] = Annotations(self._owner)
self._modules['Muclumbus'] = Muclumbus(self._owner)
for instance in self._modules.values():
for handler in instance.handlers:
......
# Copyright (C) 2019 Philipp Hörist <philipp AT hoerist.com>
#
# This file is part of nbxmpp.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; If not, see <http://www.gnu.org/licenses/>.
import logging
from nbxmpp.protocol import NS_MUCLUMBUS
from nbxmpp.protocol import NS_DATA
from nbxmpp.protocol import NS_RSM
from nbxmpp.protocol import Node
from nbxmpp.protocol import Iq
from nbxmpp.protocol import isResultNode
from nbxmpp.structs import MuclumbusItem
from nbxmpp.structs import MuclumbusResult
from nbxmpp.const import AnonymityMode
from nbxmpp.modules.dataforms import extend_form
from nbxmpp.util import call_on_response
from nbxmpp.util import callback
from nbxmpp.util import raise_error
log = logging.getLogger('nbxmpp.m.muclumbus')
# API Documentation
# https://search.jabber.network/docs/api
class Muclumbus:
def __init__(self, client):
self._client = client
self.handlers = []
@call_on_response('_parameters_received')
def request_parameters(self, jid):
query = Iq(to=jid, typ='get')
query.addChild(node=Node('search', attrs={'xmlns': NS_MUCLUMBUS}))
return query
@callback
def _parameters_received(self, stanza):
if not isResultNode(stanza):
return raise_error(log.info, stanza)
search = stanza.getTag('search', namespace=NS_MUCLUMBUS)
if search is None:
return raise_error(log.warning, stanza, 'stanza-malformed')
dataform = search.getTag('x', namespace=NS_DATA)
if dataform is None:
return raise_error(log.warning, stanza, 'stanza-malformed')
log.info('Muclumbus parameters received')
return extend_form(node=dataform)
@call_on_response('_search_received')
def set_search(self, jid, dataform, items_per_page=50, after=None):
search = Node('search', attrs={'xmlns': NS_MUCLUMBUS})
search.addChild(node=dataform)
rsm = search.addChild('set', namespace=NS_RSM)
rsm.addChild('max').setData(items_per_page)
if after is not None:
rsm.addChild('after').setData(after)
query = Iq(to=jid, typ='get')
query.addChild(node=search)
return query
@callback
def _search_received(self, stanza):
if not isResultNode(stanza):
return raise_error(log.info, stanza)
result = stanza.getTag('result', namespace=NS_MUCLUMBUS)
if result is None:
return raise_error(log.warning, stanza, 'stanza-malformed')
items = result.getTags('item')
if not items:
return MuclumbusResult(first=None,
last=None,
max=None,
end=True,
items=[])
set_ = result.getTag('set', namespace=NS_RSM)
if set_ is None:
return raise_error(log.warning, stanza, 'stanza-malformed')
first = set_.getTagData('first')
last = set_.getTagData('last')
try:
max_ = int(set_.getTagData('max'))
except Exception:
return raise_error(log.warning, stanza, 'stanza-malformed')
results = []
for item in items:
jid = item.getAttr('address')
name = item.getTagData('name')
nusers = item.getTagData('nusers')
description = item.getTagData('description')
language = item.getTagData('language')
is_open = item.getTag('is-open') is not None
try:
anonymity_mode = AnonymityMode(item.getTagData('anonymity-mode'))
except ValueError:
anonymity_mode = AnonymityMode.UNKNOWN
results.append(MuclumbusItem(jid=jid,
name=name,
nusers=nusers,
description=description,
language=language,
is_open=is_open,
anonymity_mode=anonymity_mode))
return MuclumbusResult(first=first,
last=last,
max=max_,
end=len(items) < max_,
items=results)
......@@ -196,6 +196,7 @@ NS_OMEMO_TEMP_BUNDLE = 'eu.siacs.conversations.axolotl.bundles'
NS_BOOKMARK_CONVERSION = 'urn:xmpp:bookmarks-conversion:0'
NS_DOMAIN_BASED_NAME = 'urn:xmpp:domain-based-name:1'
NS_HINTS = 'urn:xmpp:hints'
NS_MUCLUMBUS = 'https://xmlns.zombofant.net/muclumbus/search/1.0'
#xmpp_stream_error_conditions = '''
#bad-format -- -- -- The entity has sent XML that cannot be processed.
......
......@@ -100,6 +100,10 @@ AnnotationNote.__new__.__defaults__ = (None, None)
EMEData = namedtuple('EMEData', 'name namespace')
MuclumbusResult = namedtuple('MuclumbusResult', 'first last max end items')
MuclumbusItem = namedtuple('MuclumbusItem', 'jid name nusers description language is_open anonymity_mode')
class OMEMOBundle(namedtuple('OMEMOBundle', 'spk spk_signature ik otpks')):
def pick_prekey(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment