""" Slixmpp: The Slick XMPP Library Copyright (C) 2012 Erik Reuterborg Larsson, Nathanael C. Fritz This file is part of Slixmpp. See the file LICENSE for copying permission. """ import logging from slixmpp.stanza import Message from slixmpp.xmlstream import register_stanza_plugin from slixmpp.xmlstream.handler import Callback from slixmpp.xmlstream.matcher import StanzaPath from slixmpp.plugins import BasePlugin from slixmpp.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 = {'xep_0030'} stanza = stanza default_config = { 'auto_ack': True, 'auto_request': False } ack_types = ('normal', 'chat', 'headline') def plugin_init(self): 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)) def plugin_end(self): self.xmpp['xep_0030'].del_feature('urn:xmpp:receipts') self.xmpp.del_filter('out', self._filter_add_receipt_request) self.xmpp.remove_handler('Message Receipt') self.xmpp.remove_handler('Message Receipt Request') def session_bind(self, jid): 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['receipt'] = msg['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 not stanza['body']: 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