+ else -- requested item doesn't exist
+ local stanza = st.reply(stanza)
+ :tag('pubsub', {xmlns='http://jabber.org/protocol/pubsub'})
+ :tag('items', {node=node})
+ :up();
+ session.send(stanza);
+ return true;
+ end
+ elseif node then -- node doesn't exist
+ session.send(st.error_reply(stanza, 'cancel', 'item-not-found'));
+ return true;
+ else --invalid request
+ session.send(st.error_reply(stanza, 'modify', 'bad-request'));
+ return true;
+ end
+ else --no presence subscription
+ session.send(st.error_reply(stanza, 'auth', 'not-authorized')
+ :tag('presence-subscription-required', {xmlns='http://jabber.org/protocol/pubsub#errors'}));
+ return true;
+ end
+ end
+end);
+
+module:hook("iq-result/bare/disco", function(event)
+ local session, stanza = event.origin, event.stanza;
+ if stanza.attr.type == "result" then
+ local disco = stanza.tags[1];
+ if disco and disco.name == "query" and disco.attr.xmlns == "http://jabber.org/protocol/disco#info" then
+ -- Process disco response
+ local self = not stanza.attr.to;
+ local user = stanza.attr.to or (session.username..'@'..session.host);
+ local contact = stanza.attr.from;
+ local current = recipients[user] and recipients[user][contact];
+ if type(current) ~= "string" then return; end -- check if waiting for recipient's response
+ local ver = current;
+ if not string.find(current, "#") then
+ ver = calculate_hash(disco.tags); -- calculate hash
+ end
+ local notify = {};
+ for _, feature in pairs(disco.tags) do
+ if feature.name == "feature" and feature.attr.var then
+ local nfeature = feature.attr.var:match("^(.*)%+notify$");
+ if nfeature then notify[nfeature] = true; end
+ end
+ end
+ hash_map[ver] = notify; -- update hash map
+ if self then
+ for jid, item in pairs(session.roster) do -- for all interested contacts
+ if item.subscription == "both" or item.subscription == "from" then
+ if not recipients[jid] then recipients[jid] = {}; end
+ recipients[jid][contact] = notify;
+ publish_all(jid, contact, session);
+ end
+ end
+ end
+ recipients[user][contact] = notify; -- set recipient's data to calculated data
+ -- send messages to recipient
+ publish_all(user, contact, session);