|
@@ -0,0 +1,65 @@
|
|
1
|
+-- MUC Max Occupants
|
|
2
|
+-- Configuring muc_max_occupants will set a limit of the maximum number
|
|
3
|
+-- of participants that will be able to join in a room.
|
|
4
|
+-- Participants in muc_access_whitelist will not be counted for the
|
|
5
|
+-- max occupants value (values are jids like recorder@jitsi.meeet.example.com).
|
|
6
|
+-- This module is configured under the muc component that is used for jitsi-meet
|
|
7
|
+local split_jid = require "util.jid".split;
|
|
8
|
+local st = require "util.stanza";
|
|
9
|
+local it = require "util.iterators";
|
|
10
|
+
|
|
11
|
+local whitelist = module:get_option_set("muc_access_whitelist");
|
|
12
|
+local MAX_OCCUPANTS = module:get_option_number("muc_max_occupants", -1);
|
|
13
|
+
|
|
14
|
+local function count_keys(t)
|
|
15
|
+ return it.count(it.keys(t));
|
|
16
|
+end
|
|
17
|
+
|
|
18
|
+local function check_for_max_occupants(event)
|
|
19
|
+ local room, origin, stanza = event.room, event.origin, event.stanza;
|
|
20
|
+
|
|
21
|
+ local actor = stanza.attr.from;
|
|
22
|
+ local user, domain, res = split_jid(stanza.attr.from);
|
|
23
|
+
|
|
24
|
+ --no user object means no way to check for max occupants
|
|
25
|
+ if user == nil then
|
|
26
|
+ return
|
|
27
|
+ end
|
|
28
|
+ -- If we're a whitelisted user joining the room, don't bother checking the max
|
|
29
|
+ -- occupants.
|
|
30
|
+ if whitelist and whitelist:contains(domain) or whitelist:contains(user..'@'..domain) then
|
|
31
|
+ return;
|
|
32
|
+ end
|
|
33
|
+
|
|
34
|
+ if room and not room._jid_nick[stanza.attr.from] then
|
|
35
|
+ local count = count_keys(room._occupants);
|
|
36
|
+ local slots = MAX_OCCUPANTS;
|
|
37
|
+
|
|
38
|
+ -- If there is no whitelist, just check the count.
|
|
39
|
+ if not whitelist and count >= MAX_OCCUPANTS then
|
|
40
|
+ module:log("info", "Attempt to enter a maxed out MUC");
|
|
41
|
+ origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
|
|
42
|
+ return true;
|
|
43
|
+ end
|
|
44
|
+
|
|
45
|
+ -- TODO: Are Prosody hooks atomic, or is this a race condition?
|
|
46
|
+ -- For each person in the room that's not on the whitelist, subtract one
|
|
47
|
+ -- from the count.
|
|
48
|
+ for _, occupant in room:each_occupant() do
|
|
49
|
+ if not whitelist:contains(domain) and not whitelist:contains(user..'@'..domain) then
|
|
50
|
+ slots = slots - 1
|
|
51
|
+ end
|
|
52
|
+ end
|
|
53
|
+
|
|
54
|
+ -- If the room is full (<0 slots left), error out.
|
|
55
|
+ if slots <= 0 then
|
|
56
|
+ module:log("info", "Attempt to enter a maxed out MUC");
|
|
57
|
+ origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
|
|
58
|
+ return true;
|
|
59
|
+ end
|
|
60
|
+ end
|
|
61
|
+end
|
|
62
|
+
|
|
63
|
+if MAX_OCCUPANTS > 0 then
|
|
64
|
+ module:hook("muc-occupant-pre-join", check_for_max_occupants, 10);
|
|
65
|
+end
|