Software /
code /
verse
Comparison
plugins/pubsub.lua @ 222:3c257afd68e7
plugins.pubsub: New, OOP-ish, PubSub interface. Beware of stubs.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Wed, 12 Oct 2011 18:11:07 +0200 |
parent | 221:efb4f60ba36e |
child | 248:c4b55b0dc6ba |
comparison
equal
deleted
inserted
replaced
221:efb4f60ba36e | 222:3c257afd68e7 |
---|---|
1 local jid_bare = require "util.jid".bare; | 1 local jid_bare = require "util.jid".bare; |
2 local t_insert = table.insert; | |
2 | 3 |
3 local xmlns_pubsub = "http://jabber.org/protocol/pubsub"; | 4 local xmlns_pubsub = "http://jabber.org/protocol/pubsub"; |
5 local xmlns_pubsub_owner = "http://jabber.org/protocol/pubsub#owner"; | |
4 local xmlns_pubsub_event = "http://jabber.org/protocol/pubsub#event"; | 6 local xmlns_pubsub_event = "http://jabber.org/protocol/pubsub#event"; |
5 local xmlns_pubsub_errors = "http://jabber.org/protocol/pubsub#errors"; | 7 local xmlns_pubsub_errors = "http://jabber.org/protocol/pubsub#errors"; |
6 | 8 |
7 local pubsub = {}; | 9 local pubsub = {}; |
8 local pubsub_mt = { __index = pubsub }; | 10 local pubsub_mt = { __index = pubsub }; |
26 end); | 28 end); |
27 return true; | 29 return true; |
28 end | 30 end |
29 | 31 |
30 function pubsub:create(server, node, callback) | 32 function pubsub:create(server, node, callback) |
33 self.stream:warn("pubsub:create() is deprecated, " | |
34 .."you should use pubsub:service(%q):node(%q):create() instead\n%s", server or "", node, debug.traceback()); | |
31 local create = verse.iq({ to = server, type = "set" }) | 35 local create = verse.iq({ to = server, type = "set" }) |
32 :tag("pubsub", { xmlns = xmlns_pubsub }) | 36 :tag("pubsub", { xmlns = xmlns_pubsub }) |
33 :tag("create", { node = node }):up() | 37 :tag("create", { node = node }):up() |
34 self.stream:send_iq(create, function (result) | 38 self.stream:send_iq(create, function (result) |
35 if callback then | 39 if callback then |
42 end | 46 end |
43 ); | 47 ); |
44 end | 48 end |
45 | 49 |
46 function pubsub:subscribe(server, node, jid, callback) | 50 function pubsub:subscribe(server, node, jid, callback) |
51 self.stream:warn("pubsub:subscribe() is deprecated, " | |
52 .."you should use pubsub:service(%q):node(%q):subscribe(jid) instead\n%s", server or "", node, debug.traceback()); | |
47 self.stream:send_iq(verse.iq({ to = server, type = "set" }) | 53 self.stream:send_iq(verse.iq({ to = server, type = "set" }) |
48 :tag("pubsub", { xmlns = xmlns_pubsub }) | 54 :tag("pubsub", { xmlns = xmlns_pubsub }) |
49 :tag("subscribe", { node = node, jid = jid or jid_bare(self.stream.jid) }) | 55 :tag("subscribe", { node = node, jid = jid or jid_bare(self.stream.jid) }) |
50 , function (result) | 56 , function (result) |
51 if callback then | 57 if callback then |
58 end | 64 end |
59 ); | 65 ); |
60 end | 66 end |
61 | 67 |
62 function pubsub:publish(server, node, id, item, callback) | 68 function pubsub:publish(server, node, id, item, callback) |
69 self.stream:warn("pubsub:publish() is deprecated, " | |
70 .."you should use pubsub:service(%q):node(%q):publish() instead\n%s", server or "", node, debug.traceback()); | |
63 self.stream:send_iq(verse.iq({ to = server, type = "set" }) | 71 self.stream:send_iq(verse.iq({ to = server, type = "set" }) |
64 :tag("pubsub", { xmlns = xmlns_pubsub }) | 72 :tag("pubsub", { xmlns = xmlns_pubsub }) |
65 :tag("publish", { node = node }) | 73 :tag("publish", { node = node }) |
66 :tag("item", { id = id }) | 74 :tag("item", { id = id }) |
67 :add_child(item) | 75 :add_child(item) |
74 end | 82 end |
75 end | 83 end |
76 end | 84 end |
77 ); | 85 ); |
78 end | 86 end |
87 | |
88 -------------------------------------------------------------------------- | |
89 ---------------------New and improved PubSub interface-------------------- | |
90 -------------------------------------------------------------------------- | |
91 | |
92 local pubsub_service = {}; | |
93 local pubsub_service_mt = { __index = pubsub_service }; | |
94 | |
95 -- TODO should the property be named 'jid' instead? | |
96 function pubsub:service(service) | |
97 return setmetatable({ stream = self.stream, service = service }, pubsub_service_mt) | |
98 end | |
99 | |
100 -- Helper function for iq+pubsub tags | |
101 | |
102 local function pubsub_iq(iq_type, to, ns, op, node, jid, item_id) | |
103 local st = verse.iq{ type = iq_type or "get", to = to } | |
104 :tag("pubsub", { xmlns = ns or xmlns_pubsub }) -- ns would be ..#owner | |
105 if op then st:tag(op, { node = node, jid = jid }); end | |
106 if id then st:tag("item", { id = item_id ~= true and item_id or nil }); end | |
107 return st; | |
108 end | |
109 | |
110 -- http://xmpp.org/extensions/xep-0060.html#entity-subscriptions | |
111 function pubsub_service:subscriptions(callback) | |
112 self.stream:send_iq(pubsub_iq(nil, self.service, nil, "subscriptions") | |
113 , callback and function (result) | |
114 if result.attr.type == "result" then | |
115 local ps = result:get_child("pubsub", xmlns_pubsub); | |
116 local subs = ps and ps:get_child("subscriptions"); | |
117 local nodes = {}; | |
118 if subs then | |
119 for sub in subs:childtags("subscription") do | |
120 local node = self:node(sub.attr.node) | |
121 node.subscription = sub; | |
122 t_insert(nodes, node); | |
123 -- FIXME Good enough? | |
124 -- Or how about: | |
125 -- nodes[node] = sub; | |
126 end | |
127 end | |
128 callback(nodes); | |
129 else | |
130 callback(false, result:get_error()); | |
131 end | |
132 end or nil); | |
133 end | |
134 | |
135 -- http://xmpp.org/extensions/xep-0060.html#entity-affiliations | |
136 function pubsub_service:affiliations(callback) | |
137 self.stream:send_iq(pubsub_iq(nil, self.service, nil, "affiliations") | |
138 , callback and function (result) | |
139 if result.attr.type == "result" then | |
140 local ps = result:get_child("pubsub", xmlns_pubsub); | |
141 local affils = ps and ps:get_child("affiliations") or {}; | |
142 local nodes = {}; | |
143 if affils then | |
144 for affil in affils:childtags("affiliation") do | |
145 local node = self:node(affil.attr.node) | |
146 node.affiliation = affil; | |
147 t_insert(nodes, node); | |
148 -- nodes[node] = affil; | |
149 end | |
150 end | |
151 callback(nodes); | |
152 else | |
153 callback(false, result:get_error()); | |
154 end | |
155 end or nil); | |
156 end | |
157 | |
158 -- TODO Listing nodes? It's done with standard disco#items, but should | |
159 -- we have a wrapper here? If so, it could wrap items in pubsub_node objects | |
160 | |
161 --[[ | |
162 function pubsub_service:nodes(callback) | |
163 self.stream:disco_items(...) | |
164 end | |
165 --]] | |
166 | |
167 local pubsub_node = {}; | |
168 local pubsub_node_mt = { __index = pubsub_node }; | |
169 | |
170 function pubsub_service:node(node) | |
171 return setmetatable({ stream = self.stream, service = self.service, node = node }, pubsub_node_mt) | |
172 end | |
173 | |
174 function pubsub_mt:__call(service, node) | |
175 local s = self:service(service); | |
176 return node and s:node(node) or s; | |
177 end | |
178 | |
179 function pubsub_node:hook(callback, prio) | |
180 local function hook(event) | |
181 -- FIXME service == nil would mean anyone, | |
182 -- publishing would be go to your bare jid. | |
183 -- So if you're only interestied in your own | |
184 -- events, hook your own bare jid. | |
185 if (not event.service or event.from == self.service) and event.node == self.node then | |
186 return callback(event) | |
187 end | |
188 end | |
189 self.stream:hook("pubsub/event", hook, prio); | |
190 return hook; | |
191 end | |
192 | |
193 function pubsub_node:unhook(callback) | |
194 self.stream:unhook("pubsub/event", callback); | |
195 end | |
196 | |
197 function pubsub_node:create(config, callback) | |
198 if config ~= nil then | |
199 error("Not implemented yet."); | |
200 else | |
201 self.stream:send_iq(pubsub_iq("set", self.service, nil, "create", self.node), callback); | |
202 end | |
203 end | |
204 | |
205 -- <configure/> and <default/> rolled into one | |
206 function pubsub_node:configure(config, callback) | |
207 if config ~= nil then | |
208 error("Not implemented yet."); | |
209 -- if config == true then | |
210 -- fetch form and pass it to the callback | |
211 -- which would process it and pass it back | |
212 -- and then we submit it | |
213 -- elseif type(config) == "table" then | |
214 -- it's a form or stanza that we submit | |
215 -- end | |
216 -- this would be done for everything that needs a config | |
217 end | |
218 self.stream:send_iq(pubsub_iq("set", self.service, nil, config == nil and "default" or "configure", self.node), callback); | |
219 end | |
220 | |
221 function pubsub_node:publish(id, options, node, callback) | |
222 if options ~= nil then | |
223 error("Node configuration is not implemented yet."); | |
224 end | |
225 self.stream:send_iq(pubsub_iq("set", self.service, nil, "publish", self.node, nil, id) | |
226 :add_child(node) | |
227 , callback); | |
228 end | |
229 | |
230 function pubsub_node:subscribe(jid, options, callback) | |
231 if options ~= nil then | |
232 error("Subscription configuration is not implemented yet."); | |
233 end | |
234 self.stream:send_iq(pubsub_iq("set", self.service, nil, "subscribe", self.node, jid, id) | |
235 , callback); | |
236 end | |
237 | |
238 function pubsub_node:subscription(callback) | |
239 error("Not implemented yet."); | |
240 end | |
241 | |
242 function pubsub_node:affiliation(callback) | |
243 error("Not implemented yet."); | |
244 end | |
245 | |
246 function pubsub_node:unsubscribe(callback) | |
247 error("Not implemented yet."); | |
248 end | |
249 | |
250 function pubsub_node:configure_subscription(options, callback) | |
251 error("Not implemented yet."); | |
252 end | |
253 | |
254 function pubsub_node:items(count, callback) | |
255 error("Not implemented yet."); | |
256 end | |
257 | |
258 function pubsub_node:item(id, callback) | |
259 error("Not implemented yet."); | |
260 end | |
261 | |
262 function pubsub_node:retract(id, callback) | |
263 error("Not implemented yet."); | |
264 end | |
265 | |
266 function pubsub_node:purge(callback) | |
267 error("Not implemented yet."); | |
268 end | |
269 | |
270 function pubsub_node:delete(callback) | |
271 error("Not implemented yet."); | |
272 end | |
273 |