parent
212076c3a3
commit
b741959312
@ -3,10 +3,18 @@
|
|||||||
|
|
||||||
local id = require "util.id";
|
local id = require "util.id";
|
||||||
local st = require "util.stanza";
|
local st = require "util.stanza";
|
||||||
local format = require"util.format".format;
|
local timer = require "util.timer";
|
||||||
local xmlns_occupant_id = "urn:xmpp:occupant-id:0";
|
local xmlns_occupant_id = "urn:xmpp:occupant-id:0";
|
||||||
|
local xmlns_replace = "urn:xmpp:message-correct:0";
|
||||||
|
|
||||||
local function build_poll_message(room, message_id)
|
local mod_muc = module:depends"muc";
|
||||||
|
local get_room_from_jid = mod_muc.get_room_from_jid;
|
||||||
|
|
||||||
|
local debounce_delay = 10; -- number of seconds during which we must group votes to avoid flood.
|
||||||
|
local scheduled_updates = {};
|
||||||
|
|
||||||
|
-- construct the poll message stanza
|
||||||
|
local function build_poll_message(room, message_id, is_end_message)
|
||||||
local current_poll = room._data.current_poll;
|
local current_poll = room._data.current_poll;
|
||||||
if not current_poll then
|
if not current_poll then
|
||||||
return nil;
|
return nil;
|
||||||
@ -15,6 +23,10 @@ local function build_poll_message(room, message_id)
|
|||||||
|
|
||||||
local content = current_poll["muc#roompoll_question"] .. "\n";
|
local content = current_poll["muc#roompoll_question"] .. "\n";
|
||||||
|
|
||||||
|
if is_end_message then
|
||||||
|
content = content .. "This poll is now over.\n";
|
||||||
|
end
|
||||||
|
|
||||||
local total = 0;
|
local total = 0;
|
||||||
for choice, nb in pairs(current_poll.votes_by_choices) do
|
for choice, nb in pairs(current_poll.votes_by_choices) do
|
||||||
total = total + nb;
|
total = total + nb;
|
||||||
@ -23,12 +35,15 @@ local function build_poll_message(room, message_id)
|
|||||||
content = content .. choice .. ': ' .. label;
|
content = content .. choice .. ': ' .. label;
|
||||||
if total > 0 then
|
if total > 0 then
|
||||||
local nb = current_poll.votes_by_choices[choice] or 0;
|
local nb = current_poll.votes_by_choices[choice] or 0;
|
||||||
local percent = format("%d.%d%d", nb * 100 / total);
|
local percent = string.format("%.2f", nb * 100 / total);
|
||||||
content = content .. " (" .. nb .. "/" .. total .. " = " .. percent .. "%)";
|
content = content .. " (" .. nb .. "/" .. total .. " = " .. percent .. "%)";
|
||||||
end
|
end
|
||||||
content = content .. "\n";
|
content = content .. "\n";
|
||||||
end
|
end
|
||||||
content = content .. "Send a message with an exclamation mark followed by your choice number to vote. Example: !1\n";
|
|
||||||
|
if not is_end_message then
|
||||||
|
content = content .. "Send a message with an exclamation mark followed by your choice number to vote. Example: !1\n";
|
||||||
|
end
|
||||||
|
|
||||||
local msg = st.message({
|
local msg = st.message({
|
||||||
type = "groupchat",
|
type = "groupchat",
|
||||||
@ -44,32 +59,67 @@ local function build_poll_message(room, message_id)
|
|||||||
return msg;
|
return msg;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- sends a message when the poll starts.
|
||||||
local function poll_start_message(room)
|
local function poll_start_message(room)
|
||||||
if not room._data.current_poll then
|
if not room._data.current_poll then
|
||||||
return nil;
|
return nil;
|
||||||
end
|
end
|
||||||
module:log("debug", "Sending the start message for room %s poll", room.jid);
|
module:log("debug", "Sending the start message for room %s poll", room.jid);
|
||||||
local message_id = id.medium();
|
local message_id = id.medium();
|
||||||
local msg = build_poll_message(room, message_id);
|
local msg = build_poll_message(room, message_id, false);
|
||||||
room:broadcast_message(msg);
|
room:broadcast_message(msg);
|
||||||
return message_id;
|
return message_id;
|
||||||
end
|
end
|
||||||
|
|
||||||
local function schedule_poll_update_message(room)
|
-- Send the poll update message
|
||||||
-- TODO
|
local function send_poll_update_message(room)
|
||||||
|
if not room._data.current_poll then
|
||||||
|
return nil;
|
||||||
|
end
|
||||||
|
module:log("debug", "Sending an update message for room %s poll", room.jid);
|
||||||
|
local message_id = id.medium(); -- generate a new id
|
||||||
|
local msg = build_poll_message(room, message_id, false);
|
||||||
|
|
||||||
-- if not room._data.current_poll then
|
-- the update message is a <replace> message (see XEP-0308).
|
||||||
-- return nil;
|
msg:tag('replace', {
|
||||||
-- end
|
xmlns = xmlns_replace;
|
||||||
-- module:log("debug", "Sending an update message for room %s poll", room.jid);
|
id = room._data.current_poll.start_message_id;
|
||||||
-- local message_id = id.medium();
|
}):up();
|
||||||
-- local msg = build_poll_message(room, message_id);
|
|
||||||
-- room:broadcast_message(msg);
|
room:broadcast_message(msg);
|
||||||
-- return message_id;
|
return message_id;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Schedule an update of the start message.
|
||||||
|
-- We do not send this update each time someone vote,
|
||||||
|
-- to avoid flooding.
|
||||||
|
local function schedule_poll_update_message(room_jid)
|
||||||
|
if scheduled_updates[room_jid] then
|
||||||
|
-- already a running timer, we can ignore to debounce.
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
scheduled_updates[room_jid] = timer.add_task(debounce_delay, function()
|
||||||
|
scheduled_updates[room_jid] = nil;
|
||||||
|
-- We dont pass room, because here it could have been removed from memory.
|
||||||
|
-- So we must relad the room from the JID in any case.
|
||||||
|
local room = get_room_from_jid(room_jid);
|
||||||
|
if not room then
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
send_poll_update_message(room);
|
||||||
|
end);
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Send a new message when the poll is over, with the result.
|
||||||
local function poll_end_message(room)
|
local function poll_end_message(room)
|
||||||
-- TODO
|
if not room._data.current_poll then
|
||||||
|
return nil;
|
||||||
|
end
|
||||||
|
module:log("debug", "Sending the end message for room %s poll", room.jid);
|
||||||
|
local message_id = id.medium(); -- generate a new id
|
||||||
|
local msg = build_poll_message(room, message_id, true);
|
||||||
|
room:broadcast_message(msg);
|
||||||
|
return message_id;
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -56,7 +56,9 @@ local function end_current_poll (room)
|
|||||||
timer.stop(scheduled_end[room_jid]);
|
timer.stop(scheduled_end[room_jid]);
|
||||||
scheduled_end[room_jid] = nil;
|
scheduled_end[room_jid] = nil;
|
||||||
end
|
end
|
||||||
|
|
||||||
poll_end_message(room);
|
poll_end_message(room);
|
||||||
|
|
||||||
-- TODO: store the result somewhere, to keep track?
|
-- TODO: store the result somewhere, to keep track?
|
||||||
|
|
||||||
-- We don't remove the poll immediatly. Indeed, if the vote is anonymous,
|
-- We don't remove the poll immediatly. Indeed, if the vote is anonymous,
|
||||||
@ -173,18 +175,18 @@ local function handle_groupchat(event)
|
|||||||
module:log("debug", "Counting a new vote for room %s: choice %i, voter %s", room.jid, choice, occupant_bare_id);
|
module:log("debug", "Counting a new vote for room %s: choice %i, voter %s", room.jid, choice, occupant_bare_id);
|
||||||
-- counting the vote:
|
-- counting the vote:
|
||||||
if room._data.current_poll.votes_by_occupant[occupant_bare_id] ~= nil then
|
if room._data.current_poll.votes_by_occupant[occupant_bare_id] ~= nil then
|
||||||
module:log("debug", "Occupant %s has already voted for current room %s vote, reassigning his vote.", occupant_bare_id);
|
module:log("debug", "Occupant %s has already voted for current room %s vote, reassigning his vote.", occupant_bare_id, room.jid);
|
||||||
room._data.current_poll.votes_by_choices[room._data.current_poll.votes_by_occupant[occupant_bare_id]] = room._data.current_poll.votes_by_choices[room._data.current_poll.votes_by_occupant[occupant_bare_id]] - 1;
|
room._data.current_poll.votes_by_choices[room._data.current_poll.votes_by_occupant[occupant_bare_id]] = room._data.current_poll.votes_by_choices[room._data.current_poll.votes_by_occupant[occupant_bare_id]] - 1;
|
||||||
end
|
end
|
||||||
room._data.current_poll.votes_by_choices[choice] = room._data.current_poll.votes_by_choices[choice] + 1;
|
room._data.current_poll.votes_by_choices[choice] = room._data.current_poll.votes_by_choices[choice] + 1;
|
||||||
room._data.current_poll.votes_by_occupant[occupant_bare_id] = choice;
|
room._data.current_poll.votes_by_occupant[occupant_bare_id] = choice;
|
||||||
|
|
||||||
schedule_poll_update_message(room);
|
schedule_poll_update_message(room.jid);
|
||||||
|
|
||||||
-- When the poll is anonymous, we bounce the messages (but count the votes).
|
-- When the poll is anonymous, we bounce the messages (but count the votes).
|
||||||
local must_bounce = room._data.current_poll["muc#roompoll_anonymous"] == true;
|
local must_bounce = room._data.current_poll["muc#roompoll_anonymous"] == true;
|
||||||
if must_bounce then
|
if must_bounce then
|
||||||
module:log("debug", "Invalid vote, bouncing it.");
|
module:log("debug", "Anonymous votes, bouncing it.");
|
||||||
origin.send(st.error_reply(
|
origin.send(st.error_reply(
|
||||||
stanza,
|
stanza,
|
||||||
-- error_type
|
-- error_type
|
||||||
@ -218,7 +220,7 @@ local function room_restored(event)
|
|||||||
schedule_poll_end(room.jid, room._data.current_poll.end_timestamp);
|
schedule_poll_end(room.jid, room._data.current_poll.end_timestamp);
|
||||||
end
|
end
|
||||||
-- just in case, we can also reschedule an update message
|
-- just in case, we can also reschedule an update message
|
||||||
schedule_poll_update_message(room);
|
schedule_poll_update_message(room.jid);
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user