Philipp Hörist pushed to branch master at gajim / python-nbxmpp
Commits: 8cc2f1d3 by Philipp Hörist at 2019-10-14T15:06:06Z Add xhtml message attribute
- - - - - bae3cfd1 by Philipp Hörist at 2019-10-14T16:20:19Z Add Security Labels (XEP-0258) support
- - - - - 16305759 by Philipp Hörist at 2019-10-14T18:53:27Z Add Chat State Notifications (XEP-0085) support
- - - - - 6705a89b by Philipp Hörist at 2019-10-14T18:53:31Z Attention: Don't parse legacy delay tags
- - - - -
8 changed files:
- nbxmpp/const.py - nbxmpp/dispatcher.py - nbxmpp/modules/attention.py - + nbxmpp/modules/chatstates.py - nbxmpp/modules/message.py - + nbxmpp/modules/security_labels.py - nbxmpp/protocol.py - nbxmpp/structs.py
Changes:
===================================== nbxmpp/const.py ===================================== @@ -545,3 +545,12 @@ TUNE_DATA = [ 'title', 'track', 'uri'] + + +CHATSTATES = [ + 'active', + 'inactive', + 'gone', + 'composing', + 'paused' +] \ No newline at end of file
===================================== nbxmpp/dispatcher.py ===================================== @@ -76,6 +76,8 @@ from nbxmpp.modules.receipts import Receipts from nbxmpp.modules.oob import OOB from nbxmpp.modules.correction import Correction from nbxmpp.modules.attention import Attention +from nbxmpp.modules.security_labels import SecurityLabels +from nbxmpp.modules.chatstates import Chatstates from nbxmpp.modules.misc import unwrap_carbon from nbxmpp.modules.misc import unwrap_mam from nbxmpp.util import get_properties_struct @@ -219,6 +221,8 @@ class XMPPDispatcher(PlugIn): self._modules['OOB'] = OOB(self._owner) self._modules['Correction'] = Correction(self._owner) self._modules['Attention'] = Attention(self._owner) + self._modules['SecurityLabels'] = SecurityLabels(self._owner) + self._modules['Chatstates'] = Chatstates(self._owner)
for instance in self._modules.values(): for handler in instance.handlers:
===================================== nbxmpp/modules/attention.py ===================================== @@ -45,7 +45,7 @@ class Attention: if properties.is_carbon_message and properties.carbon.is_sent: return
- if stanza.getTag('x', namespace=NS_DELAY2) is not None: + if stanza.getTag('delay', namespace=NS_DELAY2) is not None: return
properties.attention = True
===================================== nbxmpp/modules/chatstates.py ===================================== @@ -0,0 +1,62 @@ +# Copyright (C) 2018 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_CHATSTATES +from nbxmpp.protocol import NS_DELAY2 +from nbxmpp.structs import StanzaHandler +from nbxmpp.const import CHATSTATES + +log = logging.getLogger('nbxmpp.m.chatstates') + + +class Chatstates: + def __init__(self, client): + self._client = client + self.handlers = [ + StanzaHandler(name='message', + callback=self._process_message_chatstate, + ns=NS_CHATSTATES, + priority=15), + ] + + def _process_message_chatstate(self, _con, stanza, properties): + chatstate = parse_chatstate(stanza) + if chatstate is None: + return + + if properties.is_mam_message: + return + + if stanza.getTag('delay', namespace=NS_DELAY2) is not None: + return + + if chatstate not in CHATSTATES: + log.warning('Invalid chatstate: %s', chatstate) + log.warning(stanza) + return + + properties.chatstate = chatstate + + +def parse_chatstate(stanza): + children = stanza.getChildren() + for child in children: + if child.getNamespace() == NS_CHATSTATES: + return child.getName() + return None
===================================== nbxmpp/modules/message.py ===================================== @@ -79,6 +79,7 @@ class BaseMessage: forms = stanza.getTags('x', namespace=NS_DATA) if forms: properties.forms = forms + properties.xhtml = stanza.getXHTML()
@staticmethod def _parse_type(stanza):
===================================== nbxmpp/modules/security_labels.py ===================================== @@ -0,0 +1,57 @@ +# Copyright (C) 2018 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_SECLABEL +from nbxmpp.structs import StanzaHandler +from nbxmpp.structs import SecurityLabel +from nbxmpp.structs import DisplayMarking + +log = logging.getLogger('nbxmpp.m.security_labels') + + +class SecurityLabels: + def __init__(self, client): + self._client = client + self.handlers = [ + StanzaHandler(name='message', + callback=self._process_message_security_label, + ns=NS_SECLABEL, + priority=15), + ] + + def _process_message_security_label(self, _con, stanza, properties): + security = stanza.getTag('securitylabel', namespace=NS_SECLABEL) + if security is None: + return + + displaymarking = security.getTag('displaymarking') + if displaymarking is None: + return + + label = displaymarking.getData() + if not label: + log.warning('No label found') + log.warning(stanza) + return + + fgcolor = displaymarking.getAttr('fgcolor') + bgcolor = displaymarking.getAttr('bgcolor') + + properties.security_label = SecurityLabel( + DisplayMarking(label, fgcolor, bgcolor))
===================================== nbxmpp/protocol.py ===================================== @@ -1243,12 +1243,14 @@ class Message(Protocol):
TODO: Returning a DOM could make rendering faster. """ - xhtml = self.getTag('html') + xhtml = self.getTag('html', namespace=NS_XHTML_IM) if xhtml: if xmllang: - body = xhtml.getTag('body', attrs={'xml:lang': xmllang}) + body = xhtml.getTag('body', + namespace=NS_XHTML, + attrs={'xml:lang': xmllang}) else: - body = xhtml.getTag('body') + body = xhtml.getTag('body', namespace=NS_XHTML) return str(body) return None
===================================== nbxmpp/structs.py ===================================== @@ -125,6 +125,9 @@ OOBData = namedtuple('OOBData', 'url desc')
CorrectionData = namedtuple('CorrectionData', 'id')
+DisplayMarking = namedtuple('DisplayMarking', 'label fgcolor bgcolor') +SecurityLabel = namedtuple('SecurityLabel', 'displaymarking') +
class DiscoInfo(namedtuple('DiscoInfo', 'stanza identities features dataforms timestamp')):
@@ -553,6 +556,9 @@ class MessageProperties: self.correction = None self.attention = False self.forms = None + self.xhtml = None + self.security_label = None + self.chatstate = None
@property def has_user_delay(self): @@ -649,6 +655,18 @@ class MessageProperties: def has_forms(self): return self.forms is not None
+ @property + def has_xhtml(self): + return self.xhtml is not None + + @property + def has_security_label(self): + return self.security_label is not None + + @property + def has_chatstate(self): + return self.chatstate is not None +
class IqProperties: def __init__(self):
View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/compare/22ddb4b89a8bdd94d96c7b4b06...