mirror of
https://git.lapiole.org/dani/ansible-roles.git
synced 2025-08-05 16:17:38 +02:00
Update to 2025-06-16 16:00
This commit is contained in:
@@ -14,8 +14,11 @@ 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 set = require 'util.set';
|
||||
|
||||
local util = module:require 'util';
|
||||
local is_admin = util.is_admin;
|
||||
local ends_with = util.ends_with;
|
||||
local is_vpaas = util.is_vpaas;
|
||||
local room_jid_match_rewrite = util.room_jid_match_rewrite;
|
||||
@@ -23,6 +26,12 @@ local get_room_from_jid = util.get_room_from_jid;
|
||||
local get_focus_occupant = util.get_focus_occupant;
|
||||
local internal_room_jid_match_rewrite = util.internal_room_jid_match_rewrite;
|
||||
local presence_check_status = util.presence_check_status;
|
||||
local respond_iq_result = util.respond_iq_result;
|
||||
|
||||
local PARTICIPANT_PROP_RAISE_HAND = 'jitsi_participant_raisedHand';
|
||||
local PARTICIPANT_PROP_REQUEST_TRANSCRIPTION = 'jitsi_participant_requestingTranscription';
|
||||
local PARTICIPANT_PROP_TRANSLATION_LANG = 'jitsi_participant_translation_language';
|
||||
local TRANSCRIPT_DEFAULT_LANG = module:get_option_string('transcriptions_default_language', 'en');
|
||||
|
||||
-- this is the main virtual host of this vnode
|
||||
local local_domain = module:get_option_string('muc_mapper_domain_base');
|
||||
@@ -43,6 +52,9 @@ local local_muc_domain = muc_domain_prefix..'.'..local_domain;
|
||||
|
||||
local NICK_NS = 'http://jabber.org/protocol/nick';
|
||||
|
||||
-- in certain cases we consider participants with token as moderators, this is the default behavior which can be turned off
|
||||
local auto_promoted_with_token = module:get_option_boolean('visitors_auto_promoted_with_token', true);
|
||||
|
||||
-- we send stats for the total number of rooms, total number of participants and total number of visitors
|
||||
local measure_rooms = module:measure('vnode-rooms', 'amount');
|
||||
local measure_participants = module:measure('vnode-participants', 'amount');
|
||||
@@ -52,17 +64,72 @@ local sent_iq_cache = require 'util.cache'.new(200);
|
||||
|
||||
local sessions = prosody.full_sessions;
|
||||
|
||||
local um_is_admin = require 'core.usermanager'.is_admin;
|
||||
local function is_admin(jid)
|
||||
return um_is_admin(jid, module.host);
|
||||
local function send_transcriptions_update(room)
|
||||
-- let's notify main prosody
|
||||
local lang_array = array();
|
||||
local count = 0;
|
||||
|
||||
for k, v in pairs(room._transcription_languages) do
|
||||
lang_array:push(v);
|
||||
count = count + 1;
|
||||
end
|
||||
|
||||
local iq_id = new_id();
|
||||
sent_iq_cache:set(iq_id, socket.gettime());
|
||||
module:send(st.iq({
|
||||
type = 'set',
|
||||
to = 'visitors.'..main_domain,
|
||||
from = local_domain,
|
||||
id = iq_id })
|
||||
:tag('visitors', { xmlns = 'jitsi:visitors',
|
||||
room = jid.join(jid.node(room.jid), muc_domain_prefix..'.'..main_domain) })
|
||||
:tag('transcription-languages', {
|
||||
xmlns = 'jitsi:visitors',
|
||||
langs = lang_array:unique():sort():concat(','),
|
||||
count = tostring(count)
|
||||
}):up());
|
||||
end
|
||||
|
||||
local function remove_transcription(room, occupant)
|
||||
local send_update = false;
|
||||
if room._transcription_languages then
|
||||
if room._transcription_languages[occupant.jid] then
|
||||
send_update = true;
|
||||
end
|
||||
room._transcription_languages[occupant.jid] = nil;
|
||||
end
|
||||
|
||||
if send_update then
|
||||
send_transcriptions_update(room);
|
||||
end
|
||||
end
|
||||
|
||||
-- if lang is nil we will remove it from the list
|
||||
local function add_transcription(room, occupant, lang)
|
||||
if not room._transcription_languages then
|
||||
room._transcription_languages = {};
|
||||
end
|
||||
|
||||
local old = room._transcription_languages[occupant.jid];
|
||||
room._transcription_languages[occupant.jid] = lang or TRANSCRIPT_DEFAULT_LANG;
|
||||
|
||||
if old ~= room._transcription_languages[occupant.jid] then
|
||||
send_transcriptions_update(room);
|
||||
end
|
||||
end
|
||||
|
||||
-- mark all occupants as visitors
|
||||
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' }));
|
||||
@@ -70,6 +137,9 @@ module:hook('muc-occupant-pre-join', function (event)
|
||||
else
|
||||
occupant.role = 'visitor';
|
||||
end
|
||||
elseif room.moderators_list and room.moderators_list:contains(resource) then
|
||||
-- remote participants, host is the main prosody
|
||||
occupant.role = 'moderator';
|
||||
end
|
||||
end, 3);
|
||||
|
||||
@@ -89,7 +159,7 @@ module:hook('muc-occupant-pre-leave', function (event)
|
||||
-- to main prosody
|
||||
local pr = occupant:get_presence();
|
||||
|
||||
local raiseHand = pr:get_child_text('jitsi_participant_raisedHand');
|
||||
local raiseHand = pr:get_child_text(PARTICIPANT_PROP_RAISE_HAND);
|
||||
|
||||
-- a promotion detected let's send it to main prosody
|
||||
if raiseHand and #raiseHand > 0 then
|
||||
@@ -111,6 +181,7 @@ module:hook('muc-occupant-pre-leave', function (event)
|
||||
module:send(promotion_request);
|
||||
end
|
||||
|
||||
remove_transcription(room, occupant);
|
||||
end, 1); -- rate limit is 0
|
||||
|
||||
-- Returns the main participants count and the visitors count
|
||||
@@ -136,6 +207,20 @@ local function cancel_destroy_timer(room)
|
||||
end
|
||||
end
|
||||
|
||||
local function destroy_with_conference_ended(room)
|
||||
-- if the room is being destroyed, ignore
|
||||
if room.destroying then
|
||||
return;
|
||||
end
|
||||
|
||||
cancel_destroy_timer(room);
|
||||
|
||||
local main_count, visitors_count = get_occupant_counts(room);
|
||||
module:log('info', 'Will destroy:%s main_occupants:%s visitors:%s', room.jid, main_count, visitors_count);
|
||||
room:destroy(nil, 'Conference ended.');
|
||||
return true;
|
||||
end
|
||||
|
||||
-- schedules a new destroy timer which will destroy the room if there are no visitors after the timeout
|
||||
local function schedule_destroy_timer(room)
|
||||
cancel_destroy_timer(room);
|
||||
@@ -165,7 +250,9 @@ module:hook('muc-occupant-left', function (event)
|
||||
if prosody.hosts[occupant_domain] and not is_admin(occupant.bare_jid) then
|
||||
local focus_occupant = get_focus_occupant(room);
|
||||
if not focus_occupant then
|
||||
module:log('info', 'No focus found for %s', room.jid);
|
||||
if not room.destroying then
|
||||
module:log('warn', 'No focus found for %s', room.jid);
|
||||
end
|
||||
return;
|
||||
end
|
||||
-- Let's forward unavailable presence to the special jicofo
|
||||
@@ -194,10 +281,15 @@ module:hook('muc-occupant-left', function (event)
|
||||
if visitors_count == 0 then
|
||||
schedule_destroy_timer(room);
|
||||
end
|
||||
|
||||
if main_count == 0 then
|
||||
destroy_with_conference_ended(room);
|
||||
end
|
||||
end);
|
||||
|
||||
-- forward visitor presences to jicofo
|
||||
-- detects raise hand in visitors presence, this is request for promotion
|
||||
-- detects the requested transcription and its language to send updates for it
|
||||
module:hook('muc-broadcast-presence', function (event)
|
||||
local occupant = event.occupant;
|
||||
|
||||
@@ -227,10 +319,11 @@ module:hook('muc-broadcast-presence', function (event)
|
||||
full_p.attr.to = focus_occupant.jid;
|
||||
room:route_to_occupant(focus_occupant, full_p);
|
||||
|
||||
local raiseHand = full_p:get_child_text('jitsi_participant_raisedHand');
|
||||
local raiseHand = full_p:get_child_text(PARTICIPANT_PROP_RAISE_HAND);
|
||||
-- a promotion detected let's send it to main prosody
|
||||
if raiseHand then
|
||||
local user_id;
|
||||
local group_id;
|
||||
local is_moderator;
|
||||
local session = sessions[occupant.jid];
|
||||
local identity = session and session.jitsi_meet_context_user;
|
||||
@@ -246,14 +339,14 @@ module:hook('muc-broadcast-presence', function (event)
|
||||
-- so we can be auto promoted
|
||||
if identity and identity.id then
|
||||
user_id = session.jitsi_meet_context_user.id;
|
||||
group_id = session.jitsi_meet_context_group;
|
||||
|
||||
if room._data.moderator_id then
|
||||
if room._data.moderator_id == user_id then
|
||||
if session.auth_token and auto_promoted_with_token then
|
||||
if not session.jitsi_meet_tenant_mismatch or session.jitsi_web_query_prefix == '' then
|
||||
-- non-vpaas and having a token is considered a moderator, and if it is not in '/' tenant
|
||||
-- the tenant from url and token should match
|
||||
is_moderator = true;
|
||||
end
|
||||
elseif session.auth_token then
|
||||
-- non-vpass and having a token is considered a moderator
|
||||
is_moderator = true;
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -272,6 +365,7 @@ module:hook('muc-broadcast-presence', function (event)
|
||||
jid = occupant.jid,
|
||||
time = raiseHand,
|
||||
userId = user_id,
|
||||
groupId = group_id,
|
||||
forcePromote = is_moderator and 'true' or 'false';
|
||||
}):up();
|
||||
|
||||
@@ -283,6 +377,18 @@ module:hook('muc-broadcast-presence', function (event)
|
||||
module:send(promotion_request);
|
||||
end
|
||||
|
||||
local requestTranscriptionValue = full_p:get_child_text(PARTICIPANT_PROP_REQUEST_TRANSCRIPTION);
|
||||
local hasTranscriptionEnabled = room._transcription_languages and room._transcription_languages[occupant.jid];
|
||||
|
||||
-- detect transcription
|
||||
if requestTranscriptionValue == 'true' then
|
||||
local lang = full_p:get_child_text(PARTICIPANT_PROP_TRANSLATION_LANG);
|
||||
|
||||
add_transcription(room, occupant, lang);
|
||||
elseif hasTranscriptionEnabled then
|
||||
remove_transcription(room, occupant, nil);
|
||||
end
|
||||
|
||||
return;
|
||||
end);
|
||||
|
||||
@@ -317,7 +423,6 @@ 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);
|
||||
return;
|
||||
end
|
||||
|
||||
@@ -327,12 +432,7 @@ local function stanza_handler(event)
|
||||
end
|
||||
|
||||
-- respond with successful receiving the iq
|
||||
origin.send(st.iq({
|
||||
type = 'result';
|
||||
from = stanza.attr.to;
|
||||
to = stanza.attr.from;
|
||||
id = stanza.attr.id
|
||||
}));
|
||||
respond_iq_result(origin, stanza);
|
||||
|
||||
local req_jid = request_promotion.attr.jid;
|
||||
-- now let's find the occupant and forward the response
|
||||
@@ -469,7 +569,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;
|
||||
|
||||
@@ -500,7 +608,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
|
||||
|
||||
@@ -523,27 +631,16 @@ local function iq_from_main_handler(event)
|
||||
end
|
||||
|
||||
-- respond with successful receiving the iq
|
||||
origin.send(st.iq({
|
||||
type = 'result';
|
||||
from = stanza.attr.to;
|
||||
to = stanza.attr.from;
|
||||
id = stanza.attr.id
|
||||
}));
|
||||
respond_iq_result(origin, stanza);
|
||||
|
||||
if process_disconnect then
|
||||
cancel_destroy_timer(room);
|
||||
|
||||
local main_count, visitors_count = get_occupant_counts(room);
|
||||
module:log('info', 'Will destroy:%s main_occupants:%s visitors:%s', room.jid, main_count, visitors_count);
|
||||
room:destroy(nil, 'Conference ended.');
|
||||
return true;
|
||||
return destroy_with_conference_ended(room);
|
||||
end
|
||||
|
||||
-- if there is password supplied use it
|
||||
-- if this is update it will either set or remove the password
|
||||
room:set_password(node.attr.password);
|
||||
room._data.meetingId = node.attr.meetingId;
|
||||
room._data.moderator_id = node.attr.moderatorId;
|
||||
local createdTimestamp = node.attr.createdTimestamp;
|
||||
room.created_timestamp = createdTimestamp and tonumber(createdTimestamp) or nil;
|
||||
|
||||
@@ -553,6 +650,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; });
|
||||
|
Reference in New Issue
Block a user