feat(visitors): Propagate moderator role to visitor nodes.

Features that depend on presence and moderator role will start working for visitors (like follow-me).
This commit is contained in:
damencho
2024-12-05 10:57:52 -06:00
committed by Дамян Минков
parent 5a45ebb877
commit b0ffc2cd69
2 changed files with 87 additions and 13 deletions

View File

@@ -14,7 +14,8 @@ local jid = require 'util.jid';
local st = require 'util.stanza';
local new_id = require 'util.id'.medium;
local filters = require 'util.filters';
local array = require"util.array";
local array = require 'util.array';
local set = require 'util.set';
local util = module:require 'util';
local ends_with = util.ends_with;
@@ -69,13 +70,11 @@ end
local function send_transcriptions_update(room)
-- let's notify main prosody
local lang_array = array{};
local lang_array = array();
local count = 0;
for k, v in pairs(room._transcription_languages) do
if not lang_array[v] then
lang_array:push(v);
end
lang_array:push(v);
count = count + 1;
end
@@ -90,7 +89,7 @@ local function send_transcriptions_update(room)
room = jid.join(jid.node(room.jid), muc_domain_prefix..'.'..main_domain) })
:tag('transcription-languages', {
xmlns = 'jitsi:visitors',
langs = lang_array:sort():concat(','),
langs = lang_array:unique():sort():concat(','),
count = tostring(count)
}):up());
end
@@ -127,8 +126,14 @@ end
module:hook('muc-occupant-pre-join', function (event)
local occupant, room, origin, stanza = event.occupant, event.room, event.origin, event.stanza;
local node, host = jid.split(occupant.bare_jid);
local resource = jid.resource(occupant.nick);
if prosody.hosts[host] and not is_admin(occupant.bare_jid) then
if is_admin(occupant.bare_jid) then
return;
end
if prosody.hosts[host] then
-- local participants which host is defined in this prosody
if room._main_room_lobby_enabled then
origin.send(st.error_reply(stanza, 'cancel', 'not-allowed', 'Visitors not allowed while lobby is on!')
:tag('no-visitors-lobby', { xmlns = 'jitsi:visitors' }));
@@ -136,6 +141,9 @@ module:hook('muc-occupant-pre-join', function (event)
else
occupant.role = 'visitor';
end
elseif room.moderators_list:contains(resource) then
-- remote participants, host is the main prosody
occupant.role = 'moderator';
end
end, 3);
@@ -399,7 +407,7 @@ local function stanza_handler(event)
local room = get_room_from_jid(room_jid_match_rewrite(room_jid));
if not room then
module:log('warn', 'No room found %s', room_jid);
module:log('warn', 'No room found %s in stanza_handler', room_jid);
return;
end
@@ -546,7 +554,15 @@ module:hook('jicofo-unlock-room', function(e)
return true;
end);
-- handles incoming iq connect stanzas
-- handles incoming iq visitors stanzas
-- connect - sent after sending all main participant's presences
-- disconnect - sent when main room is destroyed or when we receive a 'disconnect-vnode' iq from jicofo
-- update - sent on:
-- * room secret is changed
-- * lobby enabled or disabled
-- * initially before connect to report currently joined moderators
-- * moderator participant joins main room
-- * a participant has been granted moderator rights
local function iq_from_main_handler(event)
local origin, stanza = event.origin, event.stanza;
@@ -577,7 +593,7 @@ local function iq_from_main_handler(event)
local room = get_room_from_jid(room_jid_match_rewrite(room_jid));
if not room then
module:log('warn', 'No room found %s', room_jid);
module:log('warn', 'No room found %s in iq_from_main_handler for:%s', room_jid, visitors_iq);
return;
end
@@ -625,6 +641,28 @@ local function iq_from_main_handler(event)
room._main_room_lobby_enabled = false;
end
-- read the moderators list
room.moderators_list = room.moderators_list or set.new();
local moderators = node:get_child('moderators');
if moderators then
for _, child in ipairs(moderators.tags) do
if child.name == 'item' then
room.moderators_list:add(child.attr.epId);
end
end
-- let's check current occupants roles and promote them if needed
-- we change only main participants which are not moderators, but participant
for _, o in room:each_occupant() do
if not is_admin(o.bare_jid)
and o.role == 'participant'
and room.moderators_list:contains(jid.resource(o.nick)) then
room:set_affiliation(true, o.bare_jid, 'owner');
end
end
end
if fire_jicofo_unlock then
-- everything is connected allow participants to join
module:fire_event('jicofo-unlock-room', { room = room; fmuc_fired = true; });

View File

@@ -58,7 +58,7 @@ local function send_visitors_iq(conference_service, room, type)
-- send iq informing the vnode that the connect is done and it will allow visitors to join
local iq_id = new_id();
sent_iq_cache:set(iq_id, socket.gettime());
local connect_done = st.iq({
local visitors_iq = st.iq({
type = 'set',
to = conference_service,
from = module.host,
@@ -71,9 +71,23 @@ local function send_visitors_iq(conference_service, room, type)
meetingId = room._data.meetingId,
moderatorId = room._data.moderator_id, -- can be used from external modules to set single moderator for meetings
createdTimestamp = room.created_timestamp and tostring(room.created_timestamp) or nil
}):up();
});
module:send(connect_done);
if type == 'update' then
visitors_iq:tag('moderators', { xmlns = 'jitsi:visitors' });
for _, o in room:each_occupant() do
if not is_admin(o.bare_jid) and o.role == 'moderator' then
visitors_iq:tag('item', { epId = jid.resource(o.nick) }):up();
end
end
visitors_iq:up();
end
visitors_iq:up();
module:send(visitors_iq);
end
-- an event received from visitors component, which receives iqs from jicofo
@@ -97,6 +111,9 @@ local function connect_vnode(event)
local sent_main_participants = 0;
-- send update initially so we can report the moderators that will join
send_visitors_iq(conference_service, room, 'update');
for _, o in room:each_occupant() do
if not is_admin(o.bare_jid) then
local fmuc_pr = st.clone(o:get_presence());
@@ -258,6 +275,10 @@ process_host_module(main_muc_component_config, function(host_module, host)
local user, _, res = jid.split(occupant.nick);
-- a main participant we need to update all active visitor nodes
for k in pairs(vnodes) do
if occupant.role == 'moderator' then
-- first send that the participant is a moderator
send_visitors_iq(k, room, 'update');
end
local fmuc_pr = st.clone(stanza);
fmuc_pr.attr.to = jid.join(user, k, res);
fmuc_pr.attr.from = occupant.jid;
@@ -332,6 +353,21 @@ process_host_module(main_muc_component_config, function(host_module, host)
end
end
end, -100); -- we want to run last in order to check is the status code 104
host_module:hook('muc-set-affiliation', function (event)
if event.actor and not is_admin(event.actor) and event.affiliation == 'owner' then
local room = event.room;
if not visitors_nodes[room.jid] then
return;
end
-- we need to update all vnodes
local vnodes = visitors_nodes[room.jid].nodes;
for conference_service in pairs(vnodes) do
send_visitors_iq(conference_service, room, 'update');
end
end
end, -2);
end);
module:hook('jitsi-lobby-enabled', function(event)