text: """
      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 = set(['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
  