Skip to content
Back to top

# Source code for slixmpp.plugins.xep_0184.receipt

    # 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.

    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.plugin['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.plugin['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 stanza['type'] not 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.plugin['xep_0030'].supports(stanza['to'],
                        feature='urn:xmpp:receipts',
                        cached=True):
                    return stanza

            stanza['request_receipt'] = True
            return stanza