MUC: Support MUC voice requests and approvals in moderated rooms (closes #655) (thanks to Lance Stout)
authorKim Alvefur <zash@zash.se>
Fri, 20 Oct 2017 05:19:25 +0200
changeset 8854 ab5f678f1376
parent 8853 26f1a49fa9c0
child 8855 5e98d62f3f9b
MUC: Support MUC voice requests and approvals in moderated rooms (closes #655) (thanks to Lance Stout)
plugins/muc/moderated.lib.lua
plugins/muc/muc.lib.lua
--- a/plugins/muc/moderated.lib.lua	Fri Jun 01 08:47:07 2018 +0200
+++ b/plugins/muc/moderated.lib.lua	Fri Oct 20 05:19:25 2017 +0200
@@ -7,6 +7,10 @@
 -- COPYING file in the source package for more information.
 --
 
+local st = require "util.stanza";
+local dataform = require "util.dataforms";
+
+
 local function get_moderated(room)
 	return room._data.moderated;
 end
@@ -45,6 +49,71 @@
 	end
 end, 1);
 
+module:hook("muc-voice-request", function(event)
+	if event.occupant.role == "visitor" then
+		local form = dataform.new({
+			title = "Voice Request";
+			{
+				name = "FORM_TYPE";
+				type = "hidden";
+				value = "http://jabber.org/protocol/muc#request";
+			},
+			{
+				name = "muc#role";
+				type = "text-single";
+				label = "Requested Role";
+				value = "participant";
+			},
+			{
+				name = "muc#jid";
+				type = "jid-single";
+				label = "User ID";
+				value = event.stanza.attr.from;
+			},
+			{
+				name = "muc#roomnick";
+				type = "text-single";
+				label = "Room Nickname";
+				value = event.occupant.nick;
+			},
+			{
+				name = "muc#request_allow";
+				type = "boolean";
+				label = "Grant voice to this person?";
+				value = false;
+			}
+		});
+
+		local message = st.message({ type = "normal"; from = event.room.jid }):add_child(form:form()):up();
+
+		event.room:broadcast(message, function (nick, occupant)
+			return occupant.role == "moderator";
+		end);
+	end
+end);
+
+module:hook("muc-voice-response", function(event)
+	local actor = event.stanza.attr.from;
+	local affected_occupant = event.room:get_occupant_by_real_jid(event.fields["muc#jid"]);
+
+	if event.occupant.role ~= "moderator" then
+		return;
+	end
+
+	if not event.fields["muc#request_allow"] then
+		return;
+	end
+
+	if not affected_occupant then
+		return;
+	end
+
+	if affected_occupant.role == "visitor" then
+		event.room:set_role(actor, affected_occupant.nick, "participant", "Voice granted");
+	end
+end);
+
+
 return {
 	get = get_moderated;
 	set = set_moderated;
--- a/plugins/muc/muc.lib.lua	Fri Jun 01 08:47:07 2018 +0200
+++ b/plugins/muc/muc.lib.lua	Fri Oct 20 05:19:25 2017 +0200
@@ -778,6 +778,34 @@
 	return module:fire_event("muc-config-form", { room = self, actor = actor, form = form }) or form;
 end
 
+function room_mt:get_voice_form_layout()
+	local form = dataform.new({
+		{
+			name = "FORM_TYPE";
+			type = "hidden";
+			value = "http://jabber.org/protocol/muc#request";
+		},
+		{
+			name = "muc#jid";
+			type = "jid-single";
+		},
+		{
+			name = "muc#roomnick";
+			type = "text-single";
+		},
+		{
+			name = "muc#role";
+			type = "text-single";
+		},
+		{
+			name = "muc#request_allow";
+			type = "boolean";
+		}
+	});
+
+	return form;
+end
+
 function room_mt:process_form(origin, stanza)
 	local form = stanza.tags[1]:get_child("x", "jabber:x:data");
 	if form.attr.type == "cancel" then
@@ -1143,6 +1171,28 @@
 			origin.send(st.error_reply(stanza, "cancel", "bad-request"));
 			return true;
 		end
+
+		local form = stanza:get_child("x", "jabber:x:data");
+		if form and form.attr.type == "submit" then
+			local fields, errors, present = self:get_voice_form_layout():data(form);
+
+			if fields.FORM_TYPE == "http://jabber.org/protocol/muc#request" then
+				local occupant = self:get_occupant_by_real_jid(stanza.attr.from);
+				local event = {
+					room = self;
+					origin = origin;
+					stanza = stanza;
+					fields = fields;
+					occupant = occupant;
+				};
+				if occupant.role == "moderator" then
+					module:fire_event("muc-voice-response", event);
+				else
+					module:fire_event("muc-voice-request", event);
+				end
+				return true;
+			end
+		end
 	end
 end