2024-06-29 16:39:22 +00:00
|
|
|
-- mod_muc_poll
|
|
|
|
--
|
|
|
|
-- SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/>
|
|
|
|
-- SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
--
|
|
|
|
-- This file is AGPL-v3 licensed.
|
|
|
|
-- Please see the Peertube livechat plugin copyright information.
|
|
|
|
-- https://livingston.frama.io/peertube-plugin-livechat/credits/
|
|
|
|
--
|
|
|
|
-- Implements: XEP-????: MUC Poll (XEP to come).
|
|
|
|
|
2024-06-27 17:56:12 +00:00
|
|
|
local st = require "util.stanza";
|
|
|
|
local jid_bare = require "util.jid".bare;
|
|
|
|
|
|
|
|
local mod_muc = module:depends"muc";
|
|
|
|
local get_room_from_jid = mod_muc.get_room_from_jid;
|
|
|
|
|
2024-06-29 16:39:22 +00:00
|
|
|
local xmlns_poll = module:require("constants").xmlns_poll;
|
|
|
|
local send_form = module:require("form").send_form;
|
|
|
|
local process_form = module:require("form").process_form;
|
2024-06-29 17:33:37 +00:00
|
|
|
local handle_groupchat = module:require("poll").handle_groupchat;
|
2024-07-01 15:45:11 +00:00
|
|
|
local remove_specific_tags_from_groupchat = module:require("message").remove_specific_tags_from_groupchat;
|
|
|
|
local handle_new_occupant_session = module:require("message").handle_new_occupant_session;
|
2024-06-30 13:30:33 +00:00
|
|
|
local room_restored = module:require("poll").room_restored;
|
2024-06-27 17:56:12 +00:00
|
|
|
|
2024-07-04 12:04:33 +00:00
|
|
|
local poll_groupchat_votes_priority = module:get_option_number("poll_groupchat_votes_priority") or 500;
|
|
|
|
|
|
|
|
|
2024-06-27 17:56:12 +00:00
|
|
|
-- new poll creation, get form
|
|
|
|
module:hook("iq-get/bare/" .. xmlns_poll .. ":query", function (event)
|
|
|
|
local origin, stanza = event.origin, event.stanza;
|
|
|
|
local room_jid = stanza.attr.to;
|
|
|
|
module:log("debug", "Received a request for the poll form");
|
|
|
|
local room = get_room_from_jid(room_jid);
|
|
|
|
if not room then
|
|
|
|
origin.send(st.error_reply(stanza, "cancel", "item-not-found"));
|
|
|
|
return true;
|
|
|
|
end
|
|
|
|
local from = jid_bare(stanza.attr.from);
|
|
|
|
|
|
|
|
local from_affiliation = room:get_affiliation(from);
|
|
|
|
if (from_affiliation ~= "owner" and from_affiliation ~= "admin") then
|
|
|
|
origin.send(st.error_reply(stanza, "auth", "forbidden"))
|
|
|
|
return true;
|
|
|
|
end
|
|
|
|
|
|
|
|
send_form(room, origin, stanza);
|
|
|
|
return true;
|
|
|
|
end);
|
|
|
|
|
2024-06-29 16:15:04 +00:00
|
|
|
-- new poll creation, form submission
|
|
|
|
module:hook("iq-set/bare/" .. xmlns_poll .. ":query", function (event)
|
|
|
|
local origin, stanza = event.origin, event.stanza;
|
|
|
|
local room_jid = stanza.attr.to;
|
2024-06-30 15:19:14 +00:00
|
|
|
local from = stanza.attr.from;
|
|
|
|
module:log("debug", "Received a form submission for the poll form on %s from %s", room_jid, from);
|
2024-06-29 16:15:04 +00:00
|
|
|
local room = get_room_from_jid(room_jid);
|
|
|
|
if not room then
|
|
|
|
origin.send(st.error_reply(stanza, "cancel", "item-not-found"));
|
|
|
|
return true;
|
|
|
|
end
|
|
|
|
|
2024-06-30 15:19:14 +00:00
|
|
|
local occupant = room:get_occupant_by_real_jid(from);
|
|
|
|
if not occupant then
|
|
|
|
module:log("debug", "No occupant, ignoring...");
|
|
|
|
origin.send(st.error_reply(stanza, "auth", "forbidden"))
|
|
|
|
return true;
|
|
|
|
end
|
|
|
|
|
|
|
|
local from_bare = jid_bare(stanza.attr.from);
|
|
|
|
local from_affiliation = room:get_affiliation(from_bare);
|
2024-06-29 16:15:04 +00:00
|
|
|
if (from_affiliation ~= "owner" and from_affiliation ~= "admin") then
|
|
|
|
origin.send(st.error_reply(stanza, "auth", "forbidden"))
|
|
|
|
return true;
|
|
|
|
end
|
|
|
|
|
2024-06-30 15:19:14 +00:00
|
|
|
return process_form(room, origin, stanza, occupant);
|
2024-06-29 16:15:04 +00:00
|
|
|
end);
|
|
|
|
|
2024-06-27 17:56:12 +00:00
|
|
|
-- Discovering support
|
|
|
|
module:hook("muc-disco#info", function (event)
|
|
|
|
event.reply:tag("feature", { var = xmlns_poll }):up();
|
|
|
|
end);
|
2024-06-29 17:33:37 +00:00
|
|
|
|
2024-06-30 13:30:33 +00:00
|
|
|
-- On groupchat messages, we check if this is a vote for the current poll.
|
|
|
|
-- Note: we use a high priority, so it will be handled before the slow mode.
|
2024-07-04 12:04:33 +00:00
|
|
|
module:hook("muc-occupant-groupchat", handle_groupchat, poll_groupchat_votes_priority);
|
2024-06-30 13:30:33 +00:00
|
|
|
|
2024-07-01 13:01:30 +00:00
|
|
|
-- security check: we must remove all specific tags, to be sure nobody tries to spoof polls!
|
|
|
|
module:hook("muc-occupant-groupchat", remove_specific_tags_from_groupchat, 1000);
|
|
|
|
|
2024-06-30 13:30:33 +00:00
|
|
|
-- when a room is restored (after a server restart for example),
|
|
|
|
-- we must resume any current poll
|
|
|
|
module:hook("muc-room-restored", room_restored);
|
2024-07-01 15:45:11 +00:00
|
|
|
|
|
|
|
-- when a new session is opened, we must send the current poll to the client
|
|
|
|
-- Note: it should be in the MAM. But it is easier for clients to ignore delayed messages
|
|
|
|
-- when displaying polls (to ignore old polls).
|
|
|
|
module:hook("muc-occupant-session-new", handle_new_occupant_session);
|