aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/muc/request.lib.lua
blob: 4e95fdc3f333b3219214616a26d7c4ac8b23fb87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
-- Copyright (C) 2014 Daurnimator
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--

local st = require "util.stanza";
local jid_resource = require "util.jid".resource;

module:hook("muc-disco#info", function(event)
	event.reply:tag("feature", {var = "http://jabber.org/protocol/muc#request"}):up();
end);

local voice_request_form = require "util.dataforms".new({
	title = "Voice Request";
	{
		name = "FORM_TYPE";
		type = "hidden";
		value = "http://jabber.org/protocol/muc#request";
	},
	{
		name = "muc#jid";
		type = "jid-single";
		label = "User ID";
		desc = "The user's JID (address)";
	},
	{
		name = "muc#roomnick";
		type = "text-single";
		label = "Room nickname";
		desc = "The user's nickname within the room";
	},
	{
		name = "muc#role";
		type = "list-single";
		label = "Requested role";
		value = "participant";
		options = {
			"none",
			"visitor",
			"participant",
			"moderator",
		};
	},
	{
		name = "muc#request_allow";
		type = "boolean";
		label = "Grant voice to this person?";
		desc = "Specify whether this person is able to speak in a moderated room";
		value = false;
	}
});

local function handle_request(room, origin, stanza, form)
	local occupant = room:get_occupant_by_real_jid(stanza.attr.from);
	local fields = voice_request_form:data(form);
	local event = {
		room = room;
		origin = origin;
		stanza = stanza;
		fields = fields;
		occupant = occupant;
	};
	if occupant.role == "moderator" then
		module:log("debug", "%s responded to a voice request in %s", jid_resource(occupant.nick), room.jid);
		module:fire_event("muc-voice-response", event);
	else
		module:log("debug", "%s requested voice in %s", jid_resource(occupant.nick), room.jid);
		module:fire_event("muc-voice-request", event);
	end
end

module:hook("muc-voice-request", function(event)
	if event.occupant.role == "visitor" then
		local nick = jid_resource(event.occupant.nick);
		local formdata = {
			["muc#jid"] = event.stanza.attr.from;
			["muc#roomnick"] = nick;
		};

		local message = st.message({ type = "normal"; from = event.room.jid })
			:add_child(voice_request_form:form(formdata));

		event.room:broadcast(message, function (_, 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"]);
	local occupant = event.occupant;

	if occupant.role ~= "moderator" then
		module:log("debug", "%s tried to grant voice but wasn't a moderator", jid_resource(occupant.nick));
		return;
	end

	if not event.fields["muc#request_allow"] then
		module:log("debug", "%s did not grant voice", jid_resource(occupant.nick));
		return;
	end

	if not affected_occupant then
		module:log("debug", "%s tried to grant voice to unknown occupant %s",
			jid_resource(occupant.nick), event.fields["muc#jid"]);
		return;
	end

	if affected_occupant.role ~= "visitor" then
		module:log("debug", "%s tried to grant voice to %s but they already have it",
			jid_resource(occupant.nick), jid_resource(occupant.jid));
		return;
	end

	module:log("debug", "%s granted voice to %s", jid_resource(event.occupant.nick), jid_resource(occupant.jid));
	local ok, errtype, err = event.room:set_role(actor, affected_occupant.nick, "participant", "Voice granted");

	if not ok then
		module:log("debug", "Error granting voice: %s", err or errtype);
		event.origin.send(st.error_reply(event.stanza, errtype, err));
	end
end);


return {
	handle_request = handle_request;
};