mod_groups_muc_bookmarks/mod_groups_muc_bookmarks.lua
changeset 4429 b3e0295e14a3
child 4590 240fa534f586
equal deleted inserted replaced
4428:679be18e6a5e 4429: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)