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

Commits:

4 changed files:

Changes:

  • nbxmpp/dispatcher_nb.py
    ... ... @@ -56,6 +56,7 @@ from nbxmpp.modules.vcard_avatar import VCardAvatar
    56 56
     from nbxmpp.modules.captcha import Captcha
    
    57 57
     from nbxmpp.modules.entity_caps import EntityCaps
    
    58 58
     from nbxmpp.modules.blocking import Blocking
    
    59
    +from nbxmpp.modules.pubsub import PubSub
    
    59 60
     from nbxmpp.modules.misc import unwrap_carbon
    
    60 61
     from nbxmpp.modules.misc import unwrap_mam
    
    61 62
     from nbxmpp.util import get_properties_struct
    
    ... ... @@ -179,6 +180,7 @@ class XMPPDispatcher(PlugIn):
    179 180
             self._modules['VCardAvatar'] = VCardAvatar(self._owner)
    
    180 181
             self._modules['EntityCaps'] = EntityCaps(self._owner)
    
    181 182
             self._modules['Blocking'] = Blocking(self._owner)
    
    183
    +        self._modules['PubSub'] = PubSub(self._owner)
    
    182 184
     
    
    183 185
             for instance in self._modules.values():
    
    184 186
                 for handler in instance.handlers:
    

  • nbxmpp/modules/nickname.py
    ... ... @@ -18,6 +18,8 @@
    18 18
     import logging
    
    19 19
     
    
    20 20
     from nbxmpp.protocol import NS_NICK
    
    21
    +from nbxmpp.protocol import NS_PUBSUB_EVENT
    
    22
    +from nbxmpp.protocol import Node
    
    21 23
     from nbxmpp.structs import StanzaHandler
    
    22 24
     from nbxmpp.const import PresenceType
    
    23 25
     
    
    ... ... @@ -28,6 +30,10 @@ class Nickname:
    28 30
         def __init__(self, client):
    
    29 31
             self._client = client
    
    30 32
             self.handlers = [
    
    33
    +            StanzaHandler(name='message',
    
    34
    +                          callback=self._process_pubsub_nickname,
    
    35
    +                          ns=NS_PUBSUB_EVENT,
    
    36
    +                          priority=16),
    
    31 37
                 StanzaHandler(name='message',
    
    32 38
                               callback=self._process_nickname,
    
    33 39
                               ns=NS_NICK,
    
    ... ... @@ -51,9 +57,29 @@ class Nickname:
    51 57
                     return
    
    52 58
                 properties.nickname = self._parse_nickname(stanza)
    
    53 59
     
    
    60
    +    def _process_pubsub_nickname(self, _con, _stanza, properties):
    
    61
    +        if not properties.is_pubsub_event:
    
    62
    +            return
    
    63
    +
    
    64
    +        if properties.pubsub_event.node != NS_NICK:
    
    65
    +            return
    
    66
    +
    
    67
    +        nick = self._parse_nickname(properties.pubsub_event.item)
    
    68
    +        log.info('Received nickname: %s - %s', properties.jid, nick)
    
    69
    +
    
    70
    +        properties.pubsub_event = properties.pubsub_event._replace(data=nick)
    
    71
    +
    
    54 72
         @staticmethod
    
    55 73
         def _parse_nickname(stanza):
    
    56 74
             nickname = stanza.getTag('nick', namespace=NS_NICK)
    
    57 75
             if nickname is None:
    
    58 76
                 return
    
    59 77
             return nickname.getData() or None
    
    78
    +
    
    79
    +    def set_nickname(self, nickname):
    
    80
    +        item = Node('nick', {'xmlns': NS_NICK})
    
    81
    +        if nickname is not None:
    
    82
    +            item.addData(nickname)
    
    83
    +        jid = self._client.get_bound_jid().getBare()
    
    84
    +        self._client.get_module('PubSub').publish(
    
    85
    +            jid, NS_NICK, item, id_='current')

  • nbxmpp/modules/pubsub.py
    1
    +# Copyright (C) 2018 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_PUBSUB
    
    21
    +from nbxmpp.protocol import NS_PUBSUB_EVENT
    
    22
    +from nbxmpp.protocol import Iq
    
    23
    +from nbxmpp.protocol import isResultNode
    
    24
    +from nbxmpp.structs import StanzaHandler
    
    25
    +from nbxmpp.structs import PubSubEventData
    
    26
    +from nbxmpp.structs import CommonResult
    
    27
    +from nbxmpp.util import call_on_response
    
    28
    +from nbxmpp.util import callback
    
    29
    +
    
    30
    +
    
    31
    +log = logging.getLogger('nbxmpp.m.pubsub')
    
    32
    +
    
    33
    +
    
    34
    +class PubSub:
    
    35
    +    def __init__(self, client):
    
    36
    +        self._client = client
    
    37
    +        self.handlers = [
    
    38
    +            StanzaHandler(name='message',
    
    39
    +                          callback=self._process_pubsub_base,
    
    40
    +                          ns=NS_PUBSUB_EVENT,
    
    41
    +                          priority=15),
    
    42
    +        ]
    
    43
    +
    
    44
    +    def _process_pubsub_base(self, _con, stanza, properties):
    
    45
    +        event = stanza.getTag('event', namespace=NS_PUBSUB_EVENT)
    
    46
    +        items = event.getTag('items')
    
    47
    +        if len(items.getChildren()) != 1:
    
    48
    +            log.warning('PubSub event with more than one item')
    
    49
    +            log.warning(stanza)
    
    50
    +        node = items.getAttr('node')
    
    51
    +        item = items.getTag('item')
    
    52
    +        id_ = item.getAttr('id')
    
    53
    +        properties.pubsub_event = PubSubEventData(node, id_, item, None)
    
    54
    +
    
    55
    +    @call_on_response('_default_response')
    
    56
    +    def publish(self, jid, node, item, id_=None, options=None):
    
    57
    +        query = Iq('set', to=jid)
    
    58
    +        pubsub = query.addChild('pubsub', namespace=NS_PUBSUB)
    
    59
    +        publish = pubsub.addChild('publish', {'node': node})
    
    60
    +        attrs = {}
    
    61
    +        if id_ is not None:
    
    62
    +            attrs = {'id': id_}
    
    63
    +        publish.addChild('item', attrs, [item])
    
    64
    +        if options:
    
    65
    +            publish = pubsub.addChild('publish-options')
    
    66
    +            publish.addChild(node=options)
    
    67
    +        return query
    
    68
    +
    
    69
    +    @callback
    
    70
    +    def _default_response(self, stanza):
    
    71
    +        if not isResultNode(stanza):
    
    72
    +            log.info('Error: %s', stanza.getError())
    
    73
    +            return CommonResult(jid=stanza.getFrom(),
    
    74
    +                                error=stanza.getError())
    
    75
    +        return CommonResult(jid=stanza.getFrom())

  • nbxmpp/structs.py
    ... ... @@ -58,6 +58,8 @@ HTTPAuthData.__new__.__defaults__ = (None, None, None, None)
    58 58
     StanzaIDData = namedtuple('StanzaIDData', 'id by')
    
    59 59
     StanzaIDData.__new__.__defaults__ = (None, None)
    
    60 60
     
    
    61
    +PubSubEventData = namedtuple('PubSubEventData', 'node id item data')
    
    62
    +
    
    61 63
     
    
    62 64
     class MAMData(namedtuple('MAMData', 'id query_id archive namespace timestamp')):
    
    63 65
     
    
    ... ... @@ -103,6 +105,11 @@ class MessageProperties:
    103 105
             self.voice_request = None
    
    104 106
             self.self_message = False
    
    105 107
             self.mam = None
    
    108
    +        self.pubsub_event = None
    
    109
    +
    
    110
    +    @property
    
    111
    +    def is_pubsub_event(self):
    
    112
    +        return self.pubsub_event is not None
    
    106 113
     
    
    107 114
         @property
    
    108 115
         def is_mam_message(self):