Mercurial > prosody-modules
view mod_muc_log/mod_muc_log.lua @ 5170:4d6af8950016
mod_muc_moderation: Derive role from reserved nickname if occupant
When using a different client to moderate than the one used to
participate in the chat, e.g. a command line tool like clix, there's no
occupant and no role to use in the permission check. Previously the
default role based on affiliation was used. Now if you are present in
the room using your reserved nick, the role you have there is used in
the permission check instead of the default affiliation-derived role.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sun, 19 Feb 2023 18:17:37 +0100 |
parents | 585bb8ac11bb |
children |
line wrap: on
line source
-- Copyright (C) 2009 Thilo Cestonaro -- Copyright (C) 2009 Waqas Hussain -- Copyright (C) 2009-2013 Matthew Wild -- Copyright (C) 2013 Kim Alvefur -- Copyright (C) 2013 Marco Cirillo local hosts = prosody.hosts; local tostring = tostring; local split_jid = require "util.jid".split; local datamanager = require"core.storagemanager".olddm; local data_load, data_store = datamanager.load, datamanager.store; local datastore = "muc_log"; local muc_form_config_option = "muc#roomconfig_enablelogging" local log_by_default = module:get_option_boolean("muc_log_by_default", false); local log_presences = module:get_option_boolean("muc_log_presences", true); -- Module Definitions 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 logging_enabled(room) local enabled = room._data.logging; if enabled == nil then return log_by_default; end return enabled; end function log_if_needed(event) local stanza = event.stanza; if (stanza.name == "presence") or (stanza.name == "iq") or (stanza.name == "message" and tostring(stanza.attr.type) == "groupchat") then local node, host = split_jid(stanza.attr.to); if node and host then local bare = node .. "@" .. host; if get_room_from_jid(bare) then local room = get_room_from_jid(bare) local today = os.date("!%y%m%d"); local now = os.date("!%H:%M:%S"); local muc_to = nil local muc_from = nil; local already_joined = false; if room._data.hidden then -- do not log any data of private rooms return; end if not logging_enabled(room) then -- do not log where logging is not enabled return; end if stanza.name == "presence" and stanza.attr.type == nil then muc_from = stanza.attr.to; if room._occupants and room._occupants[stanza.attr.to] then already_joined = true; stanza:tag("alreadyJoined"):text("true"); end elseif stanza.name == "iq" and stanza.attr.type == "set" then -- kick, to is the room, from is the admin, nick who is kicked is attr of iq->query->item if stanza.tags[1] and stanza.tags[1].name == "query" then local tmp = stanza.tags[1]; if tmp.tags[1] ~= nil and tmp.tags[1].name == "item" and tmp.tags[1].attr.nick then tmp = tmp.tags[1]; for jid, nick in pairs(room._jid_nick) do if nick == stanza.attr.to .. "/" .. tmp.attr.nick then muc_to = nick; break; end end end end else for jid, nick in pairs(room._jid_nick) do if jid == stanza.attr.from then muc_from = nick; break; end end end if (muc_from or muc_to) then local data = data_load(node, host, datastore .. "/" .. today); local realFrom = stanza.attr.from; local realTo = stanza.attr.to; if data == nil then data = {}; end stanza.attr.from = muc_from; stanza.attr.to = muc_to; data[#data + 1] = "<stanza time=\"".. now .. "\">" .. tostring(stanza) .. "</stanza>\n"; stanza.attr.from = realFrom; stanza.attr.to = realTo; if already_joined == true then if stanza[#stanza].name == "alreadyJoined" then -- normaly the faked element should be the last, remove it when it is the last stanza[#stanza] = nil; else for i = 1, #stanza, 1 do if stanza[i].name == "alreadyJoined" then -- remove the faked element stanza[i] = nil; break; end end end end datamanager.getpath(node, host, datastore, nil, true); -- create the datastore dir data_store(node, host, datastore .. "/" .. today, data); end end end end end module:hook("muc-config-form", function(event) local room, form = event.room, event.form; table.insert(form, { name = muc_form_config_option, type = "boolean", label = "Enable Logging?", value = logging_enabled(room), } ); end); module:hook("muc-config-submitted", function(event) local room, fields, changed = event.room, event.fields, event.changed; local new = fields[muc_form_config_option]; if new ~= room._data.logging then room._data.logging = new; if type(changed) == "table" then changed[muc_form_config_option] = true; else event.changed = true; end end end); module:hook("message/bare", log_if_needed, 1); if log_presences then module:hook("iq/bare", log_if_needed, 1); module:hook("presence/full", log_if_needed, 1); end module:log("debug", "module mod_muc_log loaded!");