local st = require "util.stanza"; local datetime = require"util.datetime"; local jid_split = require"util.jid".split; local nodeprep = require"util.encodings".stringprep.nodeprep; local uuid = require"util.uuid".generate; local it = require"util.iterators"; local gettime = require"socket".gettime; local archive = module:open_store("archive2", "archive"); -- Support both old and new MUC code local mod_muc = module:depends"muc"; local rooms = rawget(mod_muc, "rooms"); local each_room = rawget(mod_muc, "each_room") or function() return it.values(rooms); end; if not rooms then rooms = module:shared"muc/rooms"; end local get_room_from_jid = rawget(mod_muc, "get_room_from_jid") or function (jid) return rooms[jid]; end local function get_room(name) local jid = name .. '@' .. module.host; return get_room_from_jid(jid); end module:depends"http"; local function template(data) local _doc = [[ Like util.template, but deals with plain text Returns a closure that is called with a table of values {name} is substituted for values["name"] and is XML escaped {name!} is substituted without XML escaping {name?} is optional and is replaced with an empty string if no value exists ]] return function(values) return (data:gsub("{([^!}]-)(%p?)}", function (name, opt) local value = values[name]; if value then if opt ~= "!" then return st.xml_escape(value); end return value; elseif opt == "?" then return ""; end end)); end end local base = template[[ {title}

{title}

{body!} ]] local dates_template = template(base{ title = "Logs for room {room}"; body = [[ ]]; }) local date_line_template = template[[
  • {date}
  • ]]; local page_template = template(base{ title = "Logs for room {room} on {date}"; body = [[ ]]; }); local line_templates = { ["message
    {nick}
    {body}
    ]]; ["message
    {nick}
    changed subject to {subject}
    ]]; ["presence"] = template[[
  • {nick}
    joined
  • ]]; ["presence
    {nick}
    left
    ]]; }; local room_list_template = template(base{ title = "Rooms on {host}"; body = [[
    {rooms!}
    ]]; }); local room_item_template = template[[
    {name}
    {description?}
    ]]; local function public_room(room) if type(room) == "string" then room = get_room(room); end return room and not room:get_hidden() and not room:get_members_only() and room._data.logging ~= false; end -- FIXME Invent some more efficient API for this local function dates_page(event, path) local request, response = event.request, event.response; local room = nodeprep(path:match("^(.*)/$")); if not room or not public_room(room) then return end local dates, i = {}, 1; module:log("debug", "Find all dates with messages"); local next_day; repeat local iter = archive:find(room, { ["start"] = next_day; limit = 1; }) if not iter then break end next_day = nil; for key, message, when in iter do next_day = datetime.date(when); dates[i], i = date_line_template{ date = next_day; }, i + 1; next_day = datetime.parse(next_day .. "T23:59:59Z") + 1; break; end until not next_day; return dates_template{ room = room; lines = table.concat(dates); }; end local function logs_page(event, path) local request, response = event.request, event.response; local room, date = path:match("^(.-)/(%d%d%d%d%-%d%d%-%d%d)$"); room = nodeprep(room); if not room then return dates_page(event, path); end if not public_room(room) then return end local logs, i = {}, 1; local iter, err = archive:find(room, { ["start"] = datetime.parse(date.."T00:00:00Z"); ["end"] = datetime.parse(date.."T23:59:59Z"); limit = math.huge; -- with = "message