Software /
code /
prosody-modules
Changeset
6198:7205e0348bbe
mod_muc_log_http: Delete because obsolete
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sun, 09 Feb 2025 17:17:10 +0100 |
parents | 6197:ba8f5cdc1676 |
children | 6199:fe8222112cf4 |
files | mod_muc_log_http/README.md mod_muc_log_http/muc_log_http/mod_muc_log_http.lua mod_muc_log_http/muc_log_http/themes/prosody/components_bit.html mod_muc_log_http/muc_log_http/themes/prosody/components_body.html mod_muc_log_http/muc_log_http/themes/prosody/day_bann.html mod_muc_log_http/muc_log_http/themes/prosody/day_body.html mod_muc_log_http/muc_log_http/themes/prosody/day_bodynp.html mod_muc_log_http/muc_log_http/themes/prosody/day_dayLink.html mod_muc_log_http/muc_log_http/themes/prosody/day_kick.html mod_muc_log_http/muc_log_http/themes/prosody/day_message.html mod_muc_log_http/muc_log_http/themes/prosody/day_messageMe.html mod_muc_log_http/muc_log_http/themes/prosody/day_presence_join.html mod_muc_log_http/muc_log_http/themes/prosody/day_presence_leave.html mod_muc_log_http/muc_log_http/themes/prosody/day_presence_statusChange.html mod_muc_log_http/muc_log_http/themes/prosody/day_presence_statusText.html mod_muc_log_http/muc_log_http/themes/prosody/day_reason.html mod_muc_log_http/muc_log_http/themes/prosody/day_time.html mod_muc_log_http/muc_log_http/themes/prosody/day_title.html mod_muc_log_http/muc_log_http/themes/prosody/day_titleChange.html mod_muc_log_http/muc_log_http/themes/prosody/days_bit.html mod_muc_log_http/muc_log_http/themes/prosody/days_body.html mod_muc_log_http/muc_log_http/themes/prosody/days_rooms_bit.html mod_muc_log_http/muc_log_http/themes/prosody/doc.html mod_muc_log_http/muc_log_http/themes/prosody/month_day.html mod_muc_log_http/muc_log_http/themes/prosody/month_emptyDay.html mod_muc_log_http/muc_log_http/themes/prosody/month_footer.html mod_muc_log_http/muc_log_http/themes/prosody/month_header.html mod_muc_log_http/muc_log_http/themes/prosody/month_weekDay.html mod_muc_log_http/muc_log_http/themes/prosody/rooms_bit.html mod_muc_log_http/muc_log_http/themes/prosody/rooms_body.html mod_muc_log_http/muc_log_http/themes/prosody/year_title.html |
diffstat | 31 files changed, 7 insertions(+), 955 deletions(-) [+] |
line wrap: on
line diff
--- a/mod_muc_log_http/README.md Sun Feb 09 17:15:27 2025 +0100 +++ b/mod_muc_log_http/README.md Sun Feb 09 17:17:10 2025 +0100 @@ -1,9 +1,15 @@ --- labels: -- 'Stage-Beta' +- 'Stage-Obsolete' summary: Provides a web interface to stored chatroom logs ... +::: {.alert .alert-danger} +This module depends on an obsolete module for storing data in an inefficient format. + +For a modern approach, see [mod_http_muc_log] which relies on [mod_muc_mam][doc:modules:mod_muc_mam]. +::: + Introduction ============
--- a/mod_muc_log_http/muc_log_http/mod_muc_log_http.lua Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,759 +0,0 @@ -module:depends("http"); - -local prosody = prosody; -local hosts = prosody.hosts; -local my_host = module:get_host(); -local strchar = string.char; -local strformat = string.format; -local split_jid = require "util.jid".split; -local config_get = require "core.configmanager".get; -local urldecode = require "net.http".urldecode; -local http_event = require "net.http.server".fire_event; -local datamanager = require"core.storagemanager".olddm; -local data_load, data_getpath = datamanager.load, datamanager.getpath; -local datastore = "muc_log"; -local url_base = "muc_log"; -local config = nil; -local table, tostring, tonumber = table, tostring, tonumber; -local os_date, os_time = os.date, os.time; -local str_format = string.format; -local io_open = io.open; -local themes_parent = (module.path and module.path:gsub("[/\\][^/\\]*$", "") or (prosody.paths.plugins or "./plugins") .. "/muc_log_http") .. "/themes"; - -local lom = require "lxp.lom"; -local lfs = require "lfs"; -local html = {}; -local theme; - --- Helper Functions - -local p_encode = datamanager.path_encode; -local function store_exists(node, host, today) - if lfs.attributes(data_getpath(node, host, datastore .. "/" .. today), "mode") then return true; else return false; end -end - --- Module Definitions - -local function html_escape(t) - if t then - t = t:gsub("<", "<"); - t = t:gsub(">", ">"); - t = t:gsub("(http://[%a%d@%.:/&%?=%-_#%%~]+)", function(h) - h = urlunescape(h) - return "<a href='" .. h .. "'>" .. h .. "</a>"; - end); - t = t:gsub("\n", "<br />"); - t = t:gsub("%%", "%%%%"); - else - t = ""; - end - return t; -end - -function create_doc(body, title) - if not body then return "" end - body = body:gsub("%%", "%%%%"); - return html.doc:gsub("###BODY_STUFF###", body) - :gsub("<title>muc_log</title>", "<title>"..(title and html_escape(title) or "Chatroom logs").."</title>"); -end - -function urlunescape (url) - url = url:gsub("+", " ") - url = url:gsub("%%(%x%x)", function(h) return strchar(tonumber(h,16)) end) - url = url:gsub("\r\n", "\n") - return url -end -local function urlencode(s) - return s and (s:gsub("[^a-zA-Z0-9.~_-]", function (c) return ("%%%02x"):format(c:byte()); end)); -end - -local function get_room_from_jid(jid) - local node, host = split_jid(jid); - local component = hosts[host]; - if component then - local muc = component.modules.muc - if muc and rawget(muc,"rooms") then - -- We're running 0.9.x or 0.10 (old MUC API) - return muc.rooms[jid]; - elseif muc and rawget(muc,"get_room_from_jid") then - -- We're running >0.10 (new MUC API) - return muc.get_room_from_jid(jid); - else - return - end - end -end - -local function get_room_list(host) - local component = hosts[host]; - local list = {}; - if component then - local muc = component.modules.muc - if muc and rawget(muc,"rooms") then - -- We're running 0.9.x or 0.10 (old MUC API) - for _, room in pairs(muc.rooms) do - list[room.jid] = room; - end - return list; - elseif muc and rawget(muc,"each_room") then - -- We're running >0.10 (new MUC API) - for room, _ in muc.each_room() do - list[room.jid] = room; - end - return list; - end - end -end - -local function generate_room_list(host) - local rooms; - - for jid, room in pairs(get_room_list(host)) do - local node = split_jid(jid); - if not room._data.hidden and room._data.logging and node then - rooms = (rooms or "") .. html.rooms.bit:gsub("###ROOM###", urlencode(node)):gsub("###COMPONENT###", host); - end - end - - if rooms then - return html.rooms.body:gsub("###ROOMS_STUFF###", rooms):gsub("###COMPONENT###", host), "Chatroom logs for "..host; - end -end - --- Calendar stuff -local function get_days_for_month(month, year) - if month == 2 then - local is_leap_year = (year % 4 == 0 and year % 100 ~= 0) or year % 400 == 0; - return is_leap_year and 29 or 28; - elseif (month < 8 and month%2 == 1) or (month >= 8 and month%2 == 0) then - return 31; - end - return 30; -end - -local function create_month(month, year, callback) - local html_str = html.month.header; - local days = get_days_for_month(month, year); - local time = os_time{year=year, month=month, day=1}; - local dow = tostring(os_date("%a", time)) - local title = tostring(os_date("%B", time)); - local week_days = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; - local week_day = 0; - local weeks = 1; - local _available_for_one_day = false; - - local week_days_html = ""; - for _, tmp in ipairs(week_days) do - week_days_html = week_days_html .. html.month.weekDay:gsub("###DAY###", tmp) .. "\n"; - end - - html_str = html_str:gsub("###TITLE###", title):gsub("###WEEKDAYS###", week_days_html); - - for i = 1, 31 do - week_day = week_day + 1; - if week_day == 1 then html_str = html_str .. "<tr>\n"; end - if i == 1 then - for _, tmp in ipairs(week_days) do - if dow ~= tmp then - html_str = html_str .. html.month.emptyDay .. "\n"; - week_day = week_day + 1; - else - break; - end - end - end - if i < days + 1 then - local tmp = tostring(i); - if callback and callback.callback then - tmp = callback.callback(callback.path, i, month, year, callback.room, callback.webpath); - end - if tmp == nil then - tmp = tostring(i); - else - _available_for_one_day = true; - end - html_str = html_str .. html.month.day:gsub("###DAY###", tmp) .. "\n"; - end - - if i >= days then - break; - end - - if week_day == 7 then - week_day = 0; - weeks = weeks + 1; - html_str = html_str .. "</tr>\n"; - end - end - - if week_day + 1 < 8 or weeks < 6 then - week_day = week_day + 1; - if week_day > 7 then - week_day = 1; - end - if week_day == 1 then - weeks = weeks + 1; - end - for y = weeks, 6 do - if week_day == 1 then - html_str = html_str .. "<tr>\n"; - end - for i = week_day, 7 do - html_str = html_str .. html.month.emptyDay .. "\n"; - end - week_day = 1 - html_str = html_str .. "</tr>\n"; - end - end - html_str = html_str .. html.month.footer; - if _available_for_one_day then - return html_str; - end -end - -local function create_year(year, callback) - local year = year; - local tmp; - if tonumber(year) <= 99 then - year = year + 2000; - end - local html_str = ""; - for i=1, 12 do - tmp = create_month(i, year, callback); - if tmp then - html_str = html_str .. "<div style='float: left; padding: 5px;'>\n" .. tmp .. "</div>\n"; - end - end - if html_str ~= "" then - return "<div name='yearDiv' style='padding: 40px; text-align: center;'>" .. html.year.title:gsub("###YEAR###", tostring(year)) .. html_str .. "</div><br style='clear:both;'/> \n"; - end - return ""; -end - -local function day_callback(path, day, month, year, room, webpath) - local webpath = webpath or "" - local year = year; - if year > 2000 then - year = year - 2000; - end - local bare_day = str_format("20%.02d-%.02d-%.02d", year, month, day); - room = p_encode(room); - local attributes, err = lfs.attributes(path.."/"..str_format("%.02d%.02d%.02d", year, month, day).."/"..room..".dat"); - if attributes ~= nil and attributes.mode == "file" then - local s = html.days.bit; - s = s:gsub("###BARE_DAY###", webpath .. bare_day); - s = s:gsub("###DAY###", day); - return s; - end - return; -end - -local function generate_day_room_content(bare_room_jid) - local days = ""; - local days_array = {}; - local tmp; - local node, host = split_jid(bare_room_jid); - local path = data_getpath(node, host, datastore); - local room = nil; - local next_room = ""; - local previous_room = ""; - local rooms = ""; - local attributes = nil; - local since = ""; - local to = ""; - local topic = ""; - local component = hosts[host]; - - if not(get_room_from_jid(bare_room_jid)) then - return; - end - - path = path:gsub("/[^/]*$", ""); - attributes = lfs.attributes(path); - do - local found = 0; - module:log("debug", generate_room_list(host)); - for jid, room in pairs(get_room_list(host)) do - local node = split_jid(jid) - if not room._data.hidden and room._data.logging and node then - if found == 0 then - previous_room = node - elseif found == 1 then - next_room = node - found = -1 - end - if jid == bare_room_jid then - found = 1 - end - - rooms = rooms .. html.days.rooms.bit:gsub("###ROOM###", urlencode(node)); - end - end - - room = get_room_from_jid(bare_room_jid); - if room._data.hidden or not room._data.logging then - room = nil; - end - end - if attributes and room then - local already_done_years = {}; - topic = room._data.subject or "(no subject)" - if topic:len() > 135 then - topic = topic:sub(1, topic:find(" ", 120)) .. " ..." - end - local folders = {}; - for folder in lfs.dir(path) do table.insert(folders, folder); end - table.sort(folders); - for _, folder in ipairs(folders) do - local year, month, day = folder:match("^(%d%d)(%d%d)(%d%d)"); - if year then - to = tostring(os_date("%B %Y", os_time({ day=tonumber(day), month=tonumber(month), year=2000+tonumber(year) }))); - if since == "" then since = to; end - if not already_done_years[year] then - module:log("debug", "creating overview for: %s", to); - days = create_year(year, {callback=day_callback, path=path, room=node}) .. days; - already_done_years[year] = true; - end - end - end - end - - tmp = html.days.body:gsub("###DAYS_STUFF###", days); - tmp = tmp:gsub("###PREVIOUS_ROOM###", previous_room == "" and node or previous_room); - tmp = tmp:gsub("###NEXT_ROOM###", next_room == "" and node or next_room); - tmp = tmp:gsub("###ROOMS###", rooms); - tmp = tmp:gsub("###ROOMTOPIC###", topic); - tmp = tmp:gsub("###SINCE###", since); - tmp = tmp:gsub("###TO###", to); - return tmp:gsub("###JID###", bare_room_jid), "Chatroom logs for "..bare_room_jid; -end - -local function parse_iq(stanza, time, nick) - local text = nil; - local victim = nil; - if(stanza.attr.type == "set") then - for _,tag in ipairs(stanza) do - if tag.tag == "query" then - for _,item in ipairs(tag) do - if item.tag == "item" and item.attr.nick ~= nil and item.attr.role == 'none' then - victim = item.attr.nick; - for _,reason in ipairs(item) do - if reason.tag == "reason" then - text = reason[1]; - break; - end - end - break; - end - end - break; - end - end - if victim then - if text then - text = html.day.reason:gsub("###REASON###", html_escape(text)); - else - text = ""; - end - return html.day.kick:gsub("###TIME_STUFF###", time):gsub("###VICTIM###", victim):gsub("###REASON_STUFF###", text); - end - end - return; -end - -local function parse_presence(stanza, time, nick) - local ret = ""; - local show_join = "block" - - if config and not config.show_join then - show_join = "none"; - end - - if stanza.attr.type == nil then - local show_status = "block" - if config and not config.show_status then - show_status = "none"; - end - local show, status = nil, ""; - local already_joined = false; - for _, tag in ipairs(stanza) do - if tag.tag == "alreadyJoined" then - already_joined = true; - elseif tag.tag == "show" then - show = tag[1]; - elseif tag.tag == "status" and tag[1] ~= nil then - status = tag[1]; - end - end - if already_joined == true then - if show == nil then - show = "online"; - end - ret = html.day.presence.statusChange:gsub("###TIME_STUFF###", time); - if status ~= "" then - status = html.day.presence.statusText:gsub("###STATUS###", html_escape(status)); - end - ret = ret:gsub("###SHOW###", show):gsub("###NICK###", nick):gsub("###SHOWHIDE###", show_status):gsub("###STATUS_STUFF###", status); - else - ret = html.day.presence.join:gsub("###TIME_STUFF###", time):gsub("###SHOWHIDE###", show_join):gsub("###NICK###", nick); - end - elseif stanza.attr.type == "unavailable" then - - ret = html.day.presence.leave:gsub("###TIME_STUFF###", time):gsub("###SHOWHIDE###", show_join):gsub("###NICK###", nick); - end - return ret; -end - -local function parse_message(stanza, time, nick) - local body, title, ret = nil, nil, ""; - - for _,tag in ipairs(stanza) do - if tag.tag == "body" then - body = tag[1]; - if nick then - break; - end - elseif tag.tag == "nick" and nick == nil then - nick = html_escape(tag[1]); - if body or title then - break; - end - elseif tag.tag == "subject" then - title = tag[1]; - if nick then - break; - end - end - end - if nick and body then - body = html_escape(body); - local me = body:find("^/me"); - local template = ""; - if not me then - template = html.day.message; - else - template = html.day.messageMe; - body = body:gsub("^/me ", ""); - end - ret = template:gsub("###TIME_STUFF###", time):gsub("###NICK###", nick):gsub("###MSG###", body); - elseif nick and title then - title = html_escape(title); - ret = html.day.titleChange:gsub("###TIME_STUFF###", time):gsub("###NICK###", nick):gsub("###TITLE###", title); - end - return ret; -end - -local function increment_day(bare_day) - local year, month, day = bare_day:match("^20(%d%d)-(%d%d)-(%d%d)$"); - local leapyear = false; - module:log("debug", tostring(day).."/"..tostring(month).."/"..tostring(year)) - - day = tonumber(day); - month = tonumber(month); - year = tonumber(year); - - if year%4 == 0 and year%100 == 0 then - if year%400 == 0 then - leapyear = true; - else - leapyear = false; -- turn of the century but not a leapyear - end - elseif year%4 == 0 then - leapyear = true; - end - - if (month == 2 and leapyear and day + 1 > 29) or - (month == 2 and not leapyear and day + 1 > 28) or - (month < 8 and month%2 == 1 and day + 1 > 31) or - (month < 8 and month%2 == 0 and day + 1 > 30) or - (month >= 8 and month%2 == 0 and day + 1 > 31) or - (month >= 8 and month%2 == 1 and day + 1 > 30) - then - if month + 1 > 12 then - year = year + 1; - month = 1; - day = 1; - else - month = month + 1; - day = 1; - end - else - day = day + 1; - end - return strformat("20%.02d-%.02d-%.02d", year, month, day); -end - -local function find_next_day(bare_room_jid, bare_day) - local node, host = split_jid(bare_room_jid); - local day = increment_day(bare_day); - local max_trys = 7; - - module:log("debug", day); - while(not store_exists(node, host, day)) do - max_trys = max_trys - 1; - if max_trys == 0 then - break; - end - day = increment_day(day); - end - if max_trys == 0 then - return nil; - else - return day; - end -end - -local function decrement_day(bare_day) - local year, month, day = bare_day:match("^20(%d%d)-(%d%d)-(%d%d)$"); - local leapyear = false; - module:log("debug", tostring(day).."/"..tostring(month).."/"..tostring(year)) - - day = tonumber(day); - month = tonumber(month); - year = tonumber(year); - - if year%4 == 0 and year%100 == 0 then - if year%400 == 0 then - leapyear = true; - else - leapyear = false; -- turn of the century but not a leapyear - end - elseif year%4 == 0 then - leapyear = true; - end - - if day - 1 == 0 then - if month - 1 == 0 then - year = year - 1; - month = 12; - day = 31; - else - month = month - 1; - if (month == 2 and leapyear) then day = 29 - elseif (month == 2 and not leapyear) then day = 28 - elseif (month < 8 and month%2 == 1) or (month >= 8 and month%2 == 0) then day = 31 - else day = 30 - end - end - else - day = day - 1; - end - return strformat("20%.02d-%.02d-%.02d", year, month, day); -end - -local function find_previous_day(bare_room_jid, bare_day) - local node, host = split_jid(bare_room_jid); - local day = decrement_day(bare_day); - local max_trys = 7; - module:log("debug", day); - while(not store_exists(node, host, day)) do - max_trys = max_trys - 1; - if max_trys == 0 then - break; - end - day = decrement_day(day); - end - if max_trys == 0 then - return nil; - else - return day; - end -end - -local function parse_day(bare_room_jid, room_subject, bare_day) - local ret = ""; - local year; - local month; - local day; - local tmp; - local node, host = split_jid(bare_room_jid); - local year, month, day = bare_day:match("^20(%d%d)-(%d%d)-(%d%d)$"); - local previous_day = find_previous_day(bare_room_jid, bare_day); - local next_day = find_next_day(bare_room_jid, bare_day); - local temptime = {day=0, month=0, year=0}; - local path = data_getpath(node, host, datastore); - path = path:gsub("/[^/]*$", ""); - local calendar = "" - - if tonumber(year) <= 99 then - year = year + 2000; - end - - temptime.day = tonumber(day) - temptime.month = tonumber(month) - temptime.year = tonumber(year) - calendar = create_month(temptime.month, temptime.year, {callback=day_callback, path=path, room=node, webpath="../"}) or "" - - if bare_day then - local data = data_load(node, host, datastore .. "/" .. bare_day:match("^20(.*)"):gsub("-", "")); - if data then - for i=1, #data, 1 do - local stanza = lom.parse(data[i]); - if stanza and stanza.attr and stanza.attr.time then - local timeStuff = html.day.time:gsub("###TIME###", stanza.attr.time):gsub("###UTC###", stanza.attr.utc or stanza.attr.time); - if stanza[1] ~= nil then - local nick; - local tmp; - - -- grep nick from "from" resource - if stanza[1].attr.from then -- presence and messages - nick = html_escape(stanza[1].attr.from:match("/(.+)$")); - elseif stanza[1].attr.to then -- iq - nick = html_escape(stanza[1].attr.to:match("/(.+)$")); - end - - if stanza[1].tag == "presence" and nick then - tmp = parse_presence(stanza[1], timeStuff, nick); - elseif stanza[1].tag == "message" then - tmp = parse_message(stanza[1], timeStuff, nick); - elseif stanza[1].tag == "iq" then - tmp = parse_iq(stanza[1], timeStuff, nick); - else - module:log("info", "unknown stanza subtag in log found. room: %s; day: %s", bare_room_jid, year .. "/" .. month .. "/" .. day); - end - if tmp then - ret = ret .. tmp - tmp = nil; - end - end - end - end - end - if ret ~= "" then - if next_day then - next_day = html.day.dayLink:gsub("###DAY###", next_day):gsub("###TEXT###", ">") - end - if previous_day then - previous_day = html.day.dayLink:gsub("###DAY###", previous_day):gsub("###TEXT###", "<"); - end - ret = ret:gsub("%%", "%%%%"); - if config.show_presences then - tmp = html.day.body:gsub("###DAY_STUFF###", ret):gsub("###JID###", bare_room_jid); - else - tmp = html.day.bodynp:gsub("###DAY_STUFF###", ret):gsub("###JID###", bare_room_jid); - end - tmp = tmp:gsub("###CALENDAR###", calendar); - tmp = tmp:gsub("###DATE###", tostring(os_date("%A, %B %d, %Y", os_time(temptime)))); - tmp = tmp:gsub("###TITLE_STUFF###", html.day.title:gsub("###TITLE###", room_subject)); - tmp = tmp:gsub("###STATUS_CHECKED###", config.show_status and "checked='checked'" or ""); - tmp = tmp:gsub("###JOIN_CHECKED###", config.show_join and "checked='checked'" or ""); - tmp = tmp:gsub("###NEXT_LINK###", next_day or ""); - tmp = tmp:gsub("###PREVIOUS_LINK###", previous_day or ""); - - return tmp, "Chatroom logs for "..bare_room_jid.." ("..tostring(os_date("%A, %B %d, %Y", os_time(temptime)))..")"; - end - end -end - -local function handle_error(code, err) return http_event("http-error", { code = code, message = err }); end -function handle_request(event) - local response = event.response; - local request = event.request; - local room; - - local node, day, more = request.url.path:match("^/"..url_base.."/+([^/]*)/*([^/]*)/*(.*)$"); - - if more ~= "" then - response.status_code = 404; - return response:send(handle_error(response.status_code, "Unknown URL.")); - end - if node == "" then node = nil; end - if day == "" then day = nil; end - - node = urldecode(node); - - if not html.doc then - response.status_code = 500; - return response:send(handle_error(response.status_code, "Muc Theme is not loaded.")); - end - - if node then room = get_room_from_jid(node.."@"..my_host); end - if node and not room then - response.status_code = 404; - return response:send(handle_error(response.status_code, "Room doesn't exist.")); - end - if room and (room._data.hidden or not room._data.logging) then - response.status_code = 404; - return response:send(handle_error(response.status_code, "There're no logs for this room.")); - end - - if not node then -- room list for component - return response:send(create_doc(generate_room_list(my_host))); - elseif not day then -- room's listing - return response:send(create_doc(generate_day_room_content(node.."@"..my_host))); - else - if not day:match("^20(%d%d)-(%d%d)-(%d%d)$") then - local y,m,d = day:match("^(%d%d)(%d%d)(%d%d)$"); - if not y then - response.status_code = 404; - return response:send(handle_error(response.status_code, "No entries for that year.")); - end - response.status_code = 301; - response.headers = { ["Location"] = request.url.path:match("^/"..url_base.."/+[^/]*").."/20"..y.."-"..m.."-"..d.."/" }; - return response:send(); - end - - local body = create_doc(parse_day(node.."@"..my_host, room._data.subject or "", day)); - if body == "" then - response.status_code = 404; - return response:send(handle_error(response.status_code, "Day entry doesn't exist.")); - end - return response:send(body); - end -end - -local function read_file(filepath) - local f,err = io_open(filepath, "r"); - if not f then return f,err; end - local t = f:read("*all"); - f:close() - return t; -end - -local function load_theme(path) - for file in lfs.dir(path) do - if file:match("%.html$") then - module:log("debug", "opening theme file: " .. file); - local content,err = read_file(path .. "/" .. file); - if not content then return content,err; end - - -- html.a.b.c = content of a_b_c.html - local tmp = html; - for idx in file:gmatch("([^_]*)_") do - tmp[idx] = tmp[idx] or {}; - tmp = tmp[idx]; - end - tmp[file:match("([^_]*)%.html$")] = content; - end - end - return true; -end - -function module.load() - config = module:get_option("muc_log_http", {}); - if module:get_option_boolean("muc_log_presences", true) then config.show_presences = true end - if config.show_status == nil then config.show_status = true; end - if config.show_join == nil then config.show_join = true; end - if config.url_base and type(config.url_base) == "string" then url_base = config.url_base; end - - theme = config.theme or "prosody"; - local theme_path = themes_parent .. "/" .. tostring(theme); - local attributes, err = lfs.attributes(theme_path); - if attributes == nil or attributes.mode ~= "directory" then - module:log("error", "Theme folder of theme \"".. tostring(theme) .. "\" isn't existing. expected Path: " .. theme_path); - return false; - end - - local themeLoaded,err = load_theme(theme_path); - if not themeLoaded then - module:log("error", "Theme \"%s\" is missing something: %s", tostring(theme), err); - return false; - end - - module:provides("http", { - default_path = url_base, - route = { - ["GET /*"] = handle_request; - } - }); -end
--- a/mod_muc_log_http/muc_log_http/themes/prosody/components_bit.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -<a href="###COMPONENT###/">###COMPONENT###</a><br /> \ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/components_body.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -<h2>Available Multi-User Chats:</h2><hr /><p> -###COMPONENTS_STUFF### -</p><hr /> \ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_bann.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -###TIME_STUFF###<span class="muc_bann"> *** ###VICTIM### got banned###REASON_STUFF###</span><br /> \ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_body.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -<div id="title"> - <div id="date">###DATE###</div> - <div id="roomjid">###JID###</div> - <div id="links">(join via <a class="component" href="xmpp:###JID###?join">client</a>)</div> -</div> -<div id="calendar"> - <div id="navigation"> - ###PREVIOUS_LINK### <a class="nav" href="../">^</a>###NEXT_LINK### - </div> - ###CALENDAR### -</div> -<div id="topic">###TITLE_STUFF###</div> -<br /> -<input id="toggleJoinLeave" type="checkbox" onclick="showHide('muc_joinLeave_container')" ###JOIN_CHECKED###/><label for="toggleJoinLeave">show/hide joins and leaves</label> -<input id="toggleStatus" type="checkbox" onclick="showHide('muc_statusChange_container')" ###STATUS_CHECKED###/><label for="toggleStatus">show/hide status changes</label> -<input id="toggleUTC" type="checkbox" onclick="changeTimeDisplay()" /><label for="toggleUTC">show time in local time, rather than in UTC</label> -<div id="main">###DAY_STUFF###</div>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_bodynp.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -<div id="title"> - <div id="date">###DATE###</div> - <div id="roomjid">###JID###</div> - <div id="links">(join via <a class="component" href="xmpp:###JID###?join">client</a>)</div> -</div> -<div id="calendar"> - <div id="navigation"> - ###PREVIOUS_LINK### <a class="nav" href="../">^</a>###NEXT_LINK### - </div> - ###CALENDAR### -</div> -<div id="topic">###TITLE_STUFF###</div> -<br /> -<input id="toggleUTC" type="checkbox" onclick="changeTimeDisplay()" /><label for="toggleUTC">show time in local time, rather than in UTC</label> -<div id="main">###DAY_STUFF###</div>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_dayLink.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -<a class="nav" href="../###DAY###/">###TEXT###</a>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_kick.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -###TIME_STUFF###<span class="muc_kick"> *** ###VICTIM### got kicked###REASON_STUFF###</span><br /> \ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_message.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -###TIME_STUFF###<span class="muc_msg_nick"><###NICK###></span> ###MSG###<br /> \ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_messageMe.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -###TIME_STUFF###<span class="muc_msg_me">*###NICK### ###MSG###</span><br /> \ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_presence_join.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -<div class="muc_joinLeave_container">###TIME_STUFF###<span class="muc_join"> *** ###NICK### has joined the room</span><br /></div>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_presence_leave.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -<div class="muc_joinLeave_container">###TIME_STUFF###<span class="muc_leave"> *** ###NICK### has left the room</span><br /></div>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_presence_statusChange.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -<div class="muc_statusChange_container">###TIME_STUFF###<span class="muc_statusChange"> *** ###NICK### shows as "###SHOW###"###STATUS_STUFF###</span><br /></div>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_presence_statusText.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ - and his status message is "###STATUS###" \ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_reason.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -, the reason was "###REASON###" \ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_time.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -<a name="###TIME###" href="####TIME###" class="timestuff">[<span name="time" id="###UTC###">###TIME###</span>]</a>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_title.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -###TITLE###
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_titleChange.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -###TIME_STUFF###<span class="muc_titleChange"> *** ###NICK### changed the title to "###TITLE###"</span><br /> \ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/days_bit.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -<a href="###BARE_DAY###/">###DAY###</a><br /> \ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/days_body.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -<div id="title"> - <div id="date">###SINCE### - ###TO###</div> - <div id="roomjid">###JID###</div> - <div id="links">(join via <a class="component" href="xmpp:###JID###?join">client</a>)</div> -</div> -<div id="calendar"> - <div id="navigation"> - <a class="nav" href="../###PREVIOUS_ROOM###/"><</a> - <a class="nav" href="../">^</a> - <a class="nav" href="../###NEXT_ROOM###/">></a> - </div> - <div class="weekday">List of rooms for this component</div> - <div id="roomList">###ROOMS###</div> -</div> -<div class="topic">###ROOMTOPIC###</div> -<div id="main"> -###DAYS_STUFF### -</div>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/days_rooms_bit.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -<a href="../###ROOM###/">###ROOM###</a><br />
--- a/mod_muc_log_http/muc_log_http/themes/prosody/doc.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -<html> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" > -<head> - <title>muc_log</title> -</head> -<script type="text/javascript"><!-- -var utc = true; -var timezoneOffset = (parseInt((new Date()).getTimezoneOffset()) * 60) * (-1); -function changeTimeDisplay() { - var eles = document.getElementsByName("time"); - utc = !utc; - for (var i = 0; i < eles.length; i++) { - var tmp = eles[i].id.split(":"); - var d; - if(tmp.length == 3) { - if(!utc) - tmp[2] = Number(tmp[2]) + timezoneOffset; - d = new Date(0, 0, 0, Number(tmp[0]), Number(tmp[1]), Number(tmp[2])); - } - else { - if(!utc) - tmp[0] = Number(tmp[0]) + timezoneOffset; - d = new Date(0, 0, 0, 0, 0, Number(tmp[0])); - } - - eles[i].innerHTML = (d.getHours() <= 9 ? "0" + d.getHours() : d.getHours()) + ":"; - eles[i].innerHTML += (d.getMinutes() <= 9 ? "0" + d.getMinutes() : d.getMinutes()) + ":"; - eles[i].innerHTML += (d.getSeconds() <= 9 ? "0" + d.getSeconds() : d.getSeconds()); - } -} - -function showHide(name) { - var eles = document.getElementsByClassName(name); - for (var i = 0; i < eles.length; i++) { - eles[i].style.display = eles[i].style.display != "none" ? "none" : ""; - } -} - -/* IE compat: */ -onload=function(){ - if (document.getElementsByClassName == undefined) { - document.getElementsByClassName = function(className) - { - var hasClassName = new RegExp("(?:^|\\s)" + className + "(?:$|\\s)"); - var allElements = document.getElementsByTagName("*"); - var results = []; - - var element; - for (var i = 0; (element = allElements[i]) != null; i++) { - var elementClass = element.className; - if (elementClass && elementClass.indexOf(className) != -1 && hasClassName.test(elementClass)) - results.push(element); - } - - return results; - } - } -} ---></script> -<style type="text/css"> -#title { - border-bottom: #f29b00 solid 3pt; padding-bottom: 3px; width: 100%; - color: #000000; font-size: 24px; font-weight: bold; font-family: sans-serif; letter-spacing: 3px; text-decoration: none; margin-bottom: 3pt; -} -#date { - float: right; -} -#links { - font-size: 9px; font-family: Verdana; letter-spacing: 1px; -} -#topic { - color: #000000; font-size: 18px; font-family: sans-serif; -} -#calendar {float: right; margin-left: 10pt;} -#navigation {text-align: center} -#roomList {padding-left: 5px; padding-right: 5px; border: 1px solid black;} - -#main {overflow: auto; border: 2px solid gray; padding: 3px; margin-top: 1em} - -a {color: #6197df; text-decoration: none;} - -a.nav {color: #6197df; font-family: monospace; letter-spacing: 7px; font-size: 24px; text-decoration: none;} -a.log {color: #6197df; text-decoration: none;} -a.log_today {color: #f29b00; text-decoration: none;} - -.day { font: 12px Verdana; height: 17px; color: #BBBBBB} -.weekday { font: 10px Verdana; height: 17px; color: #FFFFFF; background-color: #000000; margin-top: 50px; - padding-left: 5px; padding-right: 5px; padding-top: 3px; text-align: center;} -.timestuff {color: #AAAAAA; text-decoration: none;} -.muc_join {color: #009900; font-style: italic;} -.muc_leave {color: #009900; font-style: italic;} -.muc_statusChange {color: #009900; font-style: italic;} -.muc_title {color: #BBBBBB; font-size: 32px;} -.muc_titleChange {color: #009900; font-style: italic;} -.muc_kick {color: #009900; font-style: italic;} -.muc_bann {color: #009900; font-style: italic;} -.muc_msg_nick {color: #0000AA;} -.muc_msg_me {color: #0000AA;} -.month_title {font: 10pt Verdana;} -.year_title {font: bold 16px Verdana;} -.footer {margin-top: 20pt; text-align: center;} - -label {margin-right: 2em} -thead {font: 25pt bold; text-align: center} -tbody {border: solid black 1px;} -img {border: 0px} -body {margin-left: 20pt; margin-right: 20pt;} -</style> -<body> -###BODY_STUFF### -<div class="footer"><a href="http://prosody.im"><img alt="Powered by Prosody" src="http://prosody.im/files/powered_by_prosody_80x30.png"/></a></div> -</body> -</html>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/month_day.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ - <td class="day" valign="middle" align="center">###DAY###</td> \ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/month_emptyDay.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ - <td class="day"> </td> \ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/month_footer.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -</tbody></table> \ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/month_header.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -<table rules="groups" cellpadding="5"> -<thead><tr><td colspan="7">###TITLE###</td></tr></thead> -<tbody> -<tr>###WEEKDAYS###</tr>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/month_weekDay.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ - <th class="weekday" valign="middle" align="center">###DAY###</th> \ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/rooms_bit.html Sun Feb 09 17:15:27 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -<a href="###ROOM###/">###ROOM###</a><br />