Last active
June 26, 2019 20:35
-
-
Save legastero/219702bc69724f2e1f03469954547235 to your computer and use it in GitHub Desktop.
Experiment enabling presence broadcast controls in MUC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -r 5c9341a1b36f plugins/muc/mod_muc.lua | |
--- a/plugins/muc/mod_muc.lua Thu Jun 20 22:25:46 2019 +0200 | |
+++ b/plugins/muc/mod_muc.lua Wed Jun 26 13:34:55 2019 -0700 | |
@@ -86,6 +86,12 @@ | |
room_mt.get_registered_jid = register.get_registered_jid; | |
room_mt.handle_register_iq = register.handle_register_iq; | |
+local presence_broadcast = module:require "muc/presence_broadcast"; | |
+room_mt.get_presence_broadcast = presence_broadcast.get; | |
+room_mt.set_presence_broadcast = presence_broadcast.set; | |
+room_mt.get_valid_broadcast_roles = presence_broadcast.get_valid_broadcast_roles; | |
+ | |
+ | |
local jid_split = require "util.jid".split; | |
local jid_bare = require "util.jid".bare; | |
local st = require "util.stanza"; | |
@@ -263,6 +269,7 @@ | |
room:set_changesubject(module:get_option_boolean("muc_room_default_change_subject", room:get_changesubject())); | |
room:set_historylength(module:get_option_number("muc_room_default_history_length", room:get_historylength())); | |
room:set_language(lang or module:get_option_string("muc_room_default_language")); | |
+ room:set_presence_broadcast(module:get_option("muc_room_default_presence_broadcast"), room:get_presence_broadcast()) | |
end | |
function create_room(room_jid, config) | |
diff -r 5c9341a1b36f plugins/muc/muc.lib.lua | |
--- a/plugins/muc/muc.lib.lua Thu Jun 20 22:25:46 2019 +0200 | |
+++ b/plugins/muc/muc.lib.lua Wed Jun 26 13:34:55 2019 -0700 | |
@@ -217,13 +217,13 @@ | |
-- Broadcasts an occupant's presence to the whole room | |
-- Takes the x element that goes into the stanzas | |
-function room_mt:publicise_occupant_status(occupant, x, nick, actor, reason) | |
+function room_mt:publicise_occupant_status(occupant, x, nick, actor, reason, prev_role, force_unavailable) | |
local base_x = x.base or x; | |
-- Build real jid and (optionally) occupant jid template presences | |
local base_presence do | |
-- Try to use main jid's presence | |
local pr = occupant:get_presence(); | |
- if pr and (occupant.role ~= nil or pr.attr.type == "unavailable") then | |
+ if pr and (occupant.role ~= nil or pr.attr.type == "unavailable") and not force_unavailable then | |
base_presence = st.clone(pr); | |
else -- user is leaving but didn't send a leave presence. make one for them | |
base_presence = st.presence {from = occupant.nick; type = "unavailable";}; | |
@@ -279,6 +279,8 @@ | |
self_p = st.clone(base_presence):add_child(self_x); | |
end | |
+ local broadcast_roles = self:get_presence_broadcast(); | |
+ | |
-- General populance | |
for occupant_nick, n_occupant in self:each_occupant() do | |
if occupant_nick ~= occupant.nick then | |
@@ -290,7 +292,13 @@ | |
else | |
pr = get_anon_p(); | |
end | |
- self:route_to_occupant(n_occupant, pr); | |
+ if broadcast_roles[occupant.role or "none"] or force_unavailable then | |
+ self:route_to_occupant(n_occupant, pr); | |
+ elseif prev_role and broadcast_roles[prev_role] then | |
+ pr.attr.type = 'unavailable'; | |
+ self:route_to_occupant(n_occupant, pr); | |
+ end | |
+ | |
end | |
end | |
@@ -314,6 +322,7 @@ | |
local to_bare = jid_bare(to); | |
local is_anonymous = false; | |
local whois = self:get_whois(); | |
+ local broadcast_roles = self:get_presence_broadcast(); | |
if whois ~= "anyone" then | |
local affiliation = self:get_affiliation(to); | |
if affiliation ~= "admin" and affiliation ~= "owner" then | |
@@ -330,7 +339,9 @@ | |
local pres = st.clone(occupant:get_presence()); | |
pres.attr.to = to; | |
pres:add_child(x); | |
- self:route_stanza(pres); | |
+ if to_bare == occupant.bare_jid or broadcast_roles[occupant.role or "none"] then | |
+ self:route_stanza(pres); | |
+ end | |
end | |
end | |
end | |
@@ -1410,9 +1421,11 @@ | |
if not role then | |
x:tag("status", {code = "307"}):up(); | |
end | |
+ | |
+ local prev_role = occupant.role; | |
occupant.role = role; | |
self:save_occupant(occupant); | |
- self:publicise_occupant_status(occupant, x, nil, actor, reason); | |
+ self:publicise_occupant_status(occupant, x, nil, actor, reason, prev_role); | |
if role == nil then | |
module:fire_event("muc-occupant-left", {room = self; nick = occupant.nick; occupant = occupant;}); | |
end | |
diff -r 5c9341a1b36f plugins/muc/presence_broadcast.lib.lua | |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 | |
+++ b/plugins/muc/presence_broadcast.lib.lua Wed Jun 26 13:34:55 2019 -0700 | |
@@ -0,0 +1,87 @@ | |
+-- 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 valid_roles = { "visitor", "participant", "moderator" }; | |
+local default_broadcast = { | |
+ none = true; | |
+ visitor = true; | |
+ participant = true; | |
+ moderator = true; | |
+}; | |
+ | |
+local function get_presence_broadcast(room) | |
+ return room._data.presence_broadcast or default_broadcast; | |
+end | |
+ | |
+local function set_presence_broadcast(room, broadcast_roles) | |
+ broadcast_roles = broadcast_roles or default_broadcast; | |
+ | |
+ -- Ensure that unavailable presence is always sent when role changes to none | |
+ broadcast_roles.none = true; | |
+ | |
+ local changed = false; | |
+ local old_broadcast_roles = get_presence_broadcast(room); | |
+ for _, role in ipairs(valid_roles) do | |
+ if old_broadcast_roles[role] ~= broadcast_roles[role] then | |
+ changed = true; | |
+ end | |
+ end | |
+ | |
+ if not changed then return false; end | |
+ | |
+ room._data.presence_broadcast = broadcast_roles; | |
+ | |
+ for _, occupant in room:each_occupant() do | |
+ local x = st.stanza("x", {xmlns = "http://jabber.org/protocol/muc#user";}); | |
+ local role = occupant.role or "none"; | |
+ if broadcast_roles[role] and not old_broadcast_roles[role] then | |
+ -- Presence broadcast is now enabled, so announce existing user | |
+ room:publicise_occupant_status(occupant, x); | |
+ elseif old_broadcast_roles[role] and not broadcast_roles[role] then | |
+ -- Presence broadcast is now disabled, so mark existing user as unavailable | |
+ room:publicise_occupant_status(occupant, x, nil, nil, nil, nil, true); | |
+ end | |
+ end | |
+ | |
+ return true; | |
+end | |
+ | |
+module:hook("muc-config-form", function(event) | |
+ local values = {}; | |
+ for role, value in pairs(get_presence_broadcast(event.room)) do | |
+ if value then | |
+ values[#values + 1] = role; | |
+ end | |
+ end | |
+ | |
+ table.insert(event.form, { | |
+ name = "muc#roomconfig_presencebroadcast"; | |
+ type = "list-multi"; | |
+ label = "Roles for which Presence is Broadcasted"; | |
+ value = values; | |
+ options = valid_roles; | |
+ }); | |
+end, 90-3); | |
+ | |
+module:hook("muc-config-submitted/muc#roomconfig_presencebroadcast", function(event) | |
+ local broadcast_roles = {}; | |
+ for _, role in ipairs(event.value) do | |
+ broadcast_roles[role] = true; | |
+ end | |
+ if set_presence_broadcast(event.room, broadcast_roles) then | |
+ event.status_codes["104"] = true; | |
+ end | |
+end); | |
+ | |
+return { | |
+ get = get_presence_broadcast; | |
+ set = set_presence_broadcast; | |
+}; |
Ugh, never mind. Messed up generating new patch. Will get this cleaned up. 😭
Ok, there we go. All cleaned up.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
That should be updated to apply to latest 0.11 rev now (5c9341a1b36f)