mod_groups_muc_bookmarks/mod_groups_muc_bookmarks.lua
changeset 4865 5fadb991003d
parent 4590 240fa534f586
child 4866 9a8a43d0faed
equal deleted inserted replaced
4864:4a34ed2bb9a2 4865:5fadb991003d
     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)