1 local pubsub = require "util.pubsub";
2 local st = require "util.stanza";
3 local jid_bare = require "util.jid".bare;
4 local uuid_generate = require "util.uuid".generate;
6 require "core.modulemanager".load(module.host, "iq");
8 local xmlns_pubsub = "http://jabber.org/protocol/pubsub";
9 local xmlns_pubsub_errors = "http://jabber.org/protocol/pubsub#errors";
10 local xmlns_pubsub_event = "http://jabber.org/protocol/pubsub#event";
16 function handle_pubsub_iq(event)
17 local origin, stanza = event.origin, event.stanza;
18 local pubsub = stanza.tags[1];
19 local action = pubsub.tags[1];
20 local handler = handlers[stanza.attr.type.."_"..action.name];
22 handler(origin, stanza, action);
27 local pubsub_errors = {
28 ["conflict"] = { "cancel", "conflict" };
29 ["invalid-jid"] = { "modify", "bad-request", nil, "invalid-jid" };
30 ["item-not-found"] = { "cancel", "item-not-found" };
31 ["not-subscribed"] = { "modify", "unexpected-request", nil, "not-subscribed" };
33 function pubsub_error_reply(stanza, error)
34 local e = pubsub_errors[error];
35 local reply = st.error_reply(stanza, unpack(e, 1, 3));
37 reply:tag(e[4], { xmlns = xmlns_pubsub_errors }):up();
42 function handlers.get_items(origin, stanza, items)
43 local node = items.attr.node;
44 local item = items:get_child("item");
45 local id = item and item.attr.id;
46 local data = st.stanza("items", { node = node });
47 for _, entry in pairs(service:get(node, stanza.attr.from, id)) do
48 data:add_child(entry);
51 reply = st.reply(stanza)
52 :tag("pubsub", { xmlns = xmlns_pubsub })
55 reply = pubsub_error_reply(stanza, "item-not-found");
57 return origin.send(reply);
60 function handlers.set_create(origin, stanza, create)
61 local node = create.attr.node;
64 ok, ret = service:create(node, stanza.attr.from);
66 reply = st.reply(stanza);
68 reply = pubsub_error_reply(stanza, ret);
72 node = uuid_generate();
73 ok, ret = service:create(node, stanza.attr.from);
75 reply = st.reply(stanza)
76 :tag("pubsub", { xmlns = xmlns_pubsub })
77 :tag("create", { node = node });
82 function handlers.set_subscribe(origin, stanza, subscribe)
83 local node, jid = subscribe.attr.node, subscribe.attr.jid;
84 if jid_bare(jid) ~= jid_bare(stanza.attr.from) then
85 return origin.send(pubsub_error_reply(stanza, "invalid-jid"));
87 local ok, ret = service:add_subscription(node, stanza.attr.from, jid);
90 reply = st.reply(stanza)
91 :tag("pubsub", { xmlns = xmlns_pubsub })
92 :tag("subscription", {
95 subscription = "subscribed"
98 reply = pubsub_error_reply(stanza, ret);
100 return origin.send(reply);
103 function handlers.set_unsubscribe(origin, stanza, unsubscribe)
104 local node, jid = unsubscribe.attr.node, unsubscribe.attr.jid;
105 if jid_bare(jid) ~= jid_bare(stanza.attr.from) then
106 return origin.send(pubsub_error_reply(stanza, "invalid-jid"));
108 local ok, ret = service:remove_subscription(node, stanza.attr.from, jid);
111 reply = st.reply(stanza);
113 reply = pubsub_error_reply(stanza, ret);
115 return origin.send(reply);
118 function handlers.set_publish(origin, stanza, publish)
119 local node = publish.attr.node;
120 local item = publish:get_child("item");
121 local id = (item and item.attr.id) or uuid_generate();
122 local ok, ret = service:publish(node, stanza.attr.from, id, item);
125 reply = st.reply(stanza)
126 :tag("pubsub", { xmlns = xmlns_pubsub })
127 :tag("publish", { node = node })
128 :tag("item", { id = id });
130 reply = pubsub_error_reply(stanza, ret);
132 return origin.send(reply);
135 function simple_broadcast(node, jids, item)
136 local message = st.message({ from = module.host, type = "headline" })
137 :tag("event", { xmlns = xmlns_pubsub_event })
138 :tag("items", { node = node })
140 for jid in pairs(jids) do
141 module:log("debug", "Sending notification to %s", jid);
142 message.attr.to = jid;
143 core_post_stanza(hosts[module.host], message);
147 module:hook("iq/host/http://jabber.org/protocol/pubsub:pubsub", handle_pubsub_iq);
149 service = pubsub.new({
150 broadcaster = simple_broadcast
152 module.environment.service = service;