3 local st = require "util.stanza"; |
3 local st = require "util.stanza"; |
4 |
4 |
5 local mod_groups = module:depends("groups_internal") |
5 local mod_groups = module:depends("groups_internal") |
6 local mod_pep = module:depends("pep") |
6 local mod_pep = module:depends("pep") |
7 |
7 |
8 local PUBSUB_NODE_XEP0048 = "storage:bookmarks"; |
8 local XMLNS_BM2 = "urn:xmpp:bookmarks:1"; |
9 local XMLNS_XEP0048 = "storage:bookmarks"; |
|
10 local XMLNS_XEP0060 = "http://jabber.org/protocol/pubsub"; |
9 local XMLNS_XEP0060 = "http://jabber.org/protocol/pubsub"; |
11 |
10 |
12 local default_options = { |
11 local default_options = { |
13 ["persist_items"] = true; |
12 ["persist_items"] = true; |
|
13 ["max_items"] = "max"; |
|
14 ["send_last_published_item"] = "never"; |
14 ["access_model"] = "whitelist"; |
15 ["access_model"] = "whitelist"; |
15 }; |
16 }; |
16 |
17 |
17 local function get_current_bookmarks(jid, service) |
18 local function get_current_bookmarks(jid, service) |
18 local ok, id, item = service:get_last_item(PUBSUB_NODE_XEP0048, jid) |
19 local ok, items = service:get_items(XMLNS_BM2, jid) |
19 if not ok or id == nil then |
20 if not ok then return nil, items; end |
20 if id == "item-not-found" or id == nil then |
21 return items or {}; |
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 |
22 end |
33 |
23 |
34 local function update_bookmarks(jid, service, storage) |
24 local function update_bookmark(jid, service, room, bookmark) |
35 local item = st.stanza("item", { xmlns = XMLNS_XEP0060, id = "current" }):add_child(storage) |
25 local ok, err = service:publish(XMLNS_BM2, jid, room, bookmark, default_options); |
36 module:log("debug", "updating bookmarks with %q", item) |
26 if ok then |
37 local ok, err = service:publish( |
27 module:log("debug", "found existing matching bookmark, updated") |
38 PUBSUB_NODE_XEP0048, |
28 else |
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) |
29 module:log("error", "failed to update bookmarks: %s", err) |
46 end |
30 end |
47 end |
31 end |
48 |
32 |
49 local function find_matching_bookmark(storage, room) |
33 local function find_matching_bookmark(storage, room) |
50 for node in storage:childtags("conference") do |
34 return storage[room]; |
51 if node.attr.jid == room then |
|
52 return node |
|
53 end |
|
54 end |
|
55 return nil |
|
56 end |
35 end |
57 |
36 |
58 local function inject_bookmark(jid, room, autojoin, name) |
37 local function inject_bookmark(jid, room, autojoin, name) |
59 local pep_service = mod_pep.get_pep_service(jid_split(jid)) |
38 local pep_service = mod_pep.get_pep_service(jid_split(jid)) |
60 |
39 |
61 autojoin = autojoin or false and true |
40 local current, err = get_current_bookmarks(jid, pep_service); |
62 local current = get_current_bookmarks(jid, pep_service) |
41 if err then |
63 local existing = find_matching_bookmark(current, room) |
42 module:log("error", "Could not retrieve existing bookmarks for %s: %s", jid, err); |
64 if existing then |
43 return; |
|
44 end |
|
45 local found = find_matching_bookmark(current, room) |
|
46 if found then |
|
47 local existing = found:get_child("conference", XMLNS_BM2); |
65 if autojoin ~= nil then |
48 if autojoin ~= nil then |
66 existing.attr.autojoin = autojoin and "true" or "false" |
49 existing.attr.autojoin = autojoin and "true" or "false" |
67 end |
50 end |
68 if name ~= nil then |
51 if name ~= nil then |
69 -- do not change already configured names |
52 -- do not change already configured names |
70 if not existing.attr.name then |
53 if not existing.attr.name then |
71 existing.attr.name = name |
54 existing.attr.name = name |
72 end |
55 end |
73 end |
56 end |
74 done = true |
|
75 module:log("debug", "found existing matching bookmark, updated") |
|
76 else |
57 else |
77 module:log("debug", "no existing bookmark found, adding new") |
58 module:log("debug", "no existing bookmark found, adding new") |
78 current:tag("conference", { |
59 found = st.stanza("item", { xmlns = XMLNS_XEP0060; id = room }) |
79 name = name, |
60 :tag("conference", { xmlns = XMLNS_BM2; name = name; autojoin = autojoin and "true" or "false"; }) |
80 autojoin = autojoin and "true" or "false", |
|
81 jid = room, |
|
82 xmlns = XMLNS_XEP0048, |
|
83 }) |
|
84 end |
61 end |
85 |
62 |
86 update_bookmarks(jid, pep_service, current) |
63 update_bookmark(jid, pep_service, current, room, found) |
87 end |
64 end |
88 |
65 |
89 local function remove_bookmark(jid, room, autojoin, name) |
66 local function remove_bookmark(jid, room, autojoin, name) |
90 local pep_service = mod_pep.get_pep_service(jid_split(jid)) |
67 local pep_service = mod_pep.get_pep_service(jid_split(jid)) |
91 |
68 |
92 autojoin = autojoin or false and true |
69 return pep_service:retract(XMLNS_BM2, jid, room, st.stanza("retract", { id = room })); |
93 local current = get_current_bookmarks(jid, pep_service) |
|
94 if not current then |
|
95 return |
|
96 end |
|
97 current:maptags(function (node) |
|
98 if node.attr.xmlns and node.attr.xmlns ~= XMLNS_XEP0048 then |
|
99 return node |
|
100 end |
|
101 if node.name ~= "conference" then |
|
102 return node |
|
103 end |
|
104 if node.attr.jid == room then |
|
105 -- remove matching bookmark |
|
106 return nil |
|
107 end |
|
108 return node |
|
109 end) |
|
110 |
|
111 update_bookmarks(jid, pep_service, current) |
|
112 end |
70 end |
113 |
71 |
114 local function handle_user_added(event) |
72 local function handle_user_added(event) |
115 if not event.group_info.muc_jid then |
73 if not event.group_info.muc_jid then |
116 module:log("debug", "ignoring user added event on group %s because it has no MUC", event.id) |
74 module:log("debug", "ignoring user added event on group %s because it has no MUC", event.id) |