|
@@ -1,8 +1,12 @@
|
|
1
|
+local filters = require 'util.filters';
|
1
|
2
|
local jid = require "util.jid";
|
|
3
|
+local jid_bare = require "util.jid".bare;
|
2
|
4
|
local um_is_admin = require "core.usermanager".is_admin;
|
3
|
5
|
local util = module:require "util";
|
4
|
6
|
local is_healthcheck_room = util.is_healthcheck_room;
|
5
|
7
|
local extract_subdomain = util.extract_subdomain;
|
|
8
|
+local presence_check_status = util.presence_check_status;
|
|
9
|
+local MUC_NS = 'http://jabber.org/protocol/muc';
|
6
|
10
|
|
7
|
11
|
local moderated_subdomains;
|
8
|
12
|
local moderated_rooms;
|
|
@@ -17,6 +21,11 @@ local function is_admin(jid)
|
17
|
21
|
return um_is_admin(jid, module.host);
|
18
|
22
|
end
|
19
|
23
|
|
|
24
|
+-- List of the bare_jids of all occupants that are currently joining (went through pre-join) and will be promoted
|
|
25
|
+-- as moderators. As pre-join (where added) and joined event (where removed) happen one after another this list should
|
|
26
|
+-- have length of 1
|
|
27
|
+local joining_moderator_participants = {};
|
|
28
|
+
|
20
|
29
|
-- Checks whether the jid is moderated, the room name is in moderated_rooms
|
21
|
30
|
-- or if the subdomain is in the moderated_subdomains
|
22
|
31
|
-- @return returns on of the:
|
|
@@ -43,10 +52,10 @@ local function is_moderated(room_jid)
|
43
|
52
|
return false;
|
44
|
53
|
end
|
45
|
54
|
|
46
|
|
-module:hook("muc-occupant-joined", function (event)
|
|
55
|
+module:hook("muc-occupant-pre-join", function (event)
|
47
|
56
|
local room, occupant = event.room, event.occupant;
|
48
|
57
|
|
49
|
|
- if is_healthcheck_room(room.jid) or is_admin(occupant.jid) then
|
|
58
|
+ if is_healthcheck_room(room.jid) or is_admin(occupant.bare_jid) then
|
50
|
59
|
return;
|
51
|
60
|
end
|
52
|
61
|
|
|
@@ -71,7 +80,20 @@ module:hook("muc-occupant-joined", function (event)
|
71
|
80
|
end
|
72
|
81
|
end
|
73
|
82
|
|
74
|
|
- room:set_affiliation(true, occupant.bare_jid, "owner");
|
|
83
|
+ -- mark this participant that it will be promoted and is currently joining
|
|
84
|
+ joining_moderator_participants[occupant.bare_jid] = true;
|
|
85
|
+end, 2);
|
|
86
|
+
|
|
87
|
+module:hook("muc-occupant-joined", function (event)
|
|
88
|
+ local room, occupant = event.room, event.occupant;
|
|
89
|
+
|
|
90
|
+ local promote_to_moderator = joining_moderator_participants[occupant.bare_jid];
|
|
91
|
+ -- clear it
|
|
92
|
+ joining_moderator_participants[occupant.bare_jid] = nil;
|
|
93
|
+
|
|
94
|
+ if promote_to_moderator ~= nil then
|
|
95
|
+ room:set_affiliation(true, occupant.bare_jid, "owner");
|
|
96
|
+ end
|
75
|
97
|
end, 2);
|
76
|
98
|
|
77
|
99
|
module:hook("muc-occupant-left", function (event)
|
|
@@ -85,3 +107,29 @@ module:hook("muc-occupant-left", function (event)
|
85
|
107
|
end, 2);
|
86
|
108
|
|
87
|
109
|
module:hook_global('config-reloaded', load_config);
|
|
110
|
+
|
|
111
|
+-- Filters self-presences to a jid that exist in joining_participants array
|
|
112
|
+-- We want to filter those presences where we send first `participant` and just after it `moderator`
|
|
113
|
+function filter_stanza(stanza)
|
|
114
|
+ if not stanza.attr or not stanza.attr.to or stanza.name ~= "presence" then
|
|
115
|
+ return stanza;
|
|
116
|
+ end
|
|
117
|
+
|
|
118
|
+ -- Allow self-presence (code=110)
|
|
119
|
+ local bare_to = jid_bare(stanza.attr.to);
|
|
120
|
+
|
|
121
|
+ if joining_moderator_participants[bare_to] then
|
|
122
|
+ if presence_check_status(stanza:get_child('x', MUC_NS..'#user'), '110') then
|
|
123
|
+ return nil;
|
|
124
|
+ end
|
|
125
|
+ end
|
|
126
|
+
|
|
127
|
+ return stanza;
|
|
128
|
+end
|
|
129
|
+function filter_session(session)
|
|
130
|
+ -- domain mapper is filtering on default priority 0, and we need it after that
|
|
131
|
+ filters.add_filter(session, 'stanzas/out', filter_stanza, -1);
|
|
132
|
+end
|
|
133
|
+
|
|
134
|
+-- enable filtering presences
|
|
135
|
+filters.add_filter_hook(filter_session);
|