Comparison

plugins/muc/muc.lib.lua @ 10353:7b602e13c3b6

MUC: Add controls for whose presence is broadcast (closes #1335) Committed by Zash
author Lance Stout <lancestout@gmail.com>
date Sun, 20 Oct 2019 21:58:16 +0200
parent 10294:b61a7173f838
child 10361:6e051bfca12d
comparison
equal deleted inserted replaced
10352:dc1e6c2fb50a 10353:7b602e13c3b6
216 end 216 end
217 end 217 end
218 218
219 -- Broadcasts an occupant's presence to the whole room 219 -- Broadcasts an occupant's presence to the whole room
220 -- Takes the x element that goes into the stanzas 220 -- Takes the x element that goes into the stanzas
221 function room_mt:publicise_occupant_status(occupant, x, nick, actor, reason) 221 function room_mt:publicise_occupant_status(occupant, x, nick, actor, reason, prev_role, force_unavailable)
222 local base_x = x.base or x; 222 local base_x = x.base or x;
223 -- Build real jid and (optionally) occupant jid template presences 223 -- Build real jid and (optionally) occupant jid template presences
224 local base_presence do 224 local base_presence do
225 -- Try to use main jid's presence 225 -- Try to use main jid's presence
226 local pr = occupant:get_presence(); 226 local pr = occupant:get_presence();
227 if pr and (occupant.role ~= nil or pr.attr.type == "unavailable") then 227 if pr and (occupant.role ~= nil or pr.attr.type == "unavailable") and not force_unavailable then
228 base_presence = st.clone(pr); 228 base_presence = st.clone(pr);
229 else -- user is leaving but didn't send a leave presence. make one for them 229 else -- user is leaving but didn't send a leave presence. make one for them
230 base_presence = st.presence {from = occupant.nick; type = "unavailable";}; 230 base_presence = st.presence {from = occupant.nick; type = "unavailable";};
231 end 231 end
232 end 232 end
277 -- But not allowed to see actor's 277 -- But not allowed to see actor's
278 self_x = st.clone(x.self or base_x); 278 self_x = st.clone(x.self or base_x);
279 self:build_item_list(occupant, self_x, false, nick, actor_nick, nil, reason); 279 self:build_item_list(occupant, self_x, false, nick, actor_nick, nil, reason);
280 self_p = st.clone(base_presence):add_child(self_x); 280 self_p = st.clone(base_presence):add_child(self_x);
281 end 281 end
282
283 local broadcast_roles = self:get_presence_broadcast();
282 284
283 -- General populace 285 -- General populace
284 for occupant_nick, n_occupant in self:each_occupant() do 286 for occupant_nick, n_occupant in self:each_occupant() do
285 if occupant_nick ~= occupant.nick then 287 if occupant_nick ~= occupant.nick then
286 local pr; 288 local pr;
289 elseif occupant.bare_jid == n_occupant.bare_jid then 291 elseif occupant.bare_jid == n_occupant.bare_jid then
290 pr = self_p; 292 pr = self_p;
291 else 293 else
292 pr = get_anon_p(); 294 pr = get_anon_p();
293 end 295 end
294 self:route_to_occupant(n_occupant, pr); 296 if broadcast_roles[occupant.role or "none"] or force_unavailable then
297 self:route_to_occupant(n_occupant, pr);
298 elseif prev_role and broadcast_roles[prev_role] then
299 pr.attr.type = 'unavailable';
300 self:route_to_occupant(n_occupant, pr);
301 end
302
295 end 303 end
296 end 304 end
297 305
298 -- Presences for occupant itself 306 -- Presences for occupant itself
299 self_x:tag("status", {code = "110";}):up(); 307 self_x:tag("status", {code = "110";}):up();
313 321
314 function room_mt:send_occupant_list(to, filter) 322 function room_mt:send_occupant_list(to, filter)
315 local to_bare = jid_bare(to); 323 local to_bare = jid_bare(to);
316 local is_anonymous = false; 324 local is_anonymous = false;
317 local whois = self:get_whois(); 325 local whois = self:get_whois();
326 local broadcast_roles = self:get_presence_broadcast();
318 if whois ~= "anyone" then 327 if whois ~= "anyone" then
319 local affiliation = self:get_affiliation(to); 328 local affiliation = self:get_affiliation(to);
320 if affiliation ~= "admin" and affiliation ~= "owner" then 329 if affiliation ~= "admin" and affiliation ~= "owner" then
321 local occupant = self:get_occupant_by_real_jid(to); 330 local occupant = self:get_occupant_by_real_jid(to);
322 if not (occupant and can_see_real_jids(whois, occupant)) then 331 if not (occupant and can_see_real_jids(whois, occupant)) then
329 local x = st.stanza("x", {xmlns='http://jabber.org/protocol/muc#user'}); 338 local x = st.stanza("x", {xmlns='http://jabber.org/protocol/muc#user'});
330 self:build_item_list(occupant, x, is_anonymous and to_bare ~= occupant.bare_jid); -- can always see your own jids 339 self:build_item_list(occupant, x, is_anonymous and to_bare ~= occupant.bare_jid); -- can always see your own jids
331 local pres = st.clone(occupant:get_presence()); 340 local pres = st.clone(occupant:get_presence());
332 pres.attr.to = to; 341 pres.attr.to = to;
333 pres:add_child(x); 342 pres:add_child(x);
334 self:route_stanza(pres); 343 if to_bare == occupant.bare_jid or broadcast_roles[occupant.role or "none"] then
344 self:route_stanza(pres);
345 end
335 end 346 end
336 end 347 end
337 end 348 end
338 349
339 function room_mt:get_disco_info(stanza) 350 function room_mt:get_disco_info(stanza)
1440 1451
1441 local x = st.stanza("x", {xmlns = "http://jabber.org/protocol/muc#user"}); 1452 local x = st.stanza("x", {xmlns = "http://jabber.org/protocol/muc#user"});
1442 if not role then 1453 if not role then
1443 x:tag("status", {code = "307"}):up(); 1454 x:tag("status", {code = "307"}):up();
1444 end 1455 end
1456
1457 local prev_role = occupant.role;
1445 occupant.role = role; 1458 occupant.role = role;
1446 self:save_occupant(occupant); 1459 self:save_occupant(occupant);
1447 self:publicise_occupant_status(occupant, x, nil, actor, reason); 1460 self:publicise_occupant_status(occupant, x, nil, actor, reason, prev_role);
1448 if role == nil then 1461 if role == nil then
1449 module:fire_event("muc-occupant-left", { 1462 module:fire_event("muc-occupant-left", {
1450 room = self; 1463 room = self;
1451 nick = occupant.nick; 1464 nick = occupant.nick;
1452 occupant = occupant; 1465 occupant = occupant;