Software /
code /
prosody
Comparison
plugins/mod_muc_mam.lua @ 11282:cabb022f31c0
mod_muc_mam: Copy extended MAM support from mod_mam
mod_mam and mod_muc_mam are just different enough that having them be
the same module gets complicated, but close enough to have overlapping
code.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Tue, 12 Jan 2021 19:32:10 +0100 |
parent | 10944:cb52cb8aa706 |
child | 11744:5f99aa6bb76d |
comparison
equal
deleted
inserted
replaced
11281:142fb655b885 | 11282:cabb022f31c0 |
---|---|
1 -- XEP-0313: Message Archive Management for Prosody MUC | 1 -- XEP-0313: Message Archive Management for Prosody MUC |
2 -- Copyright (C) 2011-2017 Kim Alvefur | 2 -- Copyright (C) 2011-2021 Kim Alvefur |
3 -- | 3 -- |
4 -- This file is MIT/X11 licensed. | 4 -- This file is MIT/X11 licensed. |
5 | 5 |
6 if module:get_host_type() ~= "component" then | 6 if module:get_host_type() ~= "component" then |
7 module:log_status("error", "mod_%s should be loaded only on a MUC component, not normal hosts", module.name); | 7 module:log_status("error", "mod_%s should be loaded only on a MUC component, not normal hosts", module.name); |
8 return; | 8 return; |
9 end | 9 end |
10 | 10 |
11 local xmlns_mam = "urn:xmpp:mam:2"; | 11 local xmlns_mam = "urn:xmpp:mam:2"; |
12 local xmlns_mam_ext = "urn:xmpp:mam:2#extended"; | |
12 local xmlns_delay = "urn:xmpp:delay"; | 13 local xmlns_delay = "urn:xmpp:delay"; |
13 local xmlns_forward = "urn:xmpp:forward:0"; | 14 local xmlns_forward = "urn:xmpp:forward:0"; |
14 local xmlns_st_id = "urn:xmpp:sid:0"; | 15 local xmlns_st_id = "urn:xmpp:sid:0"; |
15 local xmlns_muc_user = "http://jabber.org/protocol/muc#user"; | 16 local xmlns_muc_user = "http://jabber.org/protocol/muc#user"; |
16 local muc_form_enable = "muc#roomconfig_enablearchiving" | 17 local muc_form_enable = "muc#roomconfig_enablearchiving" |
141 | 142 |
142 local qid = query.attr.queryid; | 143 local qid = query.attr.queryid; |
143 | 144 |
144 -- Search query parameters | 145 -- Search query parameters |
145 local qstart, qend; | 146 local qstart, qend; |
147 local qbefore, qafter; | |
148 local qids; | |
146 local form = query:get_child("x", "jabber:x:data"); | 149 local form = query:get_child("x", "jabber:x:data"); |
147 if form then | 150 if form then |
148 local form_type, err = get_form_type(form); | 151 local form_type, err = get_form_type(form); |
149 if not form_type then | 152 if not form_type then |
150 origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid dataform: "..err)); | 153 origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid dataform: "..err)); |
157 if err then | 160 if err then |
158 origin.send(st.error_reply(stanza, "modify", "bad-request", select(2, next(err)))); | 161 origin.send(st.error_reply(stanza, "modify", "bad-request", select(2, next(err)))); |
159 return true; | 162 return true; |
160 end | 163 end |
161 qstart, qend = form["start"], form["end"]; | 164 qstart, qend = form["start"], form["end"]; |
165 qbefore, qafter = form["before-id"], form["after-id"]; | |
166 qids = form["ids"]; | |
162 end | 167 end |
163 | 168 |
164 if qstart or qend then -- Validate timestamps | 169 if qstart or qend then -- Validate timestamps |
165 local vstart, vend = (qstart and timestamp_parse(qstart)), (qend and timestamp_parse(qend)) | 170 local vstart, vend = (qstart and timestamp_parse(qstart)), (qend and timestamp_parse(qend)) |
166 if (qstart and not vstart) or (qend and not vend) then | 171 if (qstart and not vstart) or (qend and not vend) then |
179 -- RSM stuff | 184 -- RSM stuff |
180 local qset = rsm.get(query); | 185 local qset = rsm.get(query); |
181 local qmax = m_min(qset and qset.max or default_max_items, max_max_items); | 186 local qmax = m_min(qset and qset.max or default_max_items, max_max_items); |
182 local reverse = qset and qset.before or false; | 187 local reverse = qset and qset.before or false; |
183 | 188 |
184 local before, after = qset and qset.before, qset and qset.after; | 189 local before, after = qset and qset.before or qbefore, qset and qset.after or qafter; |
185 if type(before) ~= "string" then before = nil; end | 190 if type(before) ~= "string" then before = nil; end |
186 if qset then | 191 if qset then |
187 module:log("debug", "Archive query id=%s rsm=%q", qid or stanza.attr.id, qset); | 192 module:log("debug", "Archive query id=%s rsm=%q", qid or stanza.attr.id, qset); |
188 end | 193 end |
194 -- A reverse query needs to be flipped | |
195 local flip = reverse; | |
196 -- A flip-page query needs to be the opposite of that. | |
197 if query:get_child("flip-page") then flip = not flip end | |
189 | 198 |
190 -- Load all the data! | 199 -- Load all the data! |
191 local data, err = archive:find(room_node, { | 200 local data, err = archive:find(room_node, { |
192 start = qstart; ["end"] = qend; -- Time range | 201 start = qstart; ["end"] = qend; -- Time range |
193 limit = qmax + 1; | 202 limit = qmax + 1; |
194 before = before; after = after; | 203 before = before; after = after; |
204 ids = qids; | |
195 reverse = reverse; | 205 reverse = reverse; |
196 with = "message<groupchat"; | 206 with = "message<groupchat"; |
197 }); | 207 }); |
198 | 208 |
199 if not data then | 209 if not data then |
243 fwd_st:add_child(item); | 253 fwd_st:add_child(item); |
244 | 254 |
245 if not first then first = id; end | 255 if not first then first = id; end |
246 last = id; | 256 last = id; |
247 | 257 |
248 if reverse then | 258 if flip then |
249 results[count] = fwd_st; | 259 results[count] = fwd_st; |
250 else | 260 else |
251 origin.send(fwd_st); | 261 origin.send(fwd_st); |
252 end | 262 end |
253 end | 263 end |
254 | 264 |
255 if reverse then | 265 if flip then |
256 for i = #results, 1, -1 do | 266 for i = #results, 1, -1 do |
257 origin.send(results[i]); | 267 origin.send(results[i]); |
258 end | 268 end |
269 end | |
270 if reverse then | |
259 first, last = last, first; | 271 first, last = last, first; |
260 end | 272 end |
261 | 273 |
262 | 274 |
263 origin.send(st.reply(stanza) | 275 origin.send(st.reply(stanza) |
437 | 449 |
438 -- And role/affiliation changes? | 450 -- And role/affiliation changes? |
439 | 451 |
440 module:add_feature(xmlns_mam); | 452 module:add_feature(xmlns_mam); |
441 | 453 |
454 local advertise_extended = archive.caps and archive.caps.full_id_range and archive.caps.ids; | |
455 | |
442 module:hook("muc-disco#info", function(event) | 456 module:hook("muc-disco#info", function(event) |
443 if archiving_enabled(event.room) then | 457 if archiving_enabled(event.room) then |
444 event.reply:tag("feature", {var=xmlns_mam}):up(); | 458 event.reply:tag("feature", {var=xmlns_mam}):up(); |
459 if advertise_extended then | |
460 (event.reply or event.stanza):tag("feature", {var=xmlns_mam_ext}):up(); | |
461 end | |
445 end | 462 end |
446 event.reply:tag("feature", {var=xmlns_st_id}):up(); | 463 event.reply:tag("feature", {var=xmlns_st_id}):up(); |
447 end); | 464 end); |
448 | 465 |
449 -- Cleanup | 466 -- Cleanup |