Philipp Hörist pushed to branch master at gajim / python-nbxmpp

Commits:

4 changed files:

Changes:

  • nbxmpp/dispatcher.py
    ... ... @@ -66,6 +66,7 @@ from nbxmpp.modules.openpgp import OpenPGP
    66 66
     from nbxmpp.modules.omemo import OMEMO
    
    67 67
     from nbxmpp.modules.annotations import Annotations
    
    68 68
     from nbxmpp.modules.muclumbus import Muclumbus
    
    69
    +from nbxmpp.modules.software_version import SoftwareVersion
    
    69 70
     from nbxmpp.modules.misc import unwrap_carbon
    
    70 71
     from nbxmpp.modules.misc import unwrap_mam
    
    71 72
     from nbxmpp.util import get_properties_struct
    
    ... ... @@ -200,6 +201,7 @@ class XMPPDispatcher(PlugIn):
    200 201
             self._modules['OMEMO'] = OMEMO(self._owner)
    
    201 202
             self._modules['Annotations'] = Annotations(self._owner)
    
    202 203
             self._modules['Muclumbus'] = Muclumbus(self._owner)
    
    204
    +        self._modules['SoftwareVersion'] = SoftwareVersion(self._owner)
    
    203 205
     
    
    204 206
             for instance in self._modules.values():
    
    205 207
                 for handler in instance.handlers:
    

  • nbxmpp/modules/muc.py
    ... ... @@ -82,7 +82,7 @@ class MUC:
    82 82
                               callback=self._process_direct_invite,
    
    83 83
                               typ='normal',
    
    84 84
                               ns=NS_CONFERENCE,
    
    85
    -                          priority=11),
    
    85
    +                          priority=12),
    
    86 86
                 StanzaHandler(name='message',
    
    87 87
                               callback=self._process_voice_request,
    
    88 88
                               ns=NS_DATA,
    
    ... ... @@ -90,7 +90,7 @@ class MUC:
    90 90
                 StanzaHandler(name='message',
    
    91 91
                               callback=self._process_message,
    
    92 92
                               ns=NS_MUC_USER,
    
    93
    -                          priority=12),
    
    93
    +                          priority=13),
    
    94 94
             ]
    
    95 95
     
    
    96 96
         @staticmethod
    
    ... ... @@ -225,15 +225,14 @@ class MUC:
    225 225
             if direct is None:
    
    226 226
                 return
    
    227 227
     
    
    228
    -        muc_jid = direct.getAttr('jid')
    
    229
    -        if muc_jid is None:
    
    230
    -            # Not a direct invite
    
    228
    +        if stanza.getTag('x', namespace=NS_MUC_USER) is not None:
    
    229
    +            # not a direct invite
    
    231 230
                 # See https://xmpp.org/extensions/xep-0045.html#example-57
    
    232 231
                 # read implementation notes
    
    233 232
                 return
    
    234 233
     
    
    235 234
             data = {}
    
    236
    -        data['muc'] = JID(muc_jid)
    
    235
    +        data['muc'] = JID(direct.getAttr('jid'))
    
    237 236
             data['from_'] = properties.jid
    
    238 237
             data['reason'] = direct.getAttr('reason')
    
    239 238
             data['password'] = direct.getAttr('password')
    

  • nbxmpp/modules/software_version.py
    1
    +# Copyright (C) 2019 Philipp Hörist <philipp AT hoerist.com>
    
    2
    +#
    
    3
    +# This file is part of nbxmpp.
    
    4
    +#
    
    5
    +# This program is free software; you can redistribute it and/or
    
    6
    +# modify it under the terms of the GNU General Public License
    
    7
    +# as published by the Free Software Foundation; either version 3
    
    8
    +# of the License, or (at your option) any later version.
    
    9
    +#
    
    10
    +# This program is distributed in the hope that it will be useful,
    
    11
    +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    
    12
    +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    
    13
    +# GNU General Public License for more details.
    
    14
    +#
    
    15
    +# You should have received a copy of the GNU General Public License
    
    16
    +# along with this program; If not, see <http://www.gnu.org/licenses/>.
    
    17
    +
    
    18
    +import logging
    
    19
    +
    
    20
    +from nbxmpp.protocol import NS_VERSION
    
    21
    +from nbxmpp.protocol import Iq
    
    22
    +from nbxmpp.protocol import isResultNode
    
    23
    +from nbxmpp.protocol import ErrorNode
    
    24
    +from nbxmpp.protocol import NodeProcessed
    
    25
    +from nbxmpp.protocol import ERR_SERVICE_UNAVAILABLE
    
    26
    +from nbxmpp.structs import SoftwareVersionResult
    
    27
    +from nbxmpp.structs import StanzaHandler
    
    28
    +from nbxmpp.util import call_on_response
    
    29
    +from nbxmpp.util import callback
    
    30
    +from nbxmpp.util import raise_error
    
    31
    +
    
    32
    +log = logging.getLogger('nbxmpp.m.software_version')
    
    33
    +
    
    34
    +
    
    35
    +class SoftwareVersion:
    
    36
    +    def __init__(self, client):
    
    37
    +        self._client = client
    
    38
    +        self.handlers = [
    
    39
    +            StanzaHandler(name='iq',
    
    40
    +                          callback=self._answer_request,
    
    41
    +                          typ='get',
    
    42
    +                          ns=NS_VERSION),
    
    43
    +        ]
    
    44
    +
    
    45
    +        self._name = None
    
    46
    +        self._version = None
    
    47
    +        self._os = None
    
    48
    +
    
    49
    +        self._enabled = False
    
    50
    +
    
    51
    +    def disable(self):
    
    52
    +        self._enabled = False
    
    53
    +
    
    54
    +    @call_on_response('_software_version_received')
    
    55
    +    def request_software_version(self, jid):
    
    56
    +        log.info('Request software version for %s', jid)
    
    57
    +        return Iq(typ='get', to=jid, queryNS=NS_VERSION)
    
    58
    +
    
    59
    +    @callback
    
    60
    +    def _software_version_received(self, stanza):
    
    61
    +        if not isResultNode(stanza):
    
    62
    +            return raise_error(log.info, stanza)
    
    63
    +
    
    64
    +        try:
    
    65
    +            return SoftwareVersionResult(*self._parse_info(stanza))
    
    66
    +        except Exception as error:
    
    67
    +            log.warning(error)
    
    68
    +            return raise_error(log.warning, stanza, 'stanza-malformed')
    
    69
    +
    
    70
    +    @staticmethod
    
    71
    +    def _parse_info(stanza):
    
    72
    +        name = stanza.getQueryChild('name').getData()
    
    73
    +        version = stanza.getQueryChild('version').getData()
    
    74
    +
    
    75
    +        os_info = stanza.getQueryChild('os')
    
    76
    +        if os_info is not None:
    
    77
    +            os_info = os_info.getData()
    
    78
    +
    
    79
    +        return name, version, os_info
    
    80
    +
    
    81
    +    def set_software_version(self, name, version, os=None):
    
    82
    +        self._name, self._version, self._os = name, version, os
    
    83
    +        self._enabled = True
    
    84
    +
    
    85
    +    def _answer_request(self, _con, stanza, _properties):
    
    86
    +        log.info('Request received from %s', stanza.getFrom())
    
    87
    +        if (not self._enabled or
    
    88
    +                self._name is None or
    
    89
    +                self._version is None):
    
    90
    +            iq = stanza.buildReply('error')
    
    91
    +            iq.addChild(node=ErrorNode(ERR_SERVICE_UNAVAILABLE))
    
    92
    +            log.info('Send service-unavailable')
    
    93
    +
    
    94
    +        else:
    
    95
    +            iq = stanza.buildReply('result')
    
    96
    +            query = iq.getQuery()
    
    97
    +            query.setTagData('name', self._name)
    
    98
    +            query.setTagData('version', self._version)
    
    99
    +            if self._os is not None:
    
    100
    +                query.setTagData('os', self._os)
    
    101
    +            log.info('Send software version: %s %s %s',
    
    102
    +                     self._name, self._version, self._os)
    
    103
    +
    
    104
    +        self._client.send(iq)
    
    105
    +        raise NodeProcessed

  • nbxmpp/structs.py
    ... ... @@ -104,6 +104,8 @@ MuclumbusResult = namedtuple('MuclumbusResult', 'first last max end items')
    104 104
     
    
    105 105
     MuclumbusItem = namedtuple('MuclumbusItem', 'jid name nusers description language is_open anonymity_mode')
    
    106 106
     
    
    107
    +SoftwareVersionResult = namedtuple('SoftwareVersionResult', 'name version os')
    
    108
    +
    
    107 109
     
    
    108 110
     class OMEMOBundle(namedtuple('OMEMOBundle', 'spk spk_signature ik otpks')):
    
    109 111
         def pick_prekey(self):