Philipp Hörist pushed to branch master at gajim / python-nbxmpp
Commits:
f37f2c9d by Philipp Hörist at 2019-02-24T21:20:05Z
Delay: Improve discovering server added delays
- - - - -
1 changed file:
- nbxmpp/modules/delay.py
Changes:
=====================================
nbxmpp/modules/delay.py
=====================================
@@ -44,16 +44,21 @@ class Delay:
# to indicate when the user has set the subject,
# the 'from' attr on these delays is the MUC server
# but we treat it as user timestamp
- properties.user_timestamp = parse_delay(
- stanza, from_=properties.jid.getBare())
+ jids = [properties.jid.getBare(),
+ properties.jid.getDomain()]
+
+ properties.user_timestamp = parse_delay(stanza, from_=jids)
else:
- jid = self._client.get_bound_jid().getDomain()
- timestamp = parse_delay(stanza, from_=jid)
- if timestamp is not None:
- properties.timestamp = timestamp
+ if properties.from_muc:
+ # Some servers use the MUC JID, others the domain
+ jids = [properties.jid.getBare(),
+ properties.jid.getDomain()]
+ else:
+ jids = [self._client.get_bound_jid().getDomain()]
- properties.user_timestamp = parse_delay(stanza, not_from=[jid])
+ properties.timestamp = parse_delay(stanza, from_=jids)
+ properties.user_timestamp = parse_delay(stanza, not_from=jids)
@staticmethod
def _process_presence_delay(_con, stanza, properties):
@@ -85,7 +90,7 @@ def parse_delay(stanza, epoch=True, convert='utc', from_=None, not_from=None):
delay_from = delay.getAttr('from')
if from_ is not None:
- if delay_from != from_:
+ if delay_from not in from_:
continue
if not_from is not None:
if delay_from in not_from:
View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/commit/f37f2c9dfdbcb6f6fd5f9bd00c…
--
View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/commit/f37f2c9dfdbcb6f6fd5f9bd00c…
You're receiving this email because of your account on dev.gajim.org.
Philipp Hörist pushed to branch master at gajim / python-nbxmpp
Commits:
1abe1eab by Philipp Hörist at 2019-02-24T16:22:11Z
0.9.91
- - - - -
1 changed file:
- nbxmpp/__init__.py
Changes:
=====================================
nbxmpp/__init__.py
=====================================
@@ -15,4 +15,4 @@ from .client_nb import NonBlockingClient
from .plugin import PlugIn
from .smacks import Smacks
-__version__ = "0.9.90.4"
+__version__ = "0.9.91"
View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/commit/1abe1eab36b389bf2138ef8948…
--
View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/commit/1abe1eab36b389bf2138ef8948…
You're receiving this email because of your account on dev.gajim.org.
Philipp Hörist pushed to branch master at gajim / python-nbxmpp
Commits:
bcceae50 by Philipp Hörist at 2019-02-18T21:51:38Z
Add Annotations (XEP-0145) module
- - - - -
30876f0e by Philipp Hörist at 2019-02-18T21:52:58Z
IQ: Add getQueryChild()
- - - - -
4 changed files:
- nbxmpp/dispatcher_nb.py
- + nbxmpp/modules/annotations.py
- nbxmpp/protocol.py
- nbxmpp/structs.py
Changes:
=====================================
nbxmpp/dispatcher_nb.py
=====================================
@@ -65,6 +65,7 @@ from nbxmpp.modules.user_avatar import UserAvatar
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.misc import unwrap_carbon
from nbxmpp.modules.misc import unwrap_mam
from nbxmpp.util import get_properties_struct
@@ -197,6 +198,7 @@ class XMPPDispatcher(PlugIn):
self._modules['Bookmarks'] = Bookmarks(self._owner)
self._modules['OpenPGP'] = OpenPGP(self._owner)
self._modules['OMEMO'] = OMEMO(self._owner)
+ self._modules['Annotations'] = Annotations(self._owner)
for instance in self._modules.values():
for handler in instance.handlers:
=====================================
nbxmpp/modules/annotations.py
=====================================
@@ -0,0 +1,112 @@
+# 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_PRIVATE
+from nbxmpp.protocol import NS_ROSTERNOTES
+from nbxmpp.protocol import Iq
+from nbxmpp.protocol import Node
+from nbxmpp.protocol import isResultNode
+from nbxmpp.structs import AnnotationNote
+from nbxmpp.structs import CommonResult
+from nbxmpp.modules.date_and_time import parse_datetime
+from nbxmpp.util import validate_jid
+from nbxmpp.util import call_on_response
+from nbxmpp.util import callback
+from nbxmpp.util import raise_error
+
+log = logging.getLogger('nbxmpp.m.annotations')
+
+
+class Annotations:
+ def __init__(self, client):
+ self._client = client
+ self.handlers = []
+
+ @property
+ def domain(self):
+ return self._client.get_bound_jid().getDomain()
+
+ @call_on_response('_annotations_received')
+ def request_annotations(self):
+ log.info('Request annotations for %s', self.domain)
+ payload = Node('storage', attrs={'xmlns': NS_ROSTERNOTES})
+ return Iq(typ='get', queryNS=NS_PRIVATE, payload=payload)
+
+ @callback
+ def _annotations_received(self, stanza):
+ if not isResultNode(stanza):
+ return raise_error(log.info, stanza)
+
+ storage = stanza.getQueryChild('storage')
+ if storage is None:
+ return raise_error(log.warning, stanza, 'stanza-malformed',
+ 'No annotations found')
+
+ nodes = storage.getTags('note')
+ if not nodes:
+ return raise_error(log.info, stanza, 'is-empty',
+ 'No annotations found')
+
+ notes = []
+ for note in nodes:
+ try:
+ jid = validate_jid(note.getAttr('jid'))
+ except Exception:
+ log.warning('Invalid JID: %s, ignoring it',
+ note.getAttr('jid'))
+ continue
+
+ cdate = note.getAttr('cdate')
+ if cdate is not None:
+ cdate = parse_datetime(cdate, epoch=True)
+
+ mdate = note.getAttr('mdate')
+ if mdate is not None:
+ mdate = parse_datetime(mdate, epoch=True)
+
+ data = note.getData()
+ notes.append(AnnotationNote(jid=jid, cdate=cdate,
+ mdate=mdate, data=data))
+
+ log.info('Received annotations from %s:', self.domain)
+ for note in notes:
+ log.info(notes)
+ return notes
+
+ @call_on_response('_default_response')
+ def set_annotations(self, notes):
+ log.info('Set annotations for %s:', self.domain)
+ for note in notes:
+ log.info(note)
+ storage = Node('storage', attrs={'xmlns': NS_ROSTERNOTES})
+ for note in notes:
+ node = Node('note', attrs={'jid': note.jid})
+ node.setData(note.data)
+ if note.cdate is not None:
+ node.setAttr('cdate', note.cdate)
+ if note.mdate is not None:
+ node.setAttr('mdate', note.mdate)
+ storage.addChild(node=node)
+ return Iq(typ='set', queryNS=NS_PRIVATE, payload=storage)
+
+ @callback
+ def _default_response(self, stanza):
+ if not isResultNode(stanza):
+ return raise_error(log.info, stanza)
+ return CommonResult(jid=stanza.getFrom())
=====================================
nbxmpp/protocol.py
=====================================
@@ -1393,6 +1393,22 @@ class Iq(Protocol):
if tag:
return tag.getChildren()
+ def getQueryChild(self, name=None):
+ """
+ Return the 'query' child element with name, or the first element
+ which is not an error element
+ """
+ query = self.getQuery()
+ if not query:
+ return
+ for node in query.getChildren():
+ if name is not None:
+ if node.getName() == name:
+ return node
+ else:
+ if node.getName() != 'error':
+ return node
+
def setQuery(self, name=None):
"""
Change the name of the query node, creating it if needed. Keep the
=====================================
nbxmpp/structs.py
=====================================
@@ -95,6 +95,9 @@ PGPKeyMetadata = namedtuple('PGPKeyMetadata', 'jid fingerprint date')
OMEMOMessage = namedtuple('OMEMOMessage', 'sid iv keys payload')
+AnnotationNote = namedtuple('AnnotationNote', 'jid data cdate mdate')
+AnnotationNote.__new__.__defaults__ = (None, None)
+
class OMEMOBundle(namedtuple('OMEMOBundle', 'spk spk_signature ik otpks')):
def pick_prekey(self):
View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/compare/54ea05ea7dc78de70b5e4dec7…
--
View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/compare/54ea05ea7dc78de70b5e4dec7…
You're receiving this email because of your account on dev.gajim.org.