# HG changeset patch # User Kim Alvefur # Date 1415458317 -3600 # Node ID f9f8bf82ece71ac4dbe3bc7e927b98b41412d214 # Parent d3c847070618e1f8a045f9ce742eae21d53136eb mod_http_muc_log: MUC log module using new archive API diff -r d3c847070618 -r f9f8bf82ece7 mod_http_muc_log/mod_http_muc_log.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_http_muc_log/mod_http_muc_log.lua Sat Nov 08 15:51:57 2014 +0100 @@ -0,0 +1,320 @@ +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, room) + local request, response = event.request, event.response; + + room = nodeprep(room); + 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