diff mod_muc_auto_role/mod_muc_auto_role.lua @ 6422:c41615686ce4

mod_muc_auto_role: Set default role for MUC occupants based on policies
author Matthew Wild <mwild1@gmail.com>
date Thu, 05 Mar 2026 14:35:43 +0000
parents
children fb7902f66c36
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_muc_auto_role/mod_muc_auto_role.lua	Thu Mar 05 14:35:43 2026 +0000
@@ -0,0 +1,48 @@
+local jid = require "prosody.util.jid";
+
+local xmlns_aff = "urn:xmpp:raa:0";
+
+local raa_servers = module:get_option_set("muc_auto_role_trusted_servers", {});
+local trust_threshold = module:get_option_integer("muc_auto_role_trust_threshold", 51, 0, 100);
+
+local untrusted_servers = module:get_option_set("muc_auto_role_untrusted_servers", {});
+
+local default_role = module:get_option_enum("muc_default_role", "visitor", "participant");
+
+-- TODO: This should be a config option in mod_muc
+module:hook("muc-get-default-role", function ()
+	return default_role;
+end, 5);
+
+module:hook("muc-occupant-pre-join", function (event)
+	local stanza = event.stanza;
+
+	local from_host = jid.host(stanza.attr.from);
+
+	if untrusted_servers:contains(from_host) then
+		event.occupant.role = "visitor";
+	end
+
+	if not raa_servers:contains(from_host) then
+		return;
+	end
+
+	local raa = stanza:get_child("info", xmlns_aff);
+	if not raa then
+		return;
+	end
+
+	local aff = raa.attr.affiliation;
+	local trust = tonumber(raa.attr.trust) or 50;
+
+	if aff == "member" or aff == "admin" or trust >= trust_threshold then
+		event.occupant.role = "participant";
+	else
+		event.occupant.role = "visitor";
+	end
+
+	module:log("debug", "Assigning <%s> role '%s' due to affiliation %s and trust score %d of <%s>",
+		event.occupant.nick, event.occupant.role, aff, trust, stanza.attr.from
+	);
+
+end);