Software /
code /
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 |
child | 4586: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) |