Files
Stefan-Sanger 1affb3acc3 fix: use Prosody 13 get_room_from_jid API in broadcast/FCM MUC fanout
mod_vnc_broadcast and mod_vnc_fcm accessed the deprecated
prosody.hosts[host].modules.muc.rooms[to] table, removed in Prosody 13,
triggering 'Attempt to read a non-existent global rooms' warnings and
silently breaking MUC affiliation fan-out for broadcasts and push.

Replace with a version-safe get_room_from_jid() helper (rawget fallback
to .rooms for older Prosody), matching the pattern already in
mod_vcard_muc. Guard _affiliations access behind a nil room check.

Part-of: <http://gitlab.vnc.biz/uxf/vnctalk-prosody/-/merge_requests/7>
2026-07-16 08:00:57 +02:00

116 lines
4.1 KiB
Lua

local is_admin = require "core.usermanager".is_admin;
local allowed_senders = module:get_option_set("broadcast_senders", {});
local from_address = module:get_option_string("broadcast_from");
local st = require "util.stanza";
local jid_bare = require "util.jid".bare;
local jid = require "util.jid";
local id = require "util.id"
local mod_muc = module:depends"muc";
local get_room_from_jid = rawget(mod_muc, "get_room_from_jid") or
function (jid)
local rooms = rawget(mod_muc, "rooms");
return rooms and rooms[jid];
end
local roster_manager = require("core.rostermanager");
function send_bc_message(from, to, bcid, body, title, origtarget, vnctalk_avatarup)
local msgid = id.long();
local message = "";
if (vnctalk_avatarup) then
message = st.message({ from = from, to = to, id = msgid,
type = "normal" }):body(body):up():tag("vncTalkBroadcast", { xmlns = "xmpp:vnctalk", id=bcid, title=title, origtarget = origtarget, avatarup = "true"}):up();
else
message = st.message({ from = from, to = to, id = msgid,
type = "normal" }):body(body):up():tag("vncTalkBroadcast", { xmlns = "xmpp:vnctalk", id=bcid, title=title, origtarget = origtarget}):up();
-- module:log("info", "built bcmessage: %s", tostring(message));
end
module:send(message);
end
function send_message(event)
local stanza = event.stanza;
local from = jid.bare(stanza.attr.from);
local fnode, fhost = jid.split(from);
-- module:log("info", "event.stanza is %s", stanza:get_child_text("body"));
local body = stanza:get_child_text("body");
local vnctalk_broadcast = stanza:get_child("vncTalkBroadcast", "xmpp:vnctalk");
local vnctalk_avatarup = stanza:get_child("vnctalkAvatarUpdate", "xmpp:vnctalk" ) or false;
-- module:log("info", "vnctalkavatarup %s", vnctalk_avatarup);
local vnctalk_broadcast_childid = vnctalk_broadcast.attr.id;
if vnctalk_broadcast_childid ~= nil then
module:log("info", "not casting - is already casted message %s", stanza.attr.body);
else
new_id = stanza.attr.id;
local origtarget = stanza.attr.origtarget;
-- module:log("info", "casting broadcast orig target: %s", stanza.attr.origtarget);
local bctitle = vnctalk_broadcast.attr.title;
local bc_to = stanza:get_child("vncTalkBroadcast", "xmpp:vnctalk"):childtags("to", "xmpp:vnctalk")[1];
local t_receipients = {};
for ato in vnctalk_broadcast:childtags("to") do
local to = ato:get_text();
-- module:log("info", "found to: %s", to);
if string.find(to, "@conference") then
-- module:log("info","add affiliates of %s", to);
local muc, host = jid.split(to);
-- module:log("info", "got muc %s from host %s", muc, host);
if prosody.hosts[host] then
local room = get_room_from_jid(to);
if room then
local affs = room._affiliations;
for _aff, role in pairs(affs) do
-- module:log("info", "got muc _aff %s from muc %s", _aff, to);
if from ~= _aff then
t_receipients[_aff] = true;
end
end
end
end
else
t_receipients[to] = true;
end
end
local target_groups = {};
for rgroup in vnctalk_broadcast:childtags("roster") do
local rgrp = rgroup:get_text();
-- module:log("info", "found targeted roster group: %s", rgrp);
target_groups[rgrp] = true;
end
local roster = roster_manager.load_roster(fnode, fhost);
for contact, croster in pairs(roster) do
local cgroups = croster.groups;
if cgroups ~= nil then
for a1, a2 in pairs (cgroups) do
if target_groups[a1] then
-- module:log("info","adding roster contact from group: %s ==> %s", a1, contact);
if from ~= contact then
t_receipients[contact] = true;
end
end
end
end
end
for receipient, _x in pairs(t_receipients) do
module:log("info","sending broadcast message from: %s to: %s with childid %s and body: %s and avatarup: %s", from, receipient, new_id, body, vnctalk_avatarup);
send_bc_message(from, receipient, new_id, body, bctitle, origtarget, vnctalk_avatarup);
end
-- prevent further handling (i.e. storing offline)
-- return 1
end
end
--- execute first
module:hook("message/bare", send_message, 5);