Mercurial > prosody-modules
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 |
