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