Mercurial > libervia-pubsub
annotate sat_pubsub/mam.py @ 431:5e8b8ef5c862
implentation of XEP-0346 (Form Discovery and Publishing):
The former non standard node schema has been replaced by XEP-0346 which uses 2 nodes (one
from schema/template and one for submitted values).
The implementation is an adapation of the former one, and data validation is still done
even if this is not currently specified in any XEP.
When the template node is modified, the change is reflected in the node schema.
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 11 Dec 2020 17:19:00 +0100 |
parents | ccb2a22ea0fc |
children | 91da42d44ea2 |
rev | line source |
---|---|
414 | 1 #!/usr/bin/env python3 |
280
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
2 #-*- coding: utf-8 -*- |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
3 |
316
cca47e9977a5
mam: minor improvments (module import and some checks)
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
4 # Copyright (c) 2016 Jérôme Poisson |
311 | 5 # Copyright (c) 2015-2016 Adrien Cossa |
6 # | |
7 # This program is free software: you can redistribute it and/or modify | |
8 # it under the terms of the GNU Affero General Public License as published by | |
9 # the Free Software Foundation, either version 3 of the License, or | |
10 # (at your option) any later version. | |
11 # | |
12 # This program is distributed in the hope that it will be useful, | |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 # GNU Affero General Public License for more details. | |
16 # | |
17 # You should have received a copy of the GNU Affero General Public License | |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
280
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
20 """ |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
21 XMPP Message Archive Management protocol. |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
22 |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
23 This protocol is specified in |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
24 U{XEP-0313<http://xmpp.org/extensions/xep-0313.html>}. |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
25 """ |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
26 |
311 | 27 |
414 | 28 from zope.interface import implementer |
281
30895c49ebd2
fixes the imports from sat.tmp
souliane <souliane@mailoo.org>
parents:
280
diff
changeset
|
29 |
282
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
281
diff
changeset
|
30 from twisted.words.xish import domish |
322 | 31 from twisted.python import log |
431
5e8b8ef5c862
implentation of XEP-0346 (Form Discovery and Publishing):
Goffi <goffi@goffi.org>
parents:
414
diff
changeset
|
32 from twisted.internet import defer |
322 | 33 from twisted.words.protocols.jabber import error |
282
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
281
diff
changeset
|
34 |
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
281
diff
changeset
|
35 from sat_pubsub import const |
322 | 36 from sat_pubsub import backend |
37 from wokkel import pubsub | |
282
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
281
diff
changeset
|
38 |
322 | 39 from wokkel import rsm |
40 from wokkel import mam | |
41 from wokkel import delay | |
282
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
281
diff
changeset
|
42 |
280
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
43 |
414 | 44 @implementer(mam.IMAMResource) |
280
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
45 class MAMResource(object): |
322 | 46 _errorMap = backend.PubSubResourceFromBackend._errorMap |
280
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
47 |
322 | 48 def __init__(self, backend_): |
49 self.backend = backend_ | |
50 | |
51 def _mapErrors(self, failure): | |
52 # XXX: come from backend.PubsubResourceFromBackend | |
414 | 53 e = failure.trap(*list(self._errorMap.keys())) |
280
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
54 |
322 | 55 condition, pubsubCondition, feature = self._errorMap[e] |
56 msg = failure.value.msg | |
282
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
281
diff
changeset
|
57 |
322 | 58 if pubsubCondition: |
59 exc = pubsub.PubSubError(condition, pubsubCondition, feature, msg) | |
60 else: | |
61 exc = error.StanzaError(condition, text=msg) | |
62 | |
63 raise exc | |
64 | |
325
8d939378f023
mam: removed requestor in favor of mam_request.sender and recipient + fixed bad use of requestor instead of recipient in getItemsData
Goffi <goffi@goffi.org>
parents:
322
diff
changeset
|
65 def onArchiveRequest(self, mam_request): |
280
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
66 """ |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
67 |
322 | 68 @param mam_request: The MAM archive request. |
69 @type mam_request: L{MAMQueryReques<wokkel.mam.MAMRequest>} | |
280
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
70 |
316
cca47e9977a5
mam: minor improvments (module import and some checks)
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
71 @return: A tuple with list of message data (id, element, data) and RSM element |
cca47e9977a5
mam: minor improvments (module import and some checks)
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
72 @rtype: C{tuple} |
280
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
73 """ |
316
cca47e9977a5
mam: minor improvments (module import and some checks)
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
74 # FIXME: bad result ordering |
322 | 75 try: |
76 pep = mam_request.delegated | |
77 except AttributeError: | |
78 pep = False | |
79 ext_data = {'pep': pep} | |
80 if mam_request.form: | |
414 | 81 ext_data['filters'] = list(mam_request.form.fields.values()) |
322 | 82 if mam_request.rsm is None: |
83 if const.VAL_RSM_MAX_DEFAULT != None: | |
84 log.msg("MAM request without RSM limited to {}".format(const.VAL_RSM_MAX_DEFAULT)) | |
85 ext_data['rsm'] = rsm.RSMRequest(const.VAL_RSM_MAX_DEFAULT) | |
86 else: | |
87 ext_data['rsm'] = mam_request.rsm | |
282
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
281
diff
changeset
|
88 |
375
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
369
diff
changeset
|
89 if mam_request.orderBy: |
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
369
diff
changeset
|
90 ext_data['order_by'] = mam_request.orderBy |
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
369
diff
changeset
|
91 |
431
5e8b8ef5c862
implentation of XEP-0346 (Form Discovery and Publishing):
Goffi <goffi@goffi.org>
parents:
414
diff
changeset
|
92 d = defer.ensureDeferred( |
5e8b8ef5c862
implentation of XEP-0346 (Form Discovery and Publishing):
Goffi <goffi@goffi.org>
parents:
414
diff
changeset
|
93 self.backend.getItemsData(mam_request.node, mam_request.sender, |
398
845ed0f71dd6
mam: don't crash on missing <first> element in RSM on archive request
Goffi <goffi@goffi.org>
parents:
379
diff
changeset
|
94 mam_request.recipient, None, None, ext_data) |
431
5e8b8ef5c862
implentation of XEP-0346 (Form Discovery and Publishing):
Goffi <goffi@goffi.org>
parents:
414
diff
changeset
|
95 ) |
282
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
281
diff
changeset
|
96 |
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
281
diff
changeset
|
97 def make_message(elt): |
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
281
diff
changeset
|
98 # XXX: http://xmpp.org/extensions/xep-0297.html#sect-idp629952 (rule 3) |
322 | 99 message = domish.Element((const.NS_CLIENT, "message")) |
100 event = message.addElement((pubsub.NS_PUBSUB_EVENT, "event")) | |
282
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
281
diff
changeset
|
101 items = event.addElement('items') |
322 | 102 items["node"] = mam_request.node |
282
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
281
diff
changeset
|
103 items.addChild(elt) |
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
281
diff
changeset
|
104 return message |
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
281
diff
changeset
|
105 |
322 | 106 def cb(items_data): |
282
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
281
diff
changeset
|
107 msg_data = [] |
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
281
diff
changeset
|
108 rsm_elt = None |
379
66fbf026ed49
mam: set "complete" attribute when suitable
Goffi <goffi@goffi.org>
parents:
375
diff
changeset
|
109 attributes = {} |
322 | 110 for item_data in items_data: |
111 if item_data.item.name == 'set' and item_data.item.uri == rsm.NS_RSM: | |
316
cca47e9977a5
mam: minor improvments (module import and some checks)
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
112 assert rsm_elt is None |
322 | 113 rsm_elt = item_data.item |
398
845ed0f71dd6
mam: don't crash on missing <first> element in RSM on archive request
Goffi <goffi@goffi.org>
parents:
379
diff
changeset
|
114 if rsm_elt.first: |
845ed0f71dd6
mam: don't crash on missing <first> element in RSM on archive request
Goffi <goffi@goffi.org>
parents:
379
diff
changeset
|
115 # XXX: we check if it is the last page using initial request data |
845ed0f71dd6
mam: don't crash on missing <first> element in RSM on archive request
Goffi <goffi@goffi.org>
parents:
379
diff
changeset
|
116 # and RSM element data. In this case, we must have the |
845ed0f71dd6
mam: don't crash on missing <first> element in RSM on archive request
Goffi <goffi@goffi.org>
parents:
379
diff
changeset
|
117 # "complete" |
845ed0f71dd6
mam: don't crash on missing <first> element in RSM on archive request
Goffi <goffi@goffi.org>
parents:
379
diff
changeset
|
118 # attribute set to "true". |
845ed0f71dd6
mam: don't crash on missing <first> element in RSM on archive request
Goffi <goffi@goffi.org>
parents:
379
diff
changeset
|
119 page_max = (int(rsm_elt.first['index']) + 1) * mam_request.rsm.max |
414 | 120 count = int(str(rsm_elt.count)) |
398
845ed0f71dd6
mam: don't crash on missing <first> element in RSM on archive request
Goffi <goffi@goffi.org>
parents:
379
diff
changeset
|
121 if page_max >= count: |
845ed0f71dd6
mam: don't crash on missing <first> element in RSM on archive request
Goffi <goffi@goffi.org>
parents:
379
diff
changeset
|
122 # the maximum items which can be displayed is equal to or |
845ed0f71dd6
mam: don't crash on missing <first> element in RSM on archive request
Goffi <goffi@goffi.org>
parents:
379
diff
changeset
|
123 # above the total number of items, which means we are complete |
845ed0f71dd6
mam: don't crash on missing <first> element in RSM on archive request
Goffi <goffi@goffi.org>
parents:
379
diff
changeset
|
124 attributes['complete'] = "true" |
845ed0f71dd6
mam: don't crash on missing <first> element in RSM on archive request
Goffi <goffi@goffi.org>
parents:
379
diff
changeset
|
125 else: |
401
907b10480394
mam: fixed confusion between twisted log.msg and log.warning used elsewhere
Goffi <goffi@goffi.org>
parents:
399
diff
changeset
|
126 log.msg("WARNING: no <first> element in RSM request: {xml}".format( |
907b10480394
mam: fixed confusion between twisted log.msg and log.warning used elsewhere
Goffi <goffi@goffi.org>
parents:
399
diff
changeset
|
127 xml = rsm_elt.toXml().encode('utf-8'))) |
322 | 128 elif item_data.item.name == 'item': |
398
845ed0f71dd6
mam: don't crash on missing <first> element in RSM on archive request
Goffi <goffi@goffi.org>
parents:
379
diff
changeset
|
129 msg_data.append([item_data.item['id'], make_message(item_data.item), |
845ed0f71dd6
mam: don't crash on missing <first> element in RSM on archive request
Goffi <goffi@goffi.org>
parents:
379
diff
changeset
|
130 item_data.created]) |
322 | 131 else: |
132 log.msg("WARNING: unknown element: {}".format(item_data.item.name)) | |
133 if pep: | |
134 # we need to send privileged message | |
135 # so me manage the sending ourself, and return | |
136 # an empty msg_data list to avoid double sending | |
137 for data in msg_data: | |
325
8d939378f023
mam: removed requestor in favor of mam_request.sender and recipient + fixed bad use of requestor instead of recipient in getItemsData
Goffi <goffi@goffi.org>
parents:
322
diff
changeset
|
138 self.forwardPEPMessage(mam_request, *data) |
322 | 139 msg_data = [] |
379
66fbf026ed49
mam: set "complete" attribute when suitable
Goffi <goffi@goffi.org>
parents:
375
diff
changeset
|
140 return (msg_data, rsm_elt, attributes) |
282
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
281
diff
changeset
|
141 |
322 | 142 d.addErrback(self._mapErrors) |
316
cca47e9977a5
mam: minor improvments (module import and some checks)
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
143 d.addCallback(cb) |
cca47e9977a5
mam: minor improvments (module import and some checks)
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
144 return d |
280
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
145 |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
335
diff
changeset
|
146 def forwardPEPMessage(self, mam_request, id_, elt, created): |
322 | 147 msg = domish.Element((None, 'message')) |
148 msg['from'] = self.backend.privilege.server_jid.full() | |
325
8d939378f023
mam: removed requestor in favor of mam_request.sender and recipient + fixed bad use of requestor instead of recipient in getItemsData
Goffi <goffi@goffi.org>
parents:
322
diff
changeset
|
149 msg['to'] = mam_request.sender.full() |
322 | 150 result = msg.addElement((mam.NS_MAM, 'result')) |
151 if mam_request.query_id is not None: | |
152 result['queryid'] = mam_request.query_id | |
153 result['id'] = id_ | |
154 forward = result.addElement((const.NS_FORWARD, 'forwarded')) | |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
335
diff
changeset
|
155 forward.addChild(delay.Delay(created).toElement()) |
322 | 156 forward.addChild(elt) |
157 self.backend.privilege.sendMessage(msg) | |
158 | |
280
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
159 def onPrefsGetRequest(self, requestor): |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
160 """ |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
161 |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
162 @param requestor: JID of the requestor. |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
163 @type requestor: L{JID<twisted.words.protocols.jabber.jid.JID>} |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
164 |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
165 @return: The current settings. |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
166 @rtype: L{wokkel.mam.MAMPrefs} |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
167 """ |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
168 # TODO: return the actual current settings |
316
cca47e9977a5
mam: minor improvments (module import and some checks)
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
169 return mam.MAMPrefs() |
280
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
170 |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
171 def onPrefsSetRequest(self, prefs, requestor): |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
172 """ |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
173 |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
174 @param prefs: The new settings to set. |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
175 @type prefs: L{wokkel.mam.MAMPrefs} |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
176 |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
177 @param requestor: JID of the requestor. |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
178 @type requestor: L{JID<twisted.words.protocols.jabber.jid.JID>} |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
179 |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
180 @return: The settings that have actually been set. |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
181 @rtype: L{wokkel.mam.MAMPrefs} |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
182 """ |
798cb8962c0b
MAM (XEP-0313) support: first draft
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
183 # TODO: set the new settings and return them |
316
cca47e9977a5
mam: minor improvments (module import and some checks)
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
184 return mam.MAMPrefs() |