Mercurial > prosody-hg
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 |
| parents | cb52cb8aa706 |
| children | 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 |
