mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2025-12-30 11:22:31 +00:00
Make sure we execute before prosody cleans it up from the list of room. If we try to look it up after that we will not find it. If we also add at 0 we cannot guarantee the order of hook execution.
670 lines
23 KiB
Lua
670 lines
23 KiB
Lua
-- This module is added under the main virtual host domain
|
|
-- It needs a breakout rooms muc component
|
|
--
|
|
-- VirtualHost "jitmeet.example.com"
|
|
-- modules_enabled = {
|
|
-- "muc_breakout_rooms"
|
|
-- }
|
|
-- breakout_rooms_muc = "breakout.jitmeet.example.com"
|
|
-- main_muc = "muc.jitmeet.example.com"
|
|
--
|
|
-- Component "breakout.jitmeet.example.com" "muc"
|
|
-- restrict_room_creation = true
|
|
-- storage = "memory"
|
|
-- admins = { "focusUser@auth.jitmeet.example.com" }
|
|
-- 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');
|
|
|
|
if not have_async then
|
|
module:log('warn', 'Breakout rooms will not work with Prosody version 0.10 or less.');
|
|
return;
|
|
end
|
|
|
|
local jid_node = require 'util.jid'.node;
|
|
local jid_host = require 'util.jid'.host;
|
|
local jid_split = require 'util.jid'.split;
|
|
local json = require 'cjson.safe';
|
|
local st = require 'util.stanza';
|
|
local uuid_gen = require 'util.uuid'.generate;
|
|
|
|
local util = module:require 'util';
|
|
local internal_room_jid_match_rewrite = util.internal_room_jid_match_rewrite;
|
|
local is_healthcheck_room = util.is_healthcheck_room;
|
|
local process_host_module = util.process_host_module;
|
|
|
|
local BREAKOUT_ROOMS_IDENTITY_TYPE = 'breakout_rooms';
|
|
-- Available breakout room functionality
|
|
local RENAME_FEATURE = 'http://jitsi.org/protocol/breakout_rooms#rename';
|
|
-- only send at most this often updates on breakout rooms to avoid flooding.
|
|
local BROADCAST_ROOMS_INTERVAL = .3;
|
|
-- close conference after this amount of seconds if all leave.
|
|
local ROOMS_TTL_IF_ALL_LEFT = 5;
|
|
local JSON_TYPE_ADD_BREAKOUT_ROOM = 'features/breakout-rooms/add';
|
|
local JSON_TYPE_MOVE_TO_ROOM_REQUEST = 'features/breakout-rooms/move-to-room';
|
|
local JSON_TYPE_REMOVE_BREAKOUT_ROOM = 'features/breakout-rooms/remove';
|
|
local JSON_TYPE_RENAME_BREAKOUT_ROOM = 'features/breakout-rooms/rename';
|
|
local JSON_TYPE_UPDATE_BREAKOUT_ROOMS = 'features/breakout-rooms/update';
|
|
|
|
local main_muc_component_config = module:get_option_string('main_muc');
|
|
if main_muc_component_config == nil then
|
|
module:log('error', 'breakout rooms not enabled missing main_muc config');
|
|
return ;
|
|
end
|
|
local breakout_rooms_muc_component_config = module:get_option_string('breakout_rooms_muc', 'breakout.'..module.host);
|
|
|
|
module:depends('jitsi_session');
|
|
|
|
local breakout_rooms_muc_service;
|
|
local main_muc_service;
|
|
|
|
-- Maps a breakout room jid to the main room jid
|
|
local main_rooms_map = {};
|
|
|
|
-- Utility functions
|
|
|
|
function get_main_room_jid(room_jid)
|
|
local _, host = jid_split(room_jid);
|
|
|
|
return
|
|
host == main_muc_component_config
|
|
and room_jid
|
|
or main_rooms_map[room_jid];
|
|
end
|
|
|
|
function get_main_room(room_jid)
|
|
local main_room_jid = get_main_room_jid(room_jid);
|
|
|
|
return main_muc_service.get_room_from_jid(main_room_jid), main_room_jid;
|
|
end
|
|
|
|
function get_room_from_jid(room_jid)
|
|
local host = jid_host(room_jid);
|
|
|
|
return
|
|
host == main_muc_component_config
|
|
and main_muc_service.get_room_from_jid(room_jid)
|
|
or breakout_rooms_muc_service.get_room_from_jid(room_jid);
|
|
end
|
|
|
|
function send_json_msg(to_jid, json_msg)
|
|
local stanza = st.message({ from = breakout_rooms_muc_component_config; to = to_jid; })
|
|
:tag('json-message', { xmlns = 'http://jitsi.org/jitmeet' }):text(json_msg):up();
|
|
module:send(stanza);
|
|
end
|
|
|
|
function get_participants(room)
|
|
local participants = {};
|
|
|
|
if room then
|
|
for room_nick, occupant in room:each_occupant() do
|
|
-- Filter focus as we keep it as a hidden participant
|
|
if jid_node(occupant.jid) ~= 'focus' then
|
|
local display_name = occupant:get_presence():get_child_text(
|
|
'nick', 'http://jabber.org/protocol/nick');
|
|
local real_nick = internal_room_jid_match_rewrite(room_nick);
|
|
participants[real_nick] = {
|
|
jid = occupant.jid,
|
|
role = occupant.role,
|
|
displayName = display_name
|
|
};
|
|
end
|
|
end
|
|
end
|
|
|
|
return participants;
|
|
end
|
|
|
|
function broadcast_breakout_rooms(room_jid)
|
|
local main_room = get_main_room(room_jid);
|
|
|
|
if not main_room or main_room.broadcast_timer then
|
|
return;
|
|
end
|
|
|
|
-- Only send each BROADCAST_ROOMS_INTERVAL seconds to prevent flooding of messages.
|
|
main_room.broadcast_timer = module:add_timer(BROADCAST_ROOMS_INTERVAL, function()
|
|
local main_room, main_room_jid = get_main_room(room_jid);
|
|
|
|
if not main_room then
|
|
return;
|
|
end
|
|
|
|
main_room.broadcast_timer = nil;
|
|
|
|
local real_jid = internal_room_jid_match_rewrite(main_room_jid);
|
|
local real_node = jid_node(real_jid);
|
|
local rooms = {
|
|
[real_node] = {
|
|
isMainRoom = true,
|
|
id = real_node,
|
|
jid = real_jid,
|
|
name = main_room._data.subject,
|
|
participants = get_participants(main_room)
|
|
};
|
|
}
|
|
|
|
for breakout_room_jid, subject in pairs(main_room._data.breakout_rooms or {}) do
|
|
local breakout_room = breakout_rooms_muc_service.get_room_from_jid(breakout_room_jid);
|
|
local breakout_room_node = jid_node(breakout_room_jid)
|
|
|
|
rooms[breakout_room_node] = {
|
|
id = breakout_room_node,
|
|
jid = breakout_room_jid,
|
|
name = subject,
|
|
participants = {}
|
|
}
|
|
|
|
-- The room may not physically exist yet.
|
|
if breakout_room then
|
|
rooms[breakout_room_node].participants = get_participants(breakout_room);
|
|
end
|
|
end
|
|
|
|
local json_msg, error = json.encode({
|
|
type = BREAKOUT_ROOMS_IDENTITY_TYPE,
|
|
event = JSON_TYPE_UPDATE_BREAKOUT_ROOMS,
|
|
roomCounter = main_room._data.breakout_rooms_counter,
|
|
rooms = rooms
|
|
});
|
|
|
|
if not json_msg then
|
|
module:log('error', 'not broadcasting breakout room information room:%s error:%s', main_room_jid, error);
|
|
return;
|
|
end
|
|
|
|
for _, occupant in main_room:each_occupant() do
|
|
if jid_node(occupant.jid) ~= 'focus' then
|
|
send_json_msg(occupant.jid, json_msg)
|
|
end
|
|
end
|
|
|
|
for breakout_room_jid in pairs(main_room._data.breakout_rooms or {}) do
|
|
local room = breakout_rooms_muc_service.get_room_from_jid(breakout_room_jid);
|
|
if room then
|
|
for _, occupant in room:each_occupant() do
|
|
if jid_node(occupant.jid) ~= 'focus' then
|
|
send_json_msg(occupant.jid, json_msg)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end);
|
|
end
|
|
|
|
|
|
-- Managing breakout rooms
|
|
|
|
function create_breakout_room(orig_room, subject)
|
|
local main_room, main_room_jid = get_main_room(orig_room.jid);
|
|
|
|
if orig_room ~= main_room then
|
|
module:log('warn', 'Invalid create breakout room request for %s', orig_room.jid);
|
|
return;
|
|
end
|
|
|
|
local breakout_room_jid = uuid_gen() .. '@' .. breakout_rooms_muc_component_config;
|
|
|
|
if not main_room._data.breakout_rooms then
|
|
main_room._data.breakout_rooms = {};
|
|
main_room._data.breakout_rooms_counter = 0;
|
|
end
|
|
main_room._data.breakout_rooms_counter = main_room._data.breakout_rooms_counter + 1;
|
|
main_room._data.breakout_rooms[breakout_room_jid] = subject;
|
|
main_room._data.breakout_rooms_active = true;
|
|
-- Make room persistent - not to be destroyed - if all participants join breakout rooms.
|
|
main_room:set_persistent(true);
|
|
main_room:save(true);
|
|
|
|
main_rooms_map[breakout_room_jid] = main_room_jid;
|
|
broadcast_breakout_rooms(main_room_jid);
|
|
end
|
|
|
|
function destroy_breakout_room(orig_room, room_jid, message)
|
|
local main_room, main_room_jid = get_main_room(room_jid);
|
|
|
|
if room_jid == main_room_jid then
|
|
return;
|
|
end
|
|
|
|
if orig_room ~= main_room then
|
|
module:log('warn', 'Invalid destroy breakout room request for %s', orig_room.jid);
|
|
return;
|
|
end
|
|
|
|
local breakout_room = breakout_rooms_muc_service.get_room_from_jid(room_jid);
|
|
|
|
if breakout_room then
|
|
message = message or 'Breakout room removed.';
|
|
breakout_room:destroy(main_room and main_room_jid or nil, message);
|
|
end
|
|
if main_room then
|
|
if main_room._data.breakout_rooms then
|
|
main_room._data.breakout_rooms[room_jid] = nil;
|
|
end
|
|
main_room:save(true);
|
|
|
|
main_rooms_map[room_jid] = nil;
|
|
broadcast_breakout_rooms(main_room_jid);
|
|
end
|
|
end
|
|
|
|
|
|
function rename_breakout_room(orig_room, room_jid, name)
|
|
local main_room, main_room_jid = get_main_room(room_jid);
|
|
|
|
if room_jid == main_room_jid then
|
|
return;
|
|
end
|
|
|
|
if orig_room ~= main_room then
|
|
module:log('warn', 'Invalid rename breakout room request for %s', orig_room.jid);
|
|
return;
|
|
end
|
|
|
|
if main_room then
|
|
if main_room._data.breakout_rooms then
|
|
main_room._data.breakout_rooms[room_jid] = name;
|
|
local breakout_room = breakout_rooms_muc_service.get_room_from_jid(room_jid);
|
|
|
|
if breakout_room then
|
|
breakout_room:set_subject(breakout_room.jid, name);
|
|
end
|
|
|
|
end
|
|
main_room:save(true);
|
|
broadcast_breakout_rooms(main_room_jid);
|
|
end
|
|
end
|
|
|
|
-- Handling events
|
|
|
|
function on_message(event)
|
|
local session = event.origin;
|
|
|
|
-- Check the type of the incoming stanza to avoid loops:
|
|
if event.stanza.attr.type == 'error' then
|
|
return; -- We do not want to reply to these, so leave.
|
|
end
|
|
|
|
if not session or not session.jitsi_web_query_room then
|
|
return false;
|
|
end
|
|
|
|
local message = event.stanza:get_child(BREAKOUT_ROOMS_IDENTITY_TYPE);
|
|
|
|
if not message then
|
|
return false;
|
|
end
|
|
|
|
-- get room name with tenant and find room
|
|
local room = get_room_by_name_and_subdomain(session.jitsi_web_query_room, session.jitsi_web_query_prefix);
|
|
|
|
if not room then
|
|
module:log('warn', 'No room found for %s/%s',
|
|
session.jitsi_web_query_prefix, session.jitsi_web_query_room);
|
|
return false;
|
|
end
|
|
|
|
-- check that the participant requesting is a moderator and is an occupant in the room
|
|
local from = event.stanza.attr.from;
|
|
local occupant = room:get_occupant_by_real_jid(from);
|
|
|
|
if not occupant then
|
|
-- Check if the participant is in any breakout room.
|
|
for breakout_room_jid in pairs(room._data.breakout_rooms or {}) do
|
|
local breakout_room = breakout_rooms_muc_service.get_room_from_jid(breakout_room_jid);
|
|
if breakout_room then
|
|
occupant = breakout_room:get_occupant_by_real_jid(from);
|
|
if occupant then
|
|
break;
|
|
end
|
|
end
|
|
end
|
|
if not occupant then
|
|
module:log('warn', 'No occupant %s found for %s', from, room.jid);
|
|
return false;
|
|
end
|
|
end
|
|
|
|
if occupant.role ~= 'moderator' then
|
|
module:log('warn', 'Occupant %s is not moderator and not allowed this operation for %s', from, room.jid);
|
|
return false;
|
|
end
|
|
|
|
if message.attr.type == JSON_TYPE_ADD_BREAKOUT_ROOM then
|
|
create_breakout_room(room, message.attr.subject);
|
|
return true;
|
|
elseif message.attr.type == JSON_TYPE_REMOVE_BREAKOUT_ROOM then
|
|
destroy_breakout_room(room, message.attr.breakoutRoomJid);
|
|
return true;
|
|
elseif message.attr.type == JSON_TYPE_RENAME_BREAKOUT_ROOM then
|
|
rename_breakout_room(room, message.attr.breakoutRoomJid, message.attr.subject);
|
|
return true;
|
|
elseif message.attr.type == JSON_TYPE_MOVE_TO_ROOM_REQUEST then
|
|
local participant_jid = message.attr.participantJid;
|
|
local target_room_jid = message.attr.roomJid;
|
|
|
|
if not room._data.breakout_rooms or not (
|
|
room._data.breakout_rooms[target_room_jid] or target_room_jid == internal_room_jid_match_rewrite(room.jid))
|
|
then
|
|
module:log('warn', 'Invalid breakout room %s for %s', target_room_jid, room.jid);
|
|
return false
|
|
end
|
|
|
|
local json_msg, error = json.encode({
|
|
type = BREAKOUT_ROOMS_IDENTITY_TYPE,
|
|
event = JSON_TYPE_MOVE_TO_ROOM_REQUEST,
|
|
roomJid = target_room_jid
|
|
});
|
|
|
|
if not json_msg then
|
|
module:log('error', 'skip sending request room:%s error:%s', room.jid, error);
|
|
return false
|
|
end
|
|
|
|
send_json_msg(participant_jid, json_msg)
|
|
return true;
|
|
end
|
|
|
|
-- return error.
|
|
return false;
|
|
end
|
|
|
|
function on_breakout_room_pre_create(event)
|
|
local breakout_room = event.room;
|
|
local main_room, main_room_jid = get_main_room(breakout_room.jid);
|
|
|
|
-- Only allow existent breakout rooms to be started.
|
|
-- Authorisation of breakout rooms is done by their random uuid name
|
|
if main_room and main_room._data.breakout_rooms and main_room._data.breakout_rooms[breakout_room.jid] then
|
|
breakout_room:set_subject(breakout_room.jid, main_room._data.breakout_rooms[breakout_room.jid]);
|
|
else
|
|
module:log('debug', 'Invalid breakout room %s will not be created.', breakout_room.jid);
|
|
breakout_room:destroy(main_room_jid, 'Breakout room is invalid.');
|
|
return true;
|
|
end
|
|
end
|
|
|
|
function on_occupant_joined(event)
|
|
local room = event.room;
|
|
|
|
if is_healthcheck_room(room.jid) then
|
|
return;
|
|
end
|
|
|
|
local main_room, main_room_jid = get_main_room(room.jid);
|
|
|
|
if main_room and main_room._data.breakout_rooms_active then
|
|
if jid_node(event.occupant.jid) ~= 'focus' then
|
|
broadcast_breakout_rooms(main_room_jid);
|
|
end
|
|
|
|
-- Prevent closing all rooms if a participant has joined (see on_occupant_left).
|
|
if main_room.close_timer then
|
|
main_room.close_timer:stop();
|
|
main_room.close_timer = nil;
|
|
end
|
|
end
|
|
end
|
|
|
|
function exist_occupants_in_room(room)
|
|
if not room then
|
|
return false;
|
|
end
|
|
for _, occupant in room:each_occupant() do
|
|
if jid_node(occupant.jid) ~= 'focus' then
|
|
return true;
|
|
end
|
|
end
|
|
|
|
return false;
|
|
end
|
|
|
|
function exist_occupants_in_rooms(main_room)
|
|
if exist_occupants_in_room(main_room) then
|
|
return true;
|
|
end
|
|
for breakout_room_jid in pairs(main_room._data.breakout_rooms or {}) do
|
|
local room = breakout_rooms_muc_service.get_room_from_jid(breakout_room_jid);
|
|
if exist_occupants_in_room(room) then
|
|
return true;
|
|
end
|
|
end
|
|
|
|
return false;
|
|
end
|
|
|
|
function on_occupant_pre_leave(event)
|
|
local room, occupant, session, stanza = event.room, event.occupant, event.origin, event.stanza;
|
|
|
|
local main_room = get_main_room(room.jid);
|
|
|
|
prosody.events.fire_event('jitsi-breakout-occupant-leaving', {
|
|
room = room; main_room = main_room; occupant = occupant; stanza = stanza; session = session;
|
|
});
|
|
end
|
|
|
|
function on_occupant_left(event)
|
|
local room_jid = event.room.jid;
|
|
|
|
if is_healthcheck_room(room_jid) then
|
|
return;
|
|
end
|
|
|
|
local main_room, main_room_jid = get_main_room(room_jid);
|
|
|
|
if not main_room then
|
|
return;
|
|
end
|
|
|
|
if main_room._data.breakout_rooms_active and jid_node(event.occupant.jid) ~= 'focus' then
|
|
broadcast_breakout_rooms(main_room_jid);
|
|
end
|
|
|
|
-- Close the conference if all left for good.
|
|
if main_room._data.breakout_rooms_active and not main_room.close_timer and not exist_occupants_in_rooms(main_room) then
|
|
main_room.close_timer = module:add_timer(ROOMS_TTL_IF_ALL_LEFT, function()
|
|
-- we need to look up again the room as till the timer is fired, the room maybe already destroyed/recreated
|
|
-- 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
|
|
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;
|
|
|
|
if is_healthcheck_room(main_room.jid) then
|
|
return;
|
|
end
|
|
|
|
for breakout_room_jid in pairs(main_room._data.breakout_rooms or {}) do
|
|
destroy_breakout_room(main_room, breakout_room_jid, event.reason)
|
|
end
|
|
end
|
|
|
|
|
|
-- Module operations
|
|
|
|
-- operates on already loaded breakout rooms muc module
|
|
function process_breakout_rooms_muc_loaded(breakout_rooms_muc, host_module)
|
|
module:log('debug', 'Breakout rooms muc loaded');
|
|
|
|
-- Advertise the breakout rooms component so clients can pick up the address and use it
|
|
module:add_identity('component', BREAKOUT_ROOMS_IDENTITY_TYPE, breakout_rooms_muc_component_config);
|
|
|
|
-- Tag the disco#info response with available features of breakout rooms.
|
|
host_module:hook('host-disco-info-node', function (event)
|
|
local session, reply, node = event.origin, event.reply, event.node;
|
|
if node == BREAKOUT_ROOMS_IDENTITY_TYPE and session.jitsi_web_query_room then
|
|
reply:tag('feature', { var = RENAME_FEATURE }):up();
|
|
end
|
|
event.exists = true;
|
|
end);
|
|
|
|
breakout_rooms_muc_service = breakout_rooms_muc;
|
|
module:log("info", "Hook to muc events on %s", breakout_rooms_muc_component_config);
|
|
host_module:hook('message/host', on_message);
|
|
host_module:hook('muc-occupant-joined', on_occupant_joined);
|
|
host_module:hook('muc-occupant-left', on_occupant_left);
|
|
host_module:hook('muc-room-pre-create', on_breakout_room_pre_create);
|
|
host_module:hook('muc-occupant-pre-leave', on_occupant_pre_leave);
|
|
|
|
host_module:hook('muc-disco#info', function (event)
|
|
local room = event.room;
|
|
local main_room, main_room_jid = get_main_room(room.jid);
|
|
|
|
-- Breakout room metadata.
|
|
table.insert(event.form, {
|
|
name = 'muc#roominfo_isbreakout';
|
|
label = 'Is this a breakout room?';
|
|
type = "boolean";
|
|
});
|
|
event.formdata['muc#roominfo_isbreakout'] = true;
|
|
table.insert(event.form, {
|
|
name = 'muc#roominfo_breakout_main_room';
|
|
label = 'The main room associated with this breakout room';
|
|
});
|
|
event.formdata['muc#roominfo_breakout_main_room'] = internal_room_jid_match_rewrite(main_room_jid);
|
|
|
|
-- If the main room has a lobby, make it so this breakout room also uses it.
|
|
if (main_room and main_room._data.lobbyroom and main_room:get_members_only()) then
|
|
table.insert(event.form, {
|
|
name = 'muc#roominfo_lobbyroom';
|
|
label = 'Lobby room jid';
|
|
});
|
|
event.formdata['muc#roominfo_lobbyroom'] = main_room._data.lobbyroom;
|
|
end
|
|
end);
|
|
|
|
host_module:hook("muc-config-form", function(event)
|
|
local room = event.room;
|
|
local _, main_room_jid = get_main_room(room.jid);
|
|
|
|
-- Breakout room metadata.
|
|
table.insert(event.form, {
|
|
name = 'muc#roominfo_isbreakout';
|
|
label = 'Is this a breakout room?';
|
|
type = "boolean";
|
|
value = true;
|
|
});
|
|
|
|
table.insert(event.form, {
|
|
name = 'muc#roominfo_breakout_main_room';
|
|
label = 'The main room associated with this breakout room';
|
|
value = internal_room_jid_match_rewrite(main_room_jid);
|
|
});
|
|
end);
|
|
|
|
local room_mt = breakout_rooms_muc_service.room_mt;
|
|
|
|
room_mt.get_members_only = function(room)
|
|
local main_room = get_main_room(room.jid);
|
|
|
|
if not main_room then
|
|
module:log('error', 'No main room (%s)!', room.jid);
|
|
return false;
|
|
end
|
|
|
|
return main_room.get_members_only(main_room)
|
|
end
|
|
|
|
-- we base affiliations (roles) in breakout rooms muc component to be based on the roles in the main muc
|
|
room_mt.get_affiliation = function(room, jid)
|
|
local main_room, _ = get_main_room(room.jid);
|
|
|
|
if not main_room then
|
|
module:log('error', 'No main room(%s) for %s!', room.jid, jid);
|
|
return 'none';
|
|
end
|
|
|
|
-- moderators in main room are moderators here
|
|
local role = main_room.get_affiliation(main_room, jid);
|
|
if role then
|
|
return role;
|
|
end
|
|
|
|
return 'none';
|
|
end
|
|
end
|
|
|
|
-- process or waits to process the breakout rooms muc component
|
|
process_host_module(breakout_rooms_muc_component_config, function(host_module, host)
|
|
module:log('info', 'Breakout rooms component created %s', host);
|
|
|
|
local muc_module = prosody.hosts[host].modules.muc;
|
|
|
|
if muc_module then
|
|
process_breakout_rooms_muc_loaded(muc_module, host_module);
|
|
else
|
|
module:log('debug', 'Will wait for muc to be available');
|
|
prosody.hosts[host].events.add_handler('module-loaded', function(event)
|
|
if (event.module == 'muc') then
|
|
process_breakout_rooms_muc_loaded(prosody.hosts[host].modules.muc, host_module);
|
|
end
|
|
end);
|
|
end
|
|
end);
|
|
|
|
-- operates on already loaded main muc module
|
|
function process_main_muc_loaded(main_muc, host_module)
|
|
module:log('debug', 'Main muc loaded');
|
|
|
|
main_muc_service = main_muc;
|
|
module:log("info", "Hook to muc events on %s", main_muc_component_config);
|
|
host_module:hook('muc-occupant-joined', on_occupant_joined);
|
|
host_module:hook('muc-occupant-left', on_occupant_left);
|
|
host_module:hook('muc-room-destroyed', on_main_room_destroyed, 1); -- prosody handles it at 0
|
|
end
|
|
|
|
-- process or waits to process the main muc component
|
|
process_host_module(main_muc_component_config, function(host_module, host)
|
|
local muc_module = prosody.hosts[host].modules.muc;
|
|
|
|
if muc_module then
|
|
process_main_muc_loaded(muc_module, host_module);
|
|
else
|
|
module:log('debug', 'Will wait for muc to be available');
|
|
prosody.hosts[host].events.add_handler('module-loaded', function(event)
|
|
if (event.module == 'muc') then
|
|
process_main_muc_loaded(prosody.hosts[host].modules.muc, host_module);
|
|
end
|
|
end);
|
|
end
|
|
end);
|