local jid_bare = require "util.jid".bare;
local st = require "util.stanza";
local um_is_admin = require "core.usermanager".is_admin;
-local hosts = prosody.hosts;
local rooms = module:shared "rooms";
end
end
-function track_room(room)
- rooms[room.jid] = room;
+local persistent = module:require "muc/persistent";
+local persistent_rooms_storage = module:open_store("persistent");
+local persistent_rooms = module:open_store("persistent", "map");
+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 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 = history;
+ elseif forced then
+ room_configs:set(node, nil);
+ if not next(room._occupants) then -- Room empty
+ rooms[room.jid] = nil;
+ end
+ end
end
-function forget_room(jid)
- rooms[jid] = nil;
+-- Automatically destroy empty non-persistent rooms
+module:hook("muc-occupant-left",function(event)
+ local room = event.room
+ if not room:has_occupant() and not persistent.get(room) then -- empty, non-persistent room
+ module:fire_event("muc-room-destroyed", { room = room });
+ end
+end);
+
+function track_room(room)
+ rooms[room.jid] = room;
+ -- When room is created, over-ride 'save' method
+ room.save = room_save;
end
-function get_room_from_jid(room_jid)
- return rooms[room_jid]
+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;
+ track_room(room);
+ return room;
+ end
end
-function each_room()
- return iterators.values(rooms);
+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);
+ end
end
-do -- Persistent rooms
- local persistent = module:require "muc/persistent";
- local persistent_rooms_storage = module:open_store("persistent");
- local persistent_rooms = persistent_rooms_storage:get() or {};
- 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[room.jid] = is_persistent;
- if is_persistent then
- local 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 = history;
- elseif forced then
- room_configs:set(node, nil);
- if not next(room._occupants) then -- Room empty
- rooms[room.jid] = nil;
+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
- if forced then persistent_rooms_storage:set(nil, persistent_rooms); end
end
+ return room
+end
- -- When room is created, over-ride 'save' method
- module:hook("muc-room-pre-create", function(event)
- event.room.save = room_save;
- end, 1000);
-
- -- Automatically destroy empty non-persistent rooms
- module:hook("muc-occupant-left",function(event)
- local room = event.room
- if not room:has_occupant() and not persistent.get(room) then -- empty, non-persistent room
- module:fire_event("muc-room-destroyed", { room = room });
- end
- end);
-
- local persistent_errors = false;
- for jid in pairs(persistent_rooms) do
- 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;
- track_room(room);
- else -- missing room data
- persistent_rooms[jid] = nil;
- module:log("error", "Missing data for room '%s', removing from persistent room list", jid);
- persistent_errors = true;
+function each_room()
+ 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
+ local room = restore_room(room_jid);
+ if room == nil then
+ module:log("error", "Missing data for room '%s', omitting from iteration", room_jid);
+ end
end
end
- if persistent_errors then persistent_rooms_storage:set(nil, persistent_rooms); end
+ return iterators.values(rooms);
end
module:hook("host-disco-items", function(event)
end, -1000);
module:hook("muc-room-destroyed",function(event)
- local room = event.room
- forget_room(room.jid)
+ return forget_room(event.room);
end)
do
if restrict_room_creation then
local host_suffix = module.host:gsub("^[^%.]+%.", "");
module:hook("muc-room-pre-create", function(event)
- local user_jid = event.stanza.attr.from;
+ local origin, stanza = event.origin, event.stanza;
+ local user_jid = stanza.attr.from;
if not is_admin(user_jid) and not (
restrict_room_creation == "local" and
select(2, jid_split(user_jid)) == host_suffix
};
local destroy_rooms_handler = adhoc_initial(destroy_rooms_layout, function()
- return { rooms = array.collect(each_room):pluck("jid"):sort(); };
+ return { rooms = array.collect(each_room()):pluck("jid"):sort(); };
end, function(fields, errors)
if errors then
local errmsg = {};