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
18from nbxmpp.namespaces import Namespace
19from nbxmpp.protocol import isMucPM
20from nbxmpp.protocol import Message
21from nbxmpp.structs import StanzaHandler
22from nbxmpp.structs import ReceiptData
23from nbxmpp.util import generate_id
24from nbxmpp.modules.base import BaseModule
25
26
27class Receipts(BaseModule):
28    def __init__(self, client):
29        BaseModule.__init__(self, client)
30
31        self._client = client
32        self.handlers = [
33            StanzaHandler(name='message',
34                          callback=self._process_message_receipt,
35                          ns=Namespace.RECEIPTS,
36                          priority=15),
37        ]
38
39    def _process_message_receipt(self, _client, stanza, properties):
40        request = stanza.getTag('request', namespace=Namespace.RECEIPTS)
41        if request is not None:
42            properties.receipt = ReceiptData(request.getName())
43            return
44
45        received = stanza.getTag('received', namespace=Namespace.RECEIPTS)
46        if received is not None:
47            id_ = received.getAttr('id')
48            if id_ is None:
49                self._log.warning('Receipt without id attr')
50                self._log.warning(stanza)
51                return
52
53            properties.receipt = ReceiptData(received.getName(), id_)
54
55
56def build_receipt(stanza):
57    if not isinstance(stanza, Message):
58        raise ValueError('Stanza type must be protocol.Message')
59
60    if stanza.getType() == 'error':
61        raise ValueError('Receipt can not be generated for type error messages')
62
63    if stanza.getID() is None:
64        raise ValueError('Receipt can not be generated for messages without id')
65
66    if stanza.getTag('received', namespace=Namespace.RECEIPTS) is not None:
67        raise ValueError('Receipt can not be generated for receipts')
68
69    is_muc_pm = isMucPM(stanza)
70
71    jid = stanza.getFrom()
72    typ = stanza.getType()
73    if typ == 'groupchat' or not is_muc_pm:
74        jid = jid.new_as_bare()
75
76    message = Message(to=jid, typ=typ)
77    if is_muc_pm:
78        message.setTag('x', namespace=Namespace.MUC_USER)
79    message_id = generate_id()
80    message.setID(message_id)
81    message.setReceiptReceived(stanza.getID())
82    message.setHint('store')
83    message.setOriginID(message_id)
84    return message
85