Mercurial > prosody-modules
comparison mod_groups_muc_bookmarks/mod_groups_muc_bookmarks.lua @ 4425:b3e0295e14a3
mod_groups_muc_bookmarks: manage PEP (XEP-0048) bookmarks of group members
| author | Jonas Schäfer <jonas@wielicki.name> |
|---|---|
| date | Wed, 03 Feb 2021 18:03:12 +0100 |
| parents | |
| children | 240fa534f586 |
comparison
equal
deleted
inserted
replaced
| 4424:679be18e6a5e | 4425:b3e0295e14a3 |
|---|---|
| 1 local jid_split = require "util.jid".split; | |
| 2 | |
| 3 local st = require "util.stanza"; | |
| 4 | |
| 5 local mod_groups = module:depends("groups_internal") | |
| 6 local mod_pep = module:depends("pep") | |
| 7 | |
| 8 local PUBSUB_NODE_XEP0048 = "storage:bookmarks"; | |
| 9 local XMLNS_XEP0048 = "storage:bookmarks"; | |
| 10 local XMLNS_XEP0060 = "http://jabber.org/protocol/pubsub"; | |
| 11 | |
| 12 local default_options = { | |
| 13 ["persist_items"] = true; | |
| 14 ["access_model"] = "whitelist"; | |
| 15 }; | |
| 16 | |
| 17 local function get_current_bookmarks(jid, service) | |
| 18 local ok, id, item = service:get_last_item(PUBSUB_NODE_XEP0048, jid) | |
| 19 if not ok or id == nil then | |
| 20 if id == "item-not-found" or id == nil then | |
| 21 -- return empty | |
| 22 return st.stanza("storage", { xmlns = XMLNS_XEP0048 }); | |
| 23 end | |
| 24 return nil, result | |
| 25 end | |
| 26 -- first item is the actual storage element | |
| 27 local hit = item:get_child("storage", XMLNS_XEP0048); | |
| 28 if not hit then | |
| 29 return nil, "internal-server-error" | |
| 30 end | |
| 31 return hit | |
| 32 end | |
| 33 | |
| 34 local function update_bookmarks(jid, service, storage) | |
| 35 local item = st.stanza("item", { xmlns = XMLNS_XEP0060, id = "current" }):add_child(storage) | |
| 36 module:log("debug", "updating bookmarks with %q", item) | |
| 37 local ok, err = service:publish( | |
| 38 PUBSUB_NODE_XEP0048, | |
| 39 jid, | |
| 40 "current", | |
| 41 item, | |
| 42 default_options | |
| 43 ) | |
| 44 if not ok then | |
| 45 module:log("error", "failed to update bookmarks: %s", err) | |
| 46 end | |
| 47 end | |
| 48 | |
| 49 local function find_matching_bookmark(storage, room) | |
| 50 for node in storage:childtags("conference") do | |
| 51 if node.attr.jid == room then | |
| 52 return node | |
| 53 end | |
| 54 end | |
| 55 return nil | |
| 56 end | |
| 57 | |
| 58 local function inject_bookmark(jid, room, autojoin, name) | |
| 59 local pep_service = mod_pep.get_pep_service(jid_split(jid)) | |
| 60 | |
| 61 autojoin = autojoin or false and true | |
| 62 local current = get_current_bookmarks(jid, pep_service) | |
| 63 local existing = find_matching_bookmark(current, room) | |
| 64 if existing then | |
| 65 if autojoin ~= nil then | |
| 66 existing.attr.autojoin = autojoin and "true" or "false" | |
| 67 end | |
| 68 if name ~= nil then | |
| 69 -- do not change already configured names | |
| 70 if not existing.attr.name then | |
| 71 existing.attr.name = name | |
| 72 end | |
| 73 end | |
| 74 done = true | |
| 75 module:log("debug", "found existing matching bookmark, updated") | |
| 76 else | |
| 77 module:log("debug", "no existing bookmark found, adding new") | |
| 78 current:tag("conference", { | |
| 79 name = name, | |
| 80 autojoin = autojoin and "true" or "false", | |
| 81 jid = room, | |
| 82 xmlns = XMLNS_XEP0048, | |
| 83 }) | |
| 84 end | |
| 85 | |
| 86 update_bookmarks(jid, pep_service, current) | |
| 87 end | |
| 88 | |
| 89 local function remove_bookmark(jid, room, autojoin, name) | |
| 90 local pep_service = mod_pep.get_pep_service(jid_split(jid)) | |
| 91 | |
| 92 autojoin = autojoin or false and true | |
| 93 local current = get_current_bookmarks(jid, pep_service) | |
| 94 current:maptags(function (node) | |
| 95 if node.attr.xmlns and node.attr.xmlns ~= XMLNS_XEP0048 then | |
| 96 return node | |
| 97 end | |
| 98 if node.name ~= "conference" then | |
| 99 return node | |
| 100 end | |
| 101 if node.attr.jid == room then | |
| 102 -- remove matching bookmark | |
| 103 return nil | |
| 104 end | |
| 105 return node | |
| 106 end) | |
| 107 | |
| 108 update_bookmarks(jid, pep_service, current) | |
| 109 end | |
| 110 | |
| 111 local function handle_user_added(event) | |
| 112 if not event.group_info.muc_jid then | |
| 113 module:log("debug", "ignoring user added event on group %s because it has no MUC", event.id) | |
| 114 return | |
| 115 end | |
| 116 local jid = event.user .. "@" .. event.host | |
| 117 inject_bookmark(jid, event.group_info.muc_jid, true, event.group_info.name) | |
| 118 end | |
| 119 | |
| 120 local function handle_user_removed(event) | |
| 121 if not event.group_info.muc_jid then | |
| 122 module:log("debug", "ignoring user removed event on group %s because it has no MUC", event.id) | |
| 123 return | |
| 124 end | |
| 125 -- Removing the bookmark is fine as the user just lost any privilege to | |
| 126 -- be in the MUC (as group MUCs are members-only). | |
| 127 local jid = event.user .. "@" .. event.host | |
| 128 remove_bookmark(jid, event.group_info.muc_jid, true, event.group_info.name) | |
| 129 end | |
| 130 | |
| 131 module:hook("group-user-added", handle_user_added) | |
| 132 module:hook("group-user-removed", handle_user_removed) |
