X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=plugins%2Fmuc%2Fmod_muc.lua;h=5ac230adad796244d180442fb081afe98b1d6649;hb=8dcebf9a034d176ce017ef5d28a638854a3bca0a;hp=4f5831a62c24e447efced881bf25eb72a0c9201f;hpb=f760c52919054661d998f7e0b628a317dedfa4cd;p=prosody.git diff --git a/plugins/muc/mod_muc.lua b/plugins/muc/mod_muc.lua index 4f5831a6..5ac230ad 100644 --- a/plugins/muc/mod_muc.lua +++ b/plugins/muc/mod_muc.lua @@ -7,7 +7,7 @@ -- if module:get_host_type() ~= "component" then - error("MUC should be loaded as a component, please see http://prosody.im/doc/components", 0); + error("MUC should be loaded as a component, please see https://prosody.im/doc/components", 0); end local muclib = module:require "muc"; @@ -61,14 +61,12 @@ room_mt.send_history = history.send; room_mt.get_historylength = history.get_length; room_mt.set_historylength = history.set_length; -local iterators = require "util.iterators"; local jid_split = require "util.jid".split; local jid_bare = require "util.jid".bare; local st = require "util.stanza"; +local cache = require "util.cache"; local um_is_admin = require "core.usermanager".is_admin; -local rooms = module:shared "rooms"; - module:depends("disco"); module:add_identity("conference", "text", module:get_option_string("name", "Prosody Chatrooms")); module:add_feature("http://jabber.org/protocol/muc"); @@ -100,25 +98,21 @@ local room_configs = module:open_store("config"); local function room_save(room, forced) local node = jid_split(room.jid); local is_persistent = persistent.get(room); - persistent_rooms:set(nil, room.jid, is_persistent); - if is_persistent then - local room_history = room._data.history; - room._data.history = nil; - local data = { - jid = room.jid; - _data = room._data; - _affiliations = room._affiliations; - }; - room_configs:set(node, data); - room._data.history = room_history; - elseif forced then - room_configs:set(node, nil); - if not next(room._occupants) then -- Room empty - rooms[room.jid] = nil; - end + if is_persistent or forced then + persistent_rooms:set(nil, room.jid, true); + local data = room:freeze(forced); + return room_configs:set(node, data); + else + persistent_rooms:set(nil, room.jid, nil); + return room_configs:set(node, nil); end end +local rooms = cache.new(module:get_option_number("muc_room_cache_size", 100), function (_, room) + module:log("debug", "%s evicted", room); + room_save(room, true); -- Force to disk +end); + -- Automatically destroy empty non-persistent rooms module:hook("muc-occupant-left",function(event) local room = event.room @@ -128,7 +122,7 @@ module:hook("muc-occupant-left",function(event) end); function track_room(room) - rooms[room.jid] = room; + rooms:set(room.jid, room); -- When room is created, over-ride 'save' method room.save = room_save; end @@ -137,51 +131,61 @@ local function restore_room(jid) local node = jid_split(jid); local data = room_configs:get(node); if data then - local room = muclib.new_room(jid); - room._data = data._data; - room._affiliations = data._affiliations; + local room = muclib.restore_room(data); track_room(room); return room; end end function forget_room(room) - local room_jid = room.jid; - local node = jid_split(room.jid); - rooms[room_jid] = nil; - room_configs:set(node, nil); - if persistent.get(room) then - persistent_rooms:set(nil, room_jid, nil); + module:log("debug", "Forgetting %s", room); + rooms.save = nil; + rooms:set(room.jid, nil); +end + +function delete_room(room) + module:log("debug", "Deleting %s", room); + room_configs:set(jid_split(room.jid), nil); + persistent_rooms:set(nil, room.jid, nil); +end + +function module.unload() + for room in rooms:values() do + room:save(true); + forget_room(room); end end function get_room_from_jid(room_jid) - local room = rooms[room_jid]; - if room == nil then - -- Check if in persistent storage - if persistent_rooms:get(nil, room_jid) then - room = restore_room(room_jid); - if room == nil then - module:log("error", "Missing data for room '%s', removing from persistent room list", room_jid); - persistent_rooms:set(nil, room_jid, nil); - end - end + local room = rooms:get(room_jid); + if room then + rooms:set(room_jid, room); -- bump to top; + return room; end - return room + return restore_room(room_jid); end function each_room(local_only) - if not local_only then + if local_only then + return rooms:values(); + end + return coroutine.wrap(function () + local seen = {}; -- Don't iterate over persistent rooms twice + for room in rooms:values() do + coroutine.yield(room); + seen[room.jid] = true; + end for room_jid in pairs(persistent_rooms_storage:get(nil) or {}) do - if rooms[room_jid] == nil then -- Don't restore rooms that already exist + if seen[room_jid] then local room = restore_room(room_jid); if room == nil then module:log("error", "Missing data for room '%s', omitting from iteration", room_jid); + else + coroutine.yield(room); end end end - end - return iterators.values(rooms); + end); end module:hook("host-disco-items", function(event) @@ -199,8 +203,10 @@ module:hook("muc-room-pre-create", function(event) end, -1000); module:hook("muc-room-destroyed",function(event) - return forget_room(event.room); -end) + local room = event.room; + forget_room(room); + delete_room(room); +end); do local restrict_room_creation = module:get_option("restrict_room_creation"); @@ -255,9 +261,11 @@ for event_name, method in pairs { -- Watch presence to create rooms if stanza.attr.type == nil and stanza.name == "presence" then room = muclib.new_room(room_jid); - else + elseif stanza.attr.type ~= "error" then origin.send(st.error_reply(stanza, "cancel", "not-allowed")); return true; + else + return; end end return room[method](room, origin, stanza);