Software /
code /
prosody
Changeset
13657:404d3644ac4a
mod_muc: Integrate support for vcards/avatars on MUC rooms
This was previously served by a community module (mod_vcard_muc).
It can be disabled by setting `vcard_muc = false` in the config.
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Thu, 06 Feb 2025 17:08:46 +0000 |
parents | 13656:4298e6565fec |
children | 13658:33806569d7c5 |
files | core/features.lua plugins/muc/mod_muc.lua plugins/muc/vcard.lib.lua |
diffstat | 3 files changed, 87 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/core/features.lua Thu Feb 06 17:03:03 2025 +0000 +++ b/core/features.lua Thu Feb 06 17:08:46 2025 +0000 @@ -10,6 +10,8 @@ "mod_flags"; -- mod_cloud_notify bundled "mod_cloud_notify"; + -- mod_muc has built-in vcard support + "muc_vcard"; -- Roles, module.may and per-session authz "permissions"; -- prosody.* namespace
--- a/plugins/muc/mod_muc.lua Thu Feb 06 17:03:03 2025 +0000 +++ b/plugins/muc/mod_muc.lua Thu Feb 06 17:08:46 2025 +0000 @@ -116,6 +116,10 @@ module:require "muc/hats"; module:require "muc/lock"; +if module:get_option_boolean("muc_vcard", true) ~= false then + module:require "muc/vcard"; +end + module:default_permissions("prosody:admin", { ":automatic-ownership"; ":create-room";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/muc/vcard.lib.lua Thu Feb 06 17:08:46 2025 +0000 @@ -0,0 +1,81 @@ +local mod_vcard = module:depends("vcard"); + +local jid = require "prosody.util.jid"; +local st = require "prosody.util.stanza"; + +-- This must be the same event that mod_vcard hooks +local vcard_event = "iq/bare/vcard-temp:vCard"; +local advertise_hashes = module:get_option("muc_avatar_advertise_hashes"); + +--luacheck: ignore 113/get_room_from_jid + +local function get_avatar_hash(room) + if room.avatar_hash then return room.avatar_hash; end + + local room_node = jid.split(room.jid); + local hash = mod_vcard.get_avatar_hash(room_node); + room.avatar_hash = hash; + + return hash; +end + +local function send_avatar_hash(room, to) + local hash = get_avatar_hash(room); + + local presence_vcard = st.presence({to = to, from = room.jid}) + :tag("x", { xmlns = "vcard-temp:x:update" }) + :tag("photo"):text(hash):up(); + + if to == nil then + if not advertise_hashes or advertise_hashes == "presence" then + room:broadcast_message(presence_vcard); + end + if not advertise_hashes or advertise_hashes == "message" then + room:broadcast_message(st.message({ from = room.jid, type = "groupchat" }) + :tag("x", { xmlns = "http://jabber.org/protocol/muc#user" }) + :tag("status", { code = "104" })); + end + + else + module:send(presence_vcard); + end +end + +module:hook(vcard_event, function (event) + local stanza = event.stanza; + local to = stanza.attr.to; + + if stanza.attr.type ~= "set" then + return; + end + + local room = get_room_from_jid(to); + if not room then + return; + end + + local sender_affiliation = room:get_affiliation(stanza.attr.from); + if sender_affiliation == "owner" then + event.allow_vcard_modification = true; + end +end, 10); + +if advertise_hashes ~= "none" then + module:hook("muc-occupant-joined", function (event) + send_avatar_hash(event.room, event.stanza.attr.from); + end); + module:hook("vcard-updated", function (event) + local room = get_room_from_jid(event.stanza.attr.to); + send_avatar_hash(room, nil); + end); +end + +module:hook("muc-disco#info", function (event) + event.reply:tag("feature", { var = "vcard-temp" }):up(); + + table.insert(event.form, { + name = "muc#roominfo_avatarhash", + type = "text-multi", + }); + event.formdata["muc#roominfo_avatarhash"] = get_avatar_hash(event.room); +end);