# HG changeset patch # User nicoco # Date 1737105600 -3600 # Node ID bcad6baa4fc3fed54a272cf47a5632ff1225221c # Parent d80e398a2acced31435e8c42804c8f95ba8d0524 mod_muc_moderation: partial support for XEP-0425 v0.3.0 (no tombstones) diff -r d80e398a2acc -r bcad6baa4fc3 mod_muc_moderation/README.md --- a/mod_muc_moderation/README.md Fri Jan 17 11:02:02 2025 +0000 +++ b/mod_muc_moderation/README.md Fri Jan 17 10:20:00 2025 +0100 @@ -32,6 +32,11 @@ 0.12 Works ------- --------------- +## XEP version + +This module implements [XEP-0425] v0.2.1 (tombstones included) and v0.3.0 +(except for tombstones). + ## Clients - [Converse.js](https://conversejs.org/) diff -r d80e398a2acc -r bcad6baa4fc3 mod_muc_moderation/mod_muc_moderation.lua --- a/mod_muc_moderation/mod_muc_moderation.lua Fri Jan 17 11:02:02 2025 +0000 +++ b/mod_muc_moderation/mod_muc_moderation.lua Fri Jan 17 10:20:00 2025 +0100 @@ -27,12 +27,15 @@ -- Namespaces local xmlns_fasten = "urn:xmpp:fasten:0"; local xmlns_moderate = "urn:xmpp:message-moderate:0"; +local xmlns_moderate_1 = "urn:xmpp:message-moderate:1"; local xmlns_occupant_id = "urn:xmpp:occupant-id:0"; local xmlns_retract = "urn:xmpp:message-retract:0"; +local xmlns_retract_1 = "urn:xmpp:message-retract:1"; -- Discovering support module:hook("muc-disco#info", function (event) event.reply:tag("feature", { var = xmlns_moderate }):up(); + event.reply:tag("feature", { var = xmlns_moderate_1 }):up(); end); -- TODO error registry, requires Prosody 0.12+ @@ -107,8 +110,20 @@ announcement:add_direct_child(moderated_occupant_id); end + -- XEP 0425 v0.3.0 + announcement:reset(); + if retract then + announcement:tag("retract", { xmlns = xmlns_retract_1 }) + :tag("moderated", { xmlns = xmlns_moderate_1 }) + :tag("occupant-id", { xmlns = xmlns_occupant_id; id = room:get_occupant_id(actor_occupant) }); + if reason then + announcement:up():up():text_tag("reason", reason); + end + end + + local tombstone = nil; if muc_log_archive.set and retract then tombstone = st.message({ from = original.attr.from, type = "groupchat", id = original.attr.id }) @@ -189,6 +204,36 @@ return true; end); +module:hook("iq-set/bare/" .. xmlns_moderate_1 .. ":moderate", function (event) + local stanza, origin = event.stanza, event.origin; + + local actor = stanza.attr.from; + local room_jid = stanza.attr.to; + + local moderate_tag = stanza:get_child("moderate", xmlns_moderate_1) + local retract_tag = moderate_tag:get_child("retract", xmlns_retract_1) + + if not retract_tag then return end -- other kind of moderation? + + local reason = moderate_tag:get_child_text("reason"); + local stanza_id = moderate_tag.attr.id + + local ok, error_type, error_condition, error_text = moderate( + actor, + room_jid, + stanza_id, + retract_tag, + reason + ); + if not ok then + origin.send(st.error_reply(stanza, error_type, error_condition, error_text)); + return true; + end + + origin.send(st.reply(stanza)); + return true; +end); + module:hook("muc-message-is-historic", function (event) -- Ensure moderation messages are stored if event.stanza.attr.from == event.room.jid then