Software /
code /
prosody-modules
File
mod_message_logging/mod_message_logging.lua @ 1268:854a3933cfcd
mod_muc_log_http: URL-encode room names. This allows special characters in room names to work. Ideally this escaping shouldn’t be done in the user visible content, but the module’s template system doesn’t currently allow that.
author | Waqas Hussain <waqas20@gmail.com> |
---|---|
date | Sat, 04 Jan 2014 16:50:57 -0500 |
parent | 1007:ba220790a59c |
child | 1343:7dbde05b48a9 |
line wrap: on
line source
module:set_global(); local jid_bare = require "util.jid".bare; local jid_split = require "util.jid".split; local stat, mkdir = require "lfs".attributes, require "lfs".mkdir; -- Get a filesystem-safe string local function fsencode_char(c) return ("%%%02x"):format(c:byte()); end local function fsencode(s) return (s:gsub("[^%w._-@]", fsencode_char):gsub("^%.", "_")); end local log_base_path = module:get_option("message_logging_dir", prosody.paths.data.."/message_logs"); mkdir(log_base_path); local function get_host_path(host) return log_base_path.."/"..fsencode(host); end local function get_user_path(jid) local username, host = jid_split(jid); local base = get_host_path(host)..os.date("/%Y-%m-%d"); if not stat(base) then mkdir(base); end return base.."/"..fsencode(username)..".msglog"; end local open_files_mt = { __index = function (open_files, jid) local f, err = io.open(get_user_path(jid), "a+"); if not f then module:log("error", "Failed to open message log for writing [%s]: %s", jid, err); end rawset(open_files, jid, f); return f; end }; -- [user@host] = filehandle local open_files = setmetatable({}, open_files_mt); function close_open_files() module:log("debug", "Closing all open files"); for jid, filehandle in pairs(open_files) do filehandle:close(); open_files[jid] = nil; end end module:hook_global("logging-reloaded", close_open_files); local function handle_incoming_message(event) local origin, stanza = event.origin, event.stanza; local message_type = stanza.attr.type; if message_type == "error" then return; end local from, to = jid_bare(stanza.attr.from), jid_bare(stanza.attr.to); local body = stanza:get_child("body"); if not body then return; end body = body:get_text(); local f = open_files[to]; if not f then return; end if message_type == "groupchat" then -- Add the nickname from = from.." <"..(select(3, jid_split(stanza.attr.from)) or "")..">"; end body = body:gsub("\n", "\n "); -- Indent newlines f:write("RECV: ", from, ": ", body, "\n"); f:flush(); end local function handle_outgoing_message(event) local origin, stanza = event.origin, event.stanza; local message_type = stanza.attr.type; if message_type == "error" or message_type == "groupchat" then return; end local from, to = jid_bare(stanza.attr.from), jid_bare(stanza.attr.to); local body = stanza:get_child("body"); if not body then return; end body = body:get_text(); local f = open_files[from]; if not f then return; end body = body:gsub("\n", "\n "); -- Indent newlines f:write("SEND: ", to, ": ", body, "\n"); f:flush(); end function module.add_host(module) local host_base_path = get_host_path(module.host); if not stat(host_base_path) then mkdir(host_base_path); end module:hook("message/bare", handle_incoming_message, 1); module:hook("message/full", handle_incoming_message, 1); module:hook("pre-message/bare", handle_outgoing_message, 1); module:hook("pre-message/full", handle_outgoing_message, 1); module:hook("pre-message/host", handle_outgoing_message, 1); end function module.command(arg) local command = table.remove(arg, 1); if command == "path" then print(get_user_path(arg[1])); else io.stderr:write("Unrecognised command: ", command); return 1; end return 0; end function module.save() return { open_files = open_files }; end function module.restore(saved) open_files = setmetatable(saved.open_files or {}, open_files_mt); end