diff --git a/resources/prosody-plugins/mod_muc_breakout_rooms.lua b/resources/prosody-plugins/mod_muc_breakout_rooms.lua index b3557c66d618..3f79ed576683 100644 --- a/resources/prosody-plugins/mod_muc_breakout_rooms.lua +++ b/resources/prosody-plugins/mod_muc_breakout_rooms.lua @@ -15,6 +15,9 @@ -- muc_room_locking = false -- muc_room_default_public_jids = true -- + +module:depends('room_destroy'); + -- we use async to detect Prosody 0.10 and earlier local have_async = pcall(require, 'util.async'); @@ -427,14 +430,39 @@ function on_occupant_left(event) -- and we will have the old instance local main_room, main_room_jid = get_main_room(room_jid); if main_room and main_room.close_timer then - module:log('info', 'Closing conference %s as all left for good.', main_room_jid); - main_room:set_persistent(false); - main_room:destroy(nil, 'All occupants left.'); + prosody.events.fire_event("maybe-destroy-room", { + room = main_room; + reason = 'All occupants left.'; + caller = module:get_name(); + }); end end); end end +-- Stop other modules from destroying room if breakout rooms not empty +function handle_maybe_destroy_main_room(event) + local main_room = event.room; + local caller = event.caller; + + if caller == module:get_name() then + -- we were the one that requested the deletion. Do not override. + return nil; -- stop room destruction + end + + -- deletion was requested by another module. Check for break room occupants. + for breakout_room_jid, _ in pairs(main_room._data.breakout_rooms or {}) do + local breakout_room = breakout_rooms_muc_service.get_room_from_jid(breakout_room_jid); + if breakout_room and breakout_room:has_occupant() then + module:log('info', 'Suppressing room destroy. Breakout room still occupied %s', breakout_room_jid); + return true; -- stop room destruction + end + end +end + +module:hook_global("maybe-destroy-room", handle_maybe_destroy_main_room) + + function on_main_room_destroyed(event) local main_room = event.room; diff --git a/resources/prosody-plugins/mod_persistent_lobby.lua b/resources/prosody-plugins/mod_persistent_lobby.lua index 2ebfaa48b275..2f4e30c399af 100644 --- a/resources/prosody-plugins/mod_persistent_lobby.lua +++ b/resources/prosody-plugins/mod_persistent_lobby.lua @@ -8,6 +8,7 @@ -- To trigger creation of lobby room: -- prosody.events.fire_event("create-persistent-lobby-room", { room = room; }); -- +module:depends('room_destroy'); local util = module:require "util"; local is_healthcheck_room = util.is_healthcheck_room; @@ -86,8 +87,11 @@ end -- Helper method to trigger main room destroy local function trigger_room_destroy(room) - room:set_persistent(false); - room:destroy(nil, 'main room and lobby now empty'); + prosody.events.fire_event("maybe-destroy-room", { + room = room; + reason = 'main room and lobby now empty'; + caller = module:get_name(); + }); end @@ -170,3 +174,26 @@ end module:hook_global('create-persistent-lobby-room', handle_create_persistent_lobby); + +-- Stop other modules from destroying room if persistent lobby not empty +function handle_maybe_destroy_main_room(event) + local main_room = event.room; + local caller = event.caller; + + if caller == module:get_name() then + -- we were the one that requested the deletion. Do not override. + return nil; + end + + -- deletion was requested by another module. Check for lobby occupants. + if has_persistent_lobby(main_room) and main_room._data.lobbyroom then + local lobby_room_jid = main_room._data.lobbyroom; + local lobby_room = lobby_muc_service.get_room_from_jid(lobby_room_jid); + if lobby_room and lobby_room:has_occupant() then + module:log('info', 'Suppressing room destroy. Persistent lobby still occupied %s', lobby_room_jid); + return true; -- stop room destruction + end + end +end + +module:hook_global("maybe-destroy-room", handle_maybe_destroy_main_room); diff --git a/resources/prosody-plugins/mod_room_destroy.lua b/resources/prosody-plugins/mod_room_destroy.lua new file mode 100644 index 000000000000..d3dfb3b961be --- /dev/null +++ b/resources/prosody-plugins/mod_room_destroy.lua @@ -0,0 +1,15 @@ +-- Handle room destroy requests it such a way that it can be suppressed by other +-- modules that handle room lifecycle and wish to keep the room alive. + +function handle_room_destroy(event) + local room = event.room; + local reason = event.reason; + local caller = event.caller; + + module:log('info', 'Destroying room %s (requested by %s)', room.jid, caller); + room:set_persistent(false); + room:destroy(nil, reason); +end + +module:hook_global("maybe-destroy-room", handle_room_destroy, -1); +module:log('info', 'loaded');