diff options
author | Kim Alvefur <zash@zash.se> | 2022-01-09 18:42:22 +0100 |
---|---|---|
committer | Kim Alvefur <zash@zash.se> | 2022-01-09 18:42:22 +0100 |
commit | 8a53094a7daf29d5dec902353c8ebf7cd7772bfe (patch) | |
tree | 9fa9f518b4a44ce1c0007620317f2e2fb857368b | |
parent | d8c9ea741bfd41d5876e564435062b5018971855 (diff) | |
download | prosody-8a53094a7daf29d5dec902353c8ebf7cd7772bfe.tar.gz prosody-8a53094a7daf29d5dec902353c8ebf7cd7772bfe.zip |
mod_bookmarks: Broadcast notifications per XEP-0048 and XEP-0411
For compatibility with clients relying on the notifications
-rw-r--r-- | doc/doap.xml | 9 | ||||
-rw-r--r-- | plugins/mod_bookmarks.lua | 34 |
2 files changed, 43 insertions, 0 deletions
diff --git a/doc/doap.xml b/doc/doap.xml index c03d62ee..0c6eb536 100644 --- a/doc/doap.xml +++ b/doc/doap.xml @@ -803,6 +803,15 @@ </implements> <implements> <xmpp:SupportedXep> + <xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0411.html"/> + <xmpp:version>1.1.0</xmpp:version> + <xmpp:since>0.12.0</xmpp:since> + <xmpp:status>complete</xmpp:status> + <xmpp:note>mod_bookmarks</xmpp:note> + </xmpp:SupportedXep> + </implements> + <implements> + <xmpp:SupportedXep> <xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0421.html"/> <xmpp:version>0.1.0</xmpp:version> <xmpp:since>0.12.0</xmpp:since> diff --git a/plugins/mod_bookmarks.lua b/plugins/mod_bookmarks.lua index ef376104..7797be7d 100644 --- a/plugins/mod_bookmarks.lua +++ b/plugins/mod_bookmarks.lua @@ -12,6 +12,7 @@ local private_storage = module:open_store("private", "map"); local namespace = "urn:xmpp:bookmarks:1"; local namespace_private = "jabber:iq:private"; local namespace_legacy = "storage:bookmarks"; +local xmlns_pubsub = "http://jabber.org/protocol/pubsub"; local default_options = { ["persist_items"] = true; @@ -24,12 +25,16 @@ module:hook("account-disco-info", function (event) -- This Time it’s Serious! event.reply:tag("feature", { var = namespace.."#compat" }):up(); event.reply:tag("feature", { var = namespace.."#compat-pep" }):up(); + + -- COMPAT XEP-0411 + event.reply:tag("feature", { var = "urn:xmpp:bookmarks-conversion:0" }):up(); end); -- This must be declared on the domain JID, not the account JID. Note that -- this isn’t defined in the XEP. module:add_feature(namespace_private); + local function generate_legacy_storage(items) local storage = st.stanza("storage", { xmlns = namespace_legacy }); for _, item_id in ipairs(items) do @@ -417,10 +422,39 @@ end, 1); if module:get_option_boolean("upgrade_legacy_bookmarks", true) then module:hook("resource-bind", migrate_legacy_bookmarks); end +-- COMPAT XEP-0411 Broadcast as per XEP-0048 + PEP +local function legacy_broadcast(event) + local service = event.service; + local ok, bookmarks = service:get_items(namespace, event.actor); + if bookmarks == "item-not-found" then ok, bookmarks = true, {} end + if not ok then return end + local legacy_bookmarks_item = st.stanza("item", { xmlns = xmlns_pubsub; id = "current" }) + :add_child(generate_legacy_storage(bookmarks)); + -- FIXME This broadcasts to any and all contacts who sent +notify because the node does not exist, so defaults apply. + service:broadcast("items", namespace_legacy, { --[[ no subscribers ]] }, legacy_bookmarks_item, event.actor); +end +local function broadcast_legacy_removal(event) + if event.node ~= namespace then return end + return legacy_broadcast(event); +end +module:hook("presence/initial", function (event) + -- Broadcasts to all clients with legacy+notify, not just the one coming online. + -- Upgrade to XEP-0402 to avoid it + local service = mod_pep.get_pep_service(event.origin.username); + legacy_broadcast({ service = service, actor = event.origin.full_jid }); +end); module:handle_items("pep-service", function (event) local service = event.item.service; module:hook_object_event(service.events, "node-created", on_node_created); + module:hook_object_event(service.events, "item-published/" .. namespace, legacy_broadcast); + module:hook_object_event(service.events, "item-retracted", broadcast_legacy_removal); + module:hook_object_event(service.events, "node-purged", broadcast_legacy_removal); + module:hook_object_event(service.events, "node-deleted", broadcast_legacy_removal); end, function (event) local service = event.item.service; module:unhook_object_event(service.events, "node-created", on_node_created); + module:unhook_object_event(service.events, "item-published/" .. namespace, legacy_broadcast); + module:unhook_object_event(service.events, "item-retracted", broadcast_legacy_removal); + module:unhook_object_event(service.events, "node-purged", broadcast_legacy_removal); + module:unhook_object_event(service.events, "node-deleted", broadcast_legacy_removal); end, true); |