Mercurial > prosody-hg
comparison plugins/mod_muc_mam.lua @ 9882:18f025b3987d
Merge 0.11->trunk
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Fri, 22 Mar 2019 17:58:08 +0100 |
| parents | e1d68f32ce29 78885b1bbb91 |
| children | 189b00a782bf |
comparison
equal
deleted
inserted
replaced
| 9878:dd61201fc5af | 9882:18f025b3987d |
|---|---|
| 28 | 28 |
| 29 local is_stanza = st.is_stanza; | 29 local is_stanza = st.is_stanza; |
| 30 local tostring = tostring; | 30 local tostring = tostring; |
| 31 local time_now = os.time; | 31 local time_now = os.time; |
| 32 local m_min = math.min; | 32 local m_min = math.min; |
| 33 local timestamp, timestamp_parse = require "util.datetime".datetime, require "util.datetime".parse; | 33 local timestamp, timestamp_parse, datestamp = import( "util.datetime", "datetime", "parse", "date"); |
| 34 local default_max_items, max_max_items = 20, module:get_option_number("max_archive_query_results", 50); | 34 local default_max_items, max_max_items = 20, module:get_option_number("max_archive_query_results", 50); |
| 35 | 35 |
| 36 local default_history_length = 20; | 36 local default_history_length = 20; |
| 37 local max_history_length = module:get_option_number("max_history_messages", math.huge); | 37 local max_history_length = module:get_option_number("max_history_messages", math.huge); |
| 38 | 38 |
| 39 local function get_historylength(room) | 39 local function get_historylength(room) |
| 40 return math.min(room._data.history_length or default_history_length, max_history_length); | 40 return math.min(room._data.history_length or default_history_length, max_history_length); |
| 41 end | |
| 42 | |
| 43 function schedule_cleanup() | |
| 44 -- replaced by non-noop later if cleanup is enabled | |
| 41 end | 45 end |
| 42 | 46 |
| 43 local log_all_rooms = module:get_option_boolean("muc_log_all_rooms", false); | 47 local log_all_rooms = module:get_option_boolean("muc_log_all_rooms", false); |
| 44 local log_by_default = module:get_option_boolean("muc_log_by_default", true); | 48 local log_by_default = module:get_option_boolean("muc_log_by_default", true); |
| 45 | 49 |
| 354 | 358 |
| 355 -- And stash it | 359 -- And stash it |
| 356 local id = archive:append(room_node, nil, stored_stanza, time_now(), with); | 360 local id = archive:append(room_node, nil, stored_stanza, time_now(), with); |
| 357 | 361 |
| 358 if id then | 362 if id then |
| 363 schedule_cleanup(room_node); | |
| 359 stanza:add_direct_child(st.stanza("stanza-id", { xmlns = xmlns_st_id, by = self.jid, id = id })); | 364 stanza:add_direct_child(st.stanza("stanza-id", { xmlns = xmlns_st_id, by = self.jid, id = id })); |
| 360 end | 365 end |
| 361 end | 366 end |
| 362 | 367 |
| 363 module:hook("muc-add-history", function (event) | 368 module:hook("muc-add-history", function (event) |
| 389 module:add_feature(xmlns_mam); | 394 module:add_feature(xmlns_mam); |
| 390 | 395 |
| 391 module:hook("muc-disco#info", function(event) | 396 module:hook("muc-disco#info", function(event) |
| 392 event.reply:tag("feature", {var=xmlns_mam}):up(); | 397 event.reply:tag("feature", {var=xmlns_mam}):up(); |
| 393 end); | 398 end); |
| 399 | |
| 400 -- Cleanup | |
| 401 | |
| 402 local cleanup_after = module:get_option_string("muc_log_expires_after", "1w"); | |
| 403 local cleanup_interval = module:get_option_number("muc_log_cleanup_interval", 4 * 60 * 60); | |
| 404 | |
| 405 if cleanup_after ~= "never" then | |
| 406 local cleanup_storage = module:open_store("muc_log_cleanup"); | |
| 407 local cleanup_map = module:open_store("muc_log_cleanup", "map"); | |
| 408 | |
| 409 local day = 86400; | |
| 410 local multipliers = { d = day, w = day * 7, m = 31 * day, y = 365.2425 * day }; | |
| 411 local n, m = cleanup_after:lower():match("(%d+)%s*([dwmy]?)"); | |
| 412 if not n then | |
| 413 module:log("error", "Could not parse muc_log_expires_after string %q", cleanup_after); | |
| 414 return false; | |
| 415 end | |
| 416 | |
| 417 cleanup_after = tonumber(n) * ( multipliers[m] or 1 ); | |
| 418 | |
| 419 module:log("debug", "muc_log_expires_after = %d -- in seconds", cleanup_after); | |
| 420 | |
| 421 if not archive.delete then | |
| 422 module:log("error", "muc_log_expires_after set but mod_%s does not support deleting", archive._provided_by); | |
| 423 return false; | |
| 424 end | |
| 425 | |
| 426 -- For each day, store a set of rooms that have new messages. To expire | |
| 427 -- messages, we collect the union of sets of rooms from dates that fall | |
| 428 -- outside the cleanup range. | |
| 429 | |
| 430 function schedule_cleanup(roomname, date) | |
| 431 cleanup_map:set(date or datestamp(), roomname, true); | |
| 432 end | |
| 433 | |
| 434 cleanup_runner = require "util.async".runner(function () | |
| 435 local rooms = {}; | |
| 436 local cut_off = datestamp(os.time() - cleanup_after); | |
| 437 for date in cleanup_storage:users() do | |
| 438 if date <= cut_off then | |
| 439 module:log("debug", "Messages from %q should be expired", date); | |
| 440 local messages_this_day = cleanup_storage:get(date); | |
| 441 if messages_this_day then | |
| 442 for room in pairs(messages_this_day) do | |
| 443 rooms[room] = true; | |
| 444 end | |
| 445 if date < cut_off then | |
| 446 -- Messages from the same day as the cut-off might not have expired yet, | |
| 447 -- but all earlier will have, so clear storage for those days. | |
| 448 cleanup_storage:set(date, nil); | |
| 449 end | |
| 450 end | |
| 451 end | |
| 452 end | |
| 453 local sum, num_rooms = 0, 0; | |
| 454 for room in pairs(rooms) do | |
| 455 local ok, err = archive:delete(room, { ["end"] = os.time() - cleanup_after; }) | |
| 456 if ok then | |
| 457 num_rooms = num_rooms + 1; | |
| 458 sum = sum + (tonumber(ok) or 0); | |
| 459 end | |
| 460 end | |
| 461 module:log("info", "Deleted %d expired messages for %d rooms", sum, num_rooms); | |
| 462 end); | |
| 463 | |
| 464 cleanup_task = module:add_timer(1, function () | |
| 465 cleanup_runner:run(true); | |
| 466 return cleanup_interval; | |
| 467 end); | |
| 468 else | |
| 469 module:log("debug", "Archive expiry disabled"); | |
| 470 end |
