Comparison

plugins/mod_bookmarks.lua @ 12170:750abaf99baf

mod_bookmarks: Broadcast notifications per XEP-0048 and XEP-0411 For compatibility with clients relying on the notifications
author Kim Alvefur <zash@zash.se>
date Sun, 09 Jan 2022 18:42:22 +0100
parent 12156:17cffaa78f48
child 12171:b2923a3b4e02
comparison
equal deleted inserted replaced
12169:866d06644956 12170:750abaf99baf
10 local private_storage = module:open_store("private", "map"); 10 local private_storage = module:open_store("private", "map");
11 11
12 local namespace = "urn:xmpp:bookmarks:1"; 12 local namespace = "urn:xmpp:bookmarks:1";
13 local namespace_private = "jabber:iq:private"; 13 local namespace_private = "jabber:iq:private";
14 local namespace_legacy = "storage:bookmarks"; 14 local namespace_legacy = "storage:bookmarks";
15 local xmlns_pubsub = "http://jabber.org/protocol/pubsub";
15 16
16 local default_options = { 17 local default_options = {
17 ["persist_items"] = true; 18 ["persist_items"] = true;
18 ["max_items"] = "max"; 19 ["max_items"] = "max";
19 ["send_last_published_item"] = "never"; 20 ["send_last_published_item"] = "never";
22 23
23 module:hook("account-disco-info", function (event) 24 module:hook("account-disco-info", function (event)
24 -- This Time it’s Serious! 25 -- This Time it’s Serious!
25 event.reply:tag("feature", { var = namespace.."#compat" }):up(); 26 event.reply:tag("feature", { var = namespace.."#compat" }):up();
26 event.reply:tag("feature", { var = namespace.."#compat-pep" }):up(); 27 event.reply:tag("feature", { var = namespace.."#compat-pep" }):up();
28
29 -- COMPAT XEP-0411
30 event.reply:tag("feature", { var = "urn:xmpp:bookmarks-conversion:0" }):up();
27 end); 31 end);
28 32
29 -- This must be declared on the domain JID, not the account JID. Note that 33 -- This must be declared on the domain JID, not the account JID. Note that
30 -- this isn’t defined in the XEP. 34 -- this isn’t defined in the XEP.
31 module:add_feature(namespace_private); 35 module:add_feature(namespace_private);
36
32 37
33 local function generate_legacy_storage(items) 38 local function generate_legacy_storage(items)
34 local storage = st.stanza("storage", { xmlns = namespace_legacy }); 39 local storage = st.stanza("storage", { xmlns = namespace_legacy });
35 for _, item_id in ipairs(items) do 40 for _, item_id in ipairs(items) do
36 local item = items[item_id]; 41 local item = items[item_id];
415 end 420 end
416 end, 1); 421 end, 1);
417 if module:get_option_boolean("upgrade_legacy_bookmarks", true) then 422 if module:get_option_boolean("upgrade_legacy_bookmarks", true) then
418 module:hook("resource-bind", migrate_legacy_bookmarks); 423 module:hook("resource-bind", migrate_legacy_bookmarks);
419 end 424 end
425 -- COMPAT XEP-0411 Broadcast as per XEP-0048 + PEP
426 local function legacy_broadcast(event)
427 local service = event.service;
428 local ok, bookmarks = service:get_items(namespace, event.actor);
429 if bookmarks == "item-not-found" then ok, bookmarks = true, {} end
430 if not ok then return end
431 local legacy_bookmarks_item = st.stanza("item", { xmlns = xmlns_pubsub; id = "current" })
432 :add_child(generate_legacy_storage(bookmarks));
433 -- FIXME This broadcasts to any and all contacts who sent +notify because the node does not exist, so defaults apply.
434 service:broadcast("items", namespace_legacy, { --[[ no subscribers ]] }, legacy_bookmarks_item, event.actor);
435 end
436 local function broadcast_legacy_removal(event)
437 if event.node ~= namespace then return end
438 return legacy_broadcast(event);
439 end
440 module:hook("presence/initial", function (event)
441 -- Broadcasts to all clients with legacy+notify, not just the one coming online.
442 -- Upgrade to XEP-0402 to avoid it
443 local service = mod_pep.get_pep_service(event.origin.username);
444 legacy_broadcast({ service = service, actor = event.origin.full_jid });
445 end);
420 module:handle_items("pep-service", function (event) 446 module:handle_items("pep-service", function (event)
421 local service = event.item.service; 447 local service = event.item.service;
422 module:hook_object_event(service.events, "node-created", on_node_created); 448 module:hook_object_event(service.events, "node-created", on_node_created);
449 module:hook_object_event(service.events, "item-published/" .. namespace, legacy_broadcast);
450 module:hook_object_event(service.events, "item-retracted", broadcast_legacy_removal);
451 module:hook_object_event(service.events, "node-purged", broadcast_legacy_removal);
452 module:hook_object_event(service.events, "node-deleted", broadcast_legacy_removal);
423 end, function (event) 453 end, function (event)
424 local service = event.item.service; 454 local service = event.item.service;
425 module:unhook_object_event(service.events, "node-created", on_node_created); 455 module:unhook_object_event(service.events, "node-created", on_node_created);
456 module:unhook_object_event(service.events, "item-published/" .. namespace, legacy_broadcast);
457 module:unhook_object_event(service.events, "item-retracted", broadcast_legacy_removal);
458 module:unhook_object_event(service.events, "node-purged", broadcast_legacy_removal);
459 module:unhook_object_event(service.events, "node-deleted", broadcast_legacy_removal);
426 end, true); 460 end, true);