comparison mod_storage_metronome_readonly/mod_storage_metronome_readonly.lua @ 6142:ec0e9d4f2275

mod_storage_metronome_readonly: Add support for mod_muc_mam storage
author Link Mauve <linkmauve@linkmauve.fr>
date Tue, 28 Jan 2025 00:35:39 +0100
parents dcd16e349a7a
children 44f77f4f653a
comparison
equal deleted inserted replaced
6141:dcd16e349a7a 6142:ec0e9d4f2275
3 local st = require "prosody.util.stanza"; 3 local st = require "prosody.util.stanza";
4 local now = require "prosody.util.time".now; 4 local now = require "prosody.util.time".now;
5 local gen_id = require "prosody.util.id".medium; 5 local gen_id = require "prosody.util.id".medium;
6 local set = require "prosody.util.set"; 6 local set = require "prosody.util.set";
7 local envloadfile = require"prosody.util.envload".envloadfile; 7 local envloadfile = require"prosody.util.envload".envloadfile;
8 local dir = require "lfs".dir;
8 9
9 local host = module.host; 10 local host = module.host;
10 11
11 local archive_item_limit = module:get_option_integer("storage_archive_item_limit", 10000, 0); 12 local archive_item_limit = module:get_option_integer("storage_archive_item_limit", 10000, 0);
12 13
161 store = self.store; 162 store = self.store;
162 end 163 end
163 return datamanager.users(host, store, self.type); 164 return datamanager.users(host, store, self.type);
164 end 165 end
165 166
166 local archive = {}; 167 local function parse_logs(logs, is_muc)
167 driver.archive = { __index = archive }; 168 local iter = ipairs(logs);
168 169 local i = 0;
169 archive.caps = { 170 local message;
170 total = true; 171 return function()
171 quota = archive_item_limit; 172 i, message = iter(logs, i);
172 full_id_range = true; 173 if not message then
173 ids = true; 174 return;
174 }; 175 end
175 176
176 function archive:append(username, key, value, when, with) -- luacheck: ignore 212/self username key value when with 177 local with;
177 return nil, "unsupported-store"; 178 if is_muc then
178 end 179 with = message["resource"];
179 180 else
180 function archive:find(username, query) -- luacheck: ignore 212/self query
181 if self.store == "archive" then
182 local jid = username.."@"..host;
183 local data = datamanager.load(username, host, "archiving");
184 local iter = ipairs(data["logs"]);
185 local i = 0;
186 local message;
187 return function()
188 i, message = iter(data["logs"], i);
189 if not message then
190 return;
191 end
192
193 local with;
194 local bare_to = message["bare_to"]; 181 local bare_to = message["bare_to"];
195 local bare_from = message["bare_from"]; 182 local bare_from = message["bare_from"];
196 if jid == bare_to then 183 if jid == bare_to then
197 -- received 184 -- received
198 with = bare_from; 185 with = bare_from;
199 else 186 else
200 -- sent 187 -- sent
201 with = bare_to; 188 with = bare_to;
202 end 189 end
203 190 end
204 local to = message["to"]; 191
205 local from = message["from"]; 192 local to = message["to"];
206 local id = message["id"]; 193 local from = message["from"];
207 local type = message["type"]; 194 local id = message["id"];
208 195 local type = message["type"];
209 local key = message["uid"]; 196
210 local when = message["timestamp"]; 197 local key = message["uid"];
211 local item = st.message({ to = to, from = from, id = id, type = type }, message["body"]); 198 local when = message["timestamp"];
212 if message["tags"] then 199 local item = st.message({ to = to, from = from, id = id, type = type }, message["body"]);
213 for _, tag in ipairs(message["tags"]) do 200 if message["tags"] then
214 setmetatable(tag, st.stanza_mt); 201 for _, tag in ipairs(message["tags"]) do
215 item:add_direct_child(tag); 202 setmetatable(tag, st.stanza_mt);
216 end 203 item:add_direct_child(tag);
217 end 204 end
218 if message["marker"] then 205 end
219 item:tag(message["marker"], { xmlns = "urn:xmpp:chat-markers:0", id = message["marker_id"] }); 206 if message["marker"] then
220 end 207 item:tag(message["marker"], { xmlns = "urn:xmpp:chat-markers:0", id = message["marker_id"] });
221 return key, item, when, with; 208 end
222 end; 209 return key, item, when, with;
210 end;
211 end
212
213 local archive = {};
214 driver.archive = { __index = archive };
215
216 archive.caps = {
217 total = true;
218 quota = archive_item_limit;
219 full_id_range = true;
220 ids = true;
221 };
222
223 function archive:append(username, key, value, when, with) -- luacheck: ignore 212/self username key value when with
224 return nil, "unsupported-store";
225 end
226
227 function archive:find(username, query) -- luacheck: ignore 212/self query
228 if self.store == "archive" then
229 local jid = username.."@"..host;
230 local data = datamanager.load(username, host, "archiving");
231 return parse_logs(data["logs"]);
223 232
224 elseif self.store:sub(1, 4) == "pep_" then 233 elseif self.store:sub(1, 4) == "pep_" then
225 local node = self.store:sub(5); 234 local node = self.store:sub(5);
226 235
227 local pep_base_path = datamanager.getpath(username, host, "pep"):sub(1, -5); 236 local pep_base_path = datamanager.getpath(username, host, "pep"):sub(1, -5);
247 end 256 end
248 local item = st.deserialize(payload[1]); 257 local item = st.deserialize(payload[1]);
249 local with = data["data_author"][key]; 258 local with = data["data_author"][key];
250 return key, item, time_now, with; 259 return key, item, time_now, with;
251 end; 260 end;
261
252 elseif self.store == "offline" then 262 elseif self.store == "offline" then
253 -- This is mostly copy/pasted from mod_storage_internal. 263 -- This is mostly copy/pasted from mod_storage_internal.
254 local list, err = datamanager.list_open(username, host, self.store); 264 local list, err = datamanager.list_open(username, host, self.store);
255 if not list then 265 if not list then
256 if err then 266 if err then
282 -- COMPAT Stored data may still contain legacy XEP-0091 timestamp 292 -- COMPAT Stored data may still contain legacy XEP-0091 timestamp
283 item.attr.stamp_legacy = nil; 293 item.attr.stamp_legacy = nil;
284 item = st.deserialize(item); 294 item = st.deserialize(item);
285 return key, item, when, with; 295 return key, item, when, with;
286 end 296 end
297
287 elseif self.store == "uploads" then 298 elseif self.store == "uploads" then
288 local list = {}; 299 local list = {};
289 300
290 for user in datamanager.users(host, "http_upload", "list") do 301 for user in datamanager.users(host, "http_upload", "list") do
291 local data, err = datamanager.list_open(user, host, "http_upload"); 302 local data, err = datamanager.list_open(user, host, "http_upload");
320 local with = payload[1]; 331 local with = payload[1];
321 local when = payload[2]; 332 local when = payload[2];
322 local stanza = payload[3]; 333 local stanza = payload[3];
323 return key, stanza, when, with; 334 return key, stanza, when, with;
324 end; 335 end;
336
337 elseif self.store == "muc_log" then
338 local base_path = datamanager.getpath("", host, "stanza_log"):sub(1, -5);
339 local list = {};
340 for dir_name in dir(base_path) do
341 if dir_name ~= "." and dir_name ~= ".." then
342 local path = base_path..dir_name.."/"..encode(username)..".dat";
343 local get_data = envloadfile(path, {});
344 if get_data then
345 local success, data = pcall(get_data);
346 if not success then
347 module:log("error", "Unable to load metronome storage");
348 return nil, "Error reading storage";
349 end
350 for key, item, when, with in parse_logs(data, true) do
351 table.insert(list, {key, item, when, with});
352 end
353 end
354 end
355 end
356
357 local i = 0;
358 local iter = function()
359 i = i + 1;
360 return list[i];
361 end
362
363 return function()
364 local item = iter();
365 if item == nil then
366 if list.close then
367 list:close();
368 end
369 return
370 end
371 return item[1], item[2], item[3], item[4];
372 end
373
325 else 374 else
326 return nil, "unsupported-store"; 375 return nil, "unsupported-store";
327 end 376 end
328 end 377 end
329 378
378 if not done then 427 if not done then
379 done = true; 428 done = true;
380 return ""; 429 return "";
381 end 430 end
382 end; 431 end;
432 elseif self.store == "muc_log" then
433 local iter, tbl = pairs(datamanager.load(nil, host, "persistent"));
434 local jid = nil;
435 return function()
436 jid = iter(tbl, jid);
437 if not jid then
438 return;
439 end
440 local user = jid:gsub("@.*", "");
441 return user;
442 end;
383 else 443 else
384 return nil, "unsupported-store"; 444 return nil, "unsupported-store";
385 end 445 end
386 end 446 end
387 447