screen layout and poll fix

This commit is contained in:
2026-05-20 19:24:56 +05:30
parent 90ccbb20bc
commit 43a6321c0c
6 changed files with 173 additions and 13 deletions

View File

@@ -10,6 +10,10 @@ local ROOM_INACTIVE_CALLBACK_URL = module:get_option_string(
"politictalk_room_inactive_callback_url",
os.getenv("POLITICTALK_ROOM_INACTIVE_CALLBACK_URL")
);
local ROOM_OCCUPANCY_CALLBACK_URL = module:get_option_string(
"politictalk_room_occupancy_callback_url",
os.getenv("POLITICTALK_ROOM_OCCUPANCY_CALLBACK_URL")
);
local ROOM_INACTIVE_CALLBACK_SECRET = module:get_option_string(
"politictalk_room_inactive_callback_secret",
os.getenv("POLITICTALK_ROOM_INACTIVE_CALLBACK_SECRET")
@@ -26,6 +30,18 @@ local function get_user_id(session)
return user and user.id or nil;
end
local function get_participant_limit(session)
local user = get_user(session);
local limit = user and (user.participantLimit or user.participant_limit) or nil;
local numeric_limit = tonumber(limit);
if numeric_limit and numeric_limit > 0 then
return math.floor(numeric_limit);
end
return nil;
end
local function is_moderator_session(session)
local user = get_user(session);
local moderator = user and user.moderator;
@@ -77,6 +93,16 @@ local function remove_value(values, value)
return filtered;
end
local function table_count(values)
local count = 0;
for _ in ipairs(values or {}) do
count = count + 1;
end
return count;
end
local function ensure_room_data(room)
if not room then
return false;
@@ -86,6 +112,7 @@ local function ensure_room_data(room)
room._data.moderators = room._data.moderators or {};
room._data.participants = room._data.participants or {};
room._data.politictalk_host_jids = room._data.politictalk_host_jids or {};
room._data.politictalk_participant_jids = room._data.politictalk_participant_jids or {};
room._data.politictalk_jid_user_ids = room._data.politictalk_jid_user_ids or {};
-- Enables Jitsi AV moderation automatically: hosts can speak, participants
-- must be explicitly allowed by a host before they can unmute.
@@ -119,6 +146,7 @@ local function mark_host(room, occupant, user_id)
ensure_room_data(room);
room._data.politictalk_host_jids = add_unique(room._data.politictalk_host_jids, occupant.bare_jid);
room._data.politictalk_participant_jids = remove_value(room._data.politictalk_participant_jids, occupant.bare_jid);
room._data.politictalk_jid_user_ids[occupant.bare_jid] = user_id;
end
@@ -128,6 +156,7 @@ local function mark_participant(room, occupant, user_id)
end
ensure_room_data(room);
room._data.politictalk_participant_jids = add_unique(room._data.politictalk_participant_jids, occupant.bare_jid);
room._data.politictalk_jid_user_ids[occupant.bare_jid] = user_id;
end
@@ -141,6 +170,7 @@ local function unmark_occupant(room, occupant)
local user_id = room._data.politictalk_jid_user_ids[occupant.bare_jid];
room._data.politictalk_jid_user_ids[occupant.bare_jid] = nil;
room._data.politictalk_host_jids = remove_value(room._data.politictalk_host_jids, occupant.bare_jid);
room._data.politictalk_participant_jids = remove_value(room._data.politictalk_participant_jids, occupant.bare_jid);
return user_id;
end
@@ -161,6 +191,36 @@ local function has_active_host(room)
return false;
end
local function get_active_host_count(room)
if not room then
return 0;
end
ensure_room_data(room);
local count = 0;
for _, occupant in room:each_occupant() do
if table_contains(room._data.politictalk_host_jids, occupant.bare_jid) then
count = count + 1;
end
end
return count;
end
local function get_occupant_count(room)
if not room then
return 0;
end
local count = 0;
for _ in room:each_occupant() do
count = count + 1;
end
return count;
end
local function deny_join(event, reason)
if event.origin and event.stanza then
event.origin.send(st.error_reply(event.stanza, "cancel", "not-allowed", reason));
@@ -225,6 +285,66 @@ local function notify_room_inactive(room, reason)
end);
end
local function notify_room_occupancy(room, reason)
if
not ROOM_OCCUPANCY_CALLBACK_URL
or ROOM_OCCUPANCY_CALLBACK_URL == ""
or not ROOM_INACTIVE_CALLBACK_SECRET
or ROOM_INACTIVE_CALLBACK_SECRET == ""
then
module:log("warn", "Skipping PoliticTalk room-occupancy callback because callback URL or secret is missing");
return;
end
local meeting_code = get_room_meeting_code(room);
if not meeting_code then
module:log("warn", "Skipping PoliticTalk room-occupancy callback because room meeting code is missing");
return;
end
ensure_room_data(room);
local participant_count = table_count(room._data.politictalk_participant_jids);
local moderator_count = table_count(room._data.moderators);
local occupant_count = get_occupant_count(room);
local host_count = get_active_host_count(room);
http.request(ROOM_OCCUPANCY_CALLBACK_URL, {
method = "POST";
headers = {
["Content-Type"] = "application/json";
["X-PoliticTalk-Jitsi-Secret"] = ROOM_INACTIVE_CALLBACK_SECRET;
};
body = json.encode({
meetingCode = meeting_code;
reason = reason or "occupancy_changed";
roomJid = room.jid;
participantCount = participant_count;
moderatorCount = moderator_count;
occupantCount = occupant_count;
hostCount = host_count;
});
}, function(_, code)
if code and code >= 200 and code < 300 then
module:log(
"info",
"Updated PoliticTalk room occupancy in PgApi: room=%s participants=%s occupants=%s hosts=%s",
tostring(meeting_code),
tostring(participant_count),
tostring(occupant_count),
tostring(host_count)
);
else
module:log(
"warn",
"Failed to update PoliticTalk room occupancy in PgApi: room=%s status=%s",
tostring(meeting_code),
tostring(code)
);
end
end);
end
module:hook("muc-room-pre-create", function(event)
if event.stanza and event.stanza.attr and is_admin(event.stanza.attr.from) then
return;
@@ -260,6 +380,26 @@ module:hook("muc-occupant-pre-join", function(event)
return deny_join(event, "PoliticTalk room is waiting for the host");
end
if not is_moderator then
ensure_room_data(room);
local participant_limit = get_participant_limit(session);
local active_participant_count = table_count(room._data.politictalk_participant_jids);
if
participant_limit
and active_participant_count >= participant_limit
then
module:log(
"warn",
"Blocking participant %s because PoliticTalk room is full: room=%s active=%s limit=%s",
tostring(user_id),
tostring(room and room.jid),
tostring(active_participant_count),
tostring(participant_limit)
);
return deny_join(event, "PoliticTalk room is full");
end
end
ROLE_JOINING[occupant_jid] = {
is_moderator = is_moderator;
user_id = user_id;
@@ -298,6 +438,8 @@ module:hook("muc-occupant-joined", function(event)
room:set_affiliation(true, occupant.bare_jid, "member");
module:log("info", "PoliticTalk participant joined as member: %s room=%s", tostring(role.user_id), tostring(room.jid));
end
notify_room_occupancy(room, "occupant_joined");
end, 1);
module:hook("muc-occupant-left", function(event)
@@ -317,6 +459,8 @@ module:hook("muc-occupant-left", function(event)
module:log("info", "Destroying PoliticTalk room after host left: %s", tostring(room.jid));
notify_room_inactive(room, "host_left");
room:destroy(nil, "The host has left the PoliticTalk room");
else
notify_room_occupancy(room, "occupant_left");
end
end, -20);