Changeset

6170: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 6169:dcd16e349a7a
children 6171:44f77f4f653a
files mod_storage_metronome_readonly/mod_storage_metronome_readonly.lua
diffstat 1 files changed, 99 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/mod_storage_metronome_readonly/mod_storage_metronome_readonly.lua	Mon Jan 27 21:33:18 2025 +0100
+++ b/mod_storage_metronome_readonly/mod_storage_metronome_readonly.lua	Tue Jan 28 00:35:39 2025 +0100
@@ -5,6 +5,7 @@
 local gen_id = require "prosody.util.id".medium;
 local set = require "prosody.util.set";
 local envloadfile = require"prosody.util.envload".envloadfile;
+local dir = require "lfs".dir;
 
 local host = module.host;
 
@@ -163,6 +164,52 @@
 	return datamanager.users(host, store, self.type);
 end
 
+local function parse_logs(logs, is_muc)
+	local iter = ipairs(logs);
+	local i = 0;
+	local message;
+	return function()
+		i, message = iter(logs, i);
+		if not message then
+			return;
+		end
+
+		local with;
+		if is_muc then
+			with = message["resource"];
+		else
+			local bare_to = message["bare_to"];
+			local bare_from = message["bare_from"];
+			if jid == bare_to then
+				-- received
+				with = bare_from;
+			else
+				-- sent
+				with = bare_to;
+			end
+		end
+
+		local to = message["to"];
+		local from = message["from"];
+		local id = message["id"];
+		local type = message["type"];
+
+		local key = message["uid"];
+		local when = message["timestamp"];
+		local item = st.message({ to = to, from = from, id = id, type = type }, message["body"]);
+		if message["tags"] then
+			for _, tag in ipairs(message["tags"]) do
+				setmetatable(tag, st.stanza_mt);
+				item:add_direct_child(tag);
+			end
+		end
+		if message["marker"] then
+			item:tag(message["marker"], { xmlns = "urn:xmpp:chat-markers:0", id = message["marker_id"] });
+		end
+		return key, item, when, with;
+	end;
+end
+
 local archive = {};
 driver.archive = { __index = archive };
 
@@ -181,45 +228,7 @@
 	if self.store == "archive" then
 		local jid = username.."@"..host;
 		local data = datamanager.load(username, host, "archiving");
-		local iter = ipairs(data["logs"]);
-		local i = 0;
-		local message;
-		return function()
-			i, message = iter(data["logs"], i);
-			if not message then
-				return;
-			end
-
-			local with;
-			local bare_to = message["bare_to"];
-			local bare_from = message["bare_from"];
-			if jid == bare_to then
-				-- received
-				with = bare_from;
-			else
-				-- sent
-				with = bare_to;
-			end
-
-			local to = message["to"];
-			local from = message["from"];
-			local id = message["id"];
-			local type = message["type"];
-
-			local key = message["uid"];
-			local when = message["timestamp"];
-			local item = st.message({ to = to, from = from, id = id, type = type }, message["body"]);
-			if message["tags"] then
-				for _, tag in ipairs(message["tags"]) do
-					setmetatable(tag, st.stanza_mt);
-					item:add_direct_child(tag);
-				end
-			end
-			if message["marker"] then
-				item:tag(message["marker"], { xmlns = "urn:xmpp:chat-markers:0", id = message["marker_id"] });
-			end
-			return key, item, when, with;
-		end;
+		return parse_logs(data["logs"]);
 
 	elseif self.store:sub(1, 4) == "pep_" then
 		local node = self.store:sub(5);
@@ -249,6 +258,7 @@
 			local with = data["data_author"][key];
 			return key, item, time_now, with;
 		end;
+
 	elseif self.store == "offline" then
 		-- This is mostly copy/pasted from mod_storage_internal.
 		local list, err = datamanager.list_open(username, host, self.store);
@@ -284,6 +294,7 @@
 			item = st.deserialize(item);
 			return key, item, when, with;
 		end
+
 	elseif self.store == "uploads" then
 		local list = {};
 
@@ -322,6 +333,44 @@
 			local stanza = payload[3];
 			return key, stanza, when, with;
 		end;
+
+	elseif self.store == "muc_log" then
+		local base_path = datamanager.getpath("", host, "stanza_log"):sub(1, -5);
+		local list = {};
+		for dir_name in dir(base_path) do
+			if dir_name ~= "." and dir_name ~= ".." then
+				local path = base_path..dir_name.."/"..encode(username)..".dat";
+				local get_data = envloadfile(path, {});
+				if get_data then
+					local success, data = pcall(get_data);
+					if not success then
+						module:log("error", "Unable to load metronome storage");
+						return nil, "Error reading storage";
+					end
+					for key, item, when, with in parse_logs(data, true) do
+						table.insert(list, {key, item, when, with});
+					end
+				end
+			end
+		end
+
+		local i = 0;
+		local iter = function()
+			i = i + 1;
+			return list[i];
+		end
+
+		return function()
+			local item = iter();
+			if item == nil then
+				if list.close then
+					list:close();
+				end
+				return
+			end
+			return item[1], item[2], item[3], item[4];
+		end
+
 	else
 		return nil, "unsupported-store";
 	end
@@ -380,6 +429,17 @@
 				return "";
 			end
 		end;
+	elseif self.store == "muc_log" then
+		local iter, tbl = pairs(datamanager.load(nil, host, "persistent"));
+		local jid = nil;
+		return function()
+			jid = iter(tbl, jid);
+			if not jid then
+				return;
+			end
+			local user = jid:gsub("@.*", "");
+			return user;
+		end;
 	else
 		return nil, "unsupported-store";
 	end