diff options
Diffstat (limited to 'sleekxmpp/plugins/xep_0184/receipt.py')
-rw-r--r-- | sleekxmpp/plugins/xep_0184/receipt.py | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/sleekxmpp/plugins/xep_0184/receipt.py b/sleekxmpp/plugins/xep_0184/receipt.py new file mode 100644 index 00000000..c0086b03 --- /dev/null +++ b/sleekxmpp/plugins/xep_0184/receipt.py @@ -0,0 +1,120 @@ +""" + SleekXMPP: The Sleek XMPP Library + Copyright (C) 2012 Erik Reuterborg Larsson, Nathanael C. Fritz + This file is part of SleekXMPP. + + See the file LICENSE for copying permission. +""" + +import logging + +from sleekxmpp.stanza import Message +from sleekxmpp.xmlstream import register_stanza_plugin +from sleekxmpp.xmlstream.handler import Callback +from sleekxmpp.xmlstream.matcher import StanzaPath +from sleekxmpp.plugins import BasePlugin +from sleekxmpp.plugins.xep_0184 import stanza, Request, Received + + +class XEP_0184(BasePlugin): + + """ + XEP-0184: Message Delivery Receipts + """ + + name = 'xep_0184' + description = 'XEP-0184: Message Delivery Receipts' + dependencies = set(['xep_0030']) + stanza = stanza + + ack_types = ('normal', 'chat', 'headline') + + def plugin_init(self): + self.auto_ack = self.config.get('auto_ack', True) + self.auto_request = self.config.get('auto_request', False) + + register_stanza_plugin(Message, Request) + register_stanza_plugin(Message, Received) + + self.xmpp.add_filter('out', self._filter_add_receipt_request) + + self.xmpp.register_handler( + Callback('Message Receipt', + StanzaPath('message/receipt'), + self._handle_receipt_received)) + + self.xmpp.register_handler( + Callback('Message Receipt Request', + StanzaPath('message/request_receipt'), + self._handle_receipt_request)) + + self.xmpp['xep_0030'].add_feature('urn:xmpp:receipts') + + def ack(self, msg): + """ + Acknowledge a message by sending a receipt. + + Arguments: + msg -- The message to acknowledge. + """ + ack = self.xmpp.Message() + ack['to'] = msg['from'] + ack['from'] = msg['to'] + ack['receipt'] = msg['id'] + ack['id'] = self.xmpp.new_id() + ack.send() + + def _handle_receipt_received(self, msg): + self.xmpp.event('receipt_received', msg) + + def _handle_receipt_request(self, msg): + """ + Auto-ack message receipt requests if ``self.auto_ack`` is ``True``. + + Arguments: + msg -- The incoming message requesting a receipt. + """ + if self.auto_ack: + if msg['type'] in self.ack_types: + if not msg['receipt']: + self.ack(msg) + + def _filter_add_receipt_request(self, stanza): + """ + Auto add receipt requests to outgoing messages, if: + + - ``self.auto_request`` is set to ``True`` + - The message is not for groupchat + - The message does not contain a receipt acknowledgment + - The recipient is a bare JID or, if a full JID, one + that has the ``urn:xmpp:receipts`` feature enabled + + The disco cache is checked if a full JID is specified in + the outgoing message, which may mean a round-trip disco#info + delay for the first message sent to the JID if entity caps + are not used. + """ + + if not self.auto_request: + return stanza + + if not isinstance(stanza, Message): + return stanza + + if stanza['request_receipt']: + return stanza + + if not stanza['type'] in self.ack_types: + return stanza + + if stanza['receipt']: + return stanza + + if stanza['to'].resource: + if not self.xmpp['xep_0030'].supports(stanza['to'], + feature='urn:xmpp:receipts', + cached=True): + return stanza + + stanza['request_receipt'] = True + return stanza |