Philipp Hörist pushed to branch master at gajim / python-nbxmpp
Commits:
-
a15b98ae
by Philipp Hörist at 2019-10-12T13:17:20Z
4 changed files:
Changes:
| ... | ... | @@ -72,6 +72,7 @@ from nbxmpp.modules.adhoc import AdHoc |
| 72 | 72 |
from nbxmpp.modules.ibb import IBB
|
| 73 | 73 |
from nbxmpp.modules.discovery import Discovery
|
| 74 | 74 |
from nbxmpp.modules.chat_markers import ChatMarkers
|
| 75 |
+from nbxmpp.modules.receipts import Receipts
|
|
| 75 | 76 |
from nbxmpp.modules.misc import unwrap_carbon
|
| 76 | 77 |
from nbxmpp.modules.misc import unwrap_mam
|
| 77 | 78 |
from nbxmpp.util import get_properties_struct
|
| ... | ... | @@ -211,6 +212,7 @@ class XMPPDispatcher(PlugIn): |
| 211 | 212 |
self._modules['IBB'] = IBB(self._owner)
|
| 212 | 213 |
self._modules['Discovery'] = Discovery(self._owner)
|
| 213 | 214 |
self._modules['ChatMarkers'] = ChatMarkers(self._owner)
|
| 215 |
+ self._modules['Receipts'] = Receipts(self._owner)
|
|
| 214 | 216 |
|
| 215 | 217 |
for instance in self._modules.values():
|
| 216 | 218 |
for handler in instance.handlers:
|
| 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_RECEIPTS
|
|
| 21 |
+from nbxmpp.structs import StanzaHandler
|
|
| 22 |
+from nbxmpp.structs import ReceiptData
|
|
| 23 |
+ |
|
| 24 |
+log = logging.getLogger('nbxmpp.m.receipts')
|
|
| 25 |
+ |
|
| 26 |
+ |
|
| 27 |
+class Receipts:
|
|
| 28 |
+ def __init__(self, client):
|
|
| 29 |
+ self._client = client
|
|
| 30 |
+ self.handlers = [
|
|
| 31 |
+ StanzaHandler(name='message',
|
|
| 32 |
+ callback=self._process_message_receipt,
|
|
| 33 |
+ ns=NS_RECEIPTS,
|
|
| 34 |
+ priority=15),
|
|
| 35 |
+ ]
|
|
| 36 |
+ |
|
| 37 |
+ def _process_message_receipt(self, _con, stanza, properties):
|
|
| 38 |
+ request = stanza.getTag('request', namespace=NS_RECEIPTS)
|
|
| 39 |
+ if request is not None:
|
|
| 40 |
+ properties.receipt = ReceiptData(request.getName())
|
|
| 41 |
+ return
|
|
| 42 |
+ |
|
| 43 |
+ received = stanza.getTag('received', namespace=NS_RECEIPTS)
|
|
| 44 |
+ if received is not None:
|
|
| 45 |
+ id_ = received.getAttr('id')
|
|
| 46 |
+ if id_ is None:
|
|
| 47 |
+ log.warning('Receipt without id attr')
|
|
| 48 |
+ log.warning(stanza)
|
|
| 49 |
+ return
|
|
| 50 |
+ |
|
| 51 |
+ properties.receipt = ReceiptData(received.getName(), id_)
|
| ... | ... | @@ -1323,6 +1323,11 @@ class Message(Protocol): |
| 1323 | 1323 |
"""
|
| 1324 | 1324 |
self.setTag('origin-id', namespace=NS_SID, attrs={'id': val})
|
| 1325 | 1325 |
|
| 1326 |
+ def buildReceipt(self):
|
|
| 1327 |
+ message = Message(to=self.getFrom().getBare(), typ=self.getType())
|
|
| 1328 |
+ message.setReceiptReceived(self.getID())
|
|
| 1329 |
+ return message
|
|
| 1330 |
+ |
|
| 1326 | 1331 |
def buildReply(self, text=None):
|
| 1327 | 1332 |
"""
|
| 1328 | 1333 |
Builds and returns another message object with specified text. The to,
|
| ... | ... | @@ -1352,6 +1357,12 @@ class Message(Protocol): |
| 1352 | 1357 |
def setMarkable(self):
|
| 1353 | 1358 |
self.setTag('markable', namespace=NS_CHATMARKERS)
|
| 1354 | 1359 |
|
| 1360 |
+ def setReceiptRequest(self):
|
|
| 1361 |
+ self.setTag('request', namespace=NS_RECEIPTS)
|
|
| 1362 |
+ |
|
| 1363 |
+ def setReceiptReceived(self, id_):
|
|
| 1364 |
+ self.setTag('received', namespace=NS_RECEIPTS, attrs={'id': id_})
|
|
| 1365 |
+ |
|
| 1355 | 1366 |
|
| 1356 | 1367 |
class Presence(Protocol):
|
| 1357 | 1368 |
|
| ... | ... | @@ -485,6 +485,22 @@ class CarbonData(namedtuple('MAMData', 'type')): |
| 485 | 485 |
return self.type == 'received'
|
| 486 | 486 |
|
| 487 | 487 |
|
| 488 |
+class ReceiptData(namedtuple('ReceiptData', 'type id')):
|
|
| 489 |
+ |
|
| 490 |
+ __slots__ = []
|
|
| 491 |
+ |
|
| 492 |
+ def __new__(cls, type, id=None):
|
|
| 493 |
+ return super(ReceiptData, cls).__new__(cls, type, id)
|
|
| 494 |
+ |
|
| 495 |
+ @property
|
|
| 496 |
+ def is_request(self):
|
|
| 497 |
+ return self.type == 'request'
|
|
| 498 |
+ |
|
| 499 |
+ @property
|
|
| 500 |
+ def is_received(self):
|
|
| 501 |
+ return self.type == 'received'
|
|
| 502 |
+ |
|
| 503 |
+ |
|
| 488 | 504 |
class Properties:
|
| 489 | 505 |
pass
|
| 490 | 506 |
|
| ... | ... | @@ -528,6 +544,7 @@ class MessageProperties: |
| 528 | 544 |
self.encrypted = None
|
| 529 | 545 |
self.pgp_legacy = None
|
| 530 | 546 |
self.marker = None
|
| 547 |
+ self.receipt = None
|
|
| 531 | 548 |
|
| 532 | 549 |
@property
|
| 533 | 550 |
def has_user_delay(self):
|
| ... | ... | @@ -604,6 +621,10 @@ class MessageProperties: |
| 604 | 621 |
def is_marker(self):
|
| 605 | 622 |
return self.marker is not None
|
| 606 | 623 |
|
| 624 |
+ @property
|
|
| 625 |
+ def is_receipt(self):
|
|
| 626 |
+ return self.receipt is not None
|
|
| 627 |
+ |
|
| 607 | 628 |
|
| 608 | 629 |
class IqProperties:
|
| 609 | 630 |
def __init__(self):
|