1 |
1 |
2 -- PUBLISH-SUBSCRIBE (BEP-0060) |
2 -- PUBLISH-SUBSCRIBE (BEP-0060) |
3 |
3 |
4 -- library |
4 -- library |
5 |
5 |
6 require 'lm' |
6 local lm = require 'lm' |
7 local iq = require 'iq' |
7 local iq = require 'iq' |
8 require 'x_data' |
8 require 'x_data' |
9 |
9 |
10 -- public |
10 -- |
11 |
11 |
12 pubsub = { } |
12 local O = { |
|
13 handlers = { }, |
|
14 } |
|
15 |
|
16 local F = { } |
|
17 |
|
18 function F.handler ( xmlns, handler ) |
|
19 O.handlers[xmlns] = handler |
|
20 end |
|
21 |
|
22 function F.message_handler ( conn, mess ) |
|
23 local e = mess:child ( 'event' ) |
|
24 if e and e:attribute ( 'xmlns' ) == 'http://jabber.org/protocol/pubsub#event' then |
|
25 local is = e:child ( 'items' ) |
|
26 if is then |
|
27 local from = mess:attribute ( 'from' ) |
|
28 local node = is:attribute ( 'node' ) |
|
29 local item = is:child () |
|
30 while item do |
|
31 local id = item:attribute ( 'id' ) |
|
32 local n = item:child () |
|
33 while n do |
|
34 local xmlns = n:attribute ( 'xmlns' ) |
|
35 if O.handlers[xmlns] then |
|
36 O.handlers[xmlns] ( from, node, n, id ) |
|
37 end |
|
38 n = n:next () |
|
39 end |
|
40 item = item:next () |
|
41 end |
|
42 return true |
|
43 end |
|
44 end |
|
45 return false |
|
46 end |
13 |
47 |
14 -- SUBSCRIBER USE CASES |
48 -- SUBSCRIBER USE CASES |
15 |
49 |
16 function pubsub.subscribe ( conn, to, node, success, fail ) |
50 function F.subscribe ( conn, to, node, success, fail ) |
17 local jid = conn:jid():gsub ( '/.*', '' ) |
51 local jid = conn:jid():gsub ( '/.*', '' ) |
18 iq.send ( conn, to, 'set', |
52 iq.send ( conn, to, 'set', |
19 { |
53 { |
20 pubsub = { xmlns = 'http://jabber.org/protocol/pubsub', |
54 pubsub = { xmlns = 'http://jabber.org/protocol/pubsub', |
21 subscribe = { node = node, jid = jid }, |
55 subscribe = { node = node, jid = jid }, |
97 end |
131 end |
98 end |
132 end |
99 end, fail ) |
133 end, fail ) |
100 end |
134 end |
101 |
135 |
102 function pubsub.delete_node ( conn, to, node, success, fail ) |
136 function F.delete_node ( conn, to, node, success, fail ) |
103 iq.send ( conn, to, 'set', |
137 iq.send ( conn, to, 'set', |
104 { |
138 { |
105 pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner', |
139 pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner', |
106 delete = { node = node }, |
140 delete = { node = node }, |
107 }, |
141 }, |
108 }, success, fail ) |
142 }, success, fail ) |
109 end |
143 end |
110 |
144 |
111 function pubsub.purge_node ( conn, to, node, success, fail ) |
145 function F.purge_node ( conn, to, node, success, fail ) |
112 iq.send ( conn, to, 'set', |
146 iq.send ( conn, to, 'set', |
113 { |
147 { |
114 pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner', |
148 pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner', |
115 purge = { node = node }, |
149 purge = { node = node }, |
116 }, |
150 }, |
117 }, success, fail ) |
151 }, success, fail ) |
118 end |
152 end |
119 |
153 |
120 function pubsub.configure_node ( conn, to, node, success, fail ) |
154 function F.configure_node ( conn, to, node, success, fail ) |
121 iq.send ( conn, to, 'get', |
155 iq.send ( conn, to, 'get', |
122 { |
156 { |
123 pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner', |
157 pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner', |
124 configure = { node = node }, |
158 configure = { node = node }, |
125 }, |
159 }, |
151 fail ( mess:xml () ) -- XXX |
185 fail ( mess:xml () ) -- XXX |
152 end |
186 end |
153 end, fail ) |
187 end, fail ) |
154 end |
188 end |
155 |
189 |
156 function pubsub.list_subscriptions ( conn, to, node, success, fail ) |
190 function F.list_subscriptions ( conn, to, node, success, fail ) |
157 iq.send ( conn, to, 'get', |
191 iq.send ( conn, to, 'get', |
158 { |
192 { |
159 pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner', |
193 pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner', |
160 subscriptions = { node = node }, |
194 subscriptions = { node = node }, |
161 }, |
195 }, |
162 }, |
196 }, |
163 function ( mess ) |
197 function ( mess ) |
164 local s = mess:path ( 'pubsub', 'subscriptions' ) |
198 local s = mess:path ( 'pubsub', 'subscriptions' ) |
165 if s then |
199 if s then |
166 local sub = s:children () |
200 local sub = s:child () |
167 local ret = { } |
201 local ret = { } |
168 while sub do |
202 while sub do |
169 table.insert ( ret, { jid = sub:attribute ( 'jid' ), subscription = sub:attribute ( 'subscription' ), subid = sub:attribute ( 'subid' ) } ) |
203 table.insert ( ret, { jid = sub:attribute ( 'jid' ), subscription = sub:attribute ( 'subscription' ), subid = sub:attribute ( 'subid' ) } ) |
170 sub = sub:next () |
204 sub = sub:next () |
171 end |
205 end |
174 fail ( mess:xml () ) -- XXX |
208 fail ( mess:xml () ) -- XXX |
175 end |
209 end |
176 end, fail ) |
210 end, fail ) |
177 end |
211 end |
178 |
212 |
179 function pubsub.modify_subscription ( conn, to, node, jid, state, success, fail, id ) |
213 function F.modify_subscription ( conn, to, node, jid, state, success, fail, id ) |
180 iq.send ( conn, to, 'set', |
214 iq.send ( conn, to, 'set', |
181 { |
215 { |
182 pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner', |
216 pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner', |
183 subscriptions = { node = node, |
217 subscriptions = { node = node, |
184 subscription = { jid = jid, subscription = state, id = id }, |
218 subscription = { jid = jid, subscription = state, id = id }, |
185 }, |
219 }, |
186 }, |
220 }, |
187 }, success, fail ) |
221 }, success, fail ) |
188 end |
222 end |
189 |
223 |
190 -- mcabber |
224 return F |
191 |
|
192 main.command ( 'node', |
|
193 function ( args ) |
|
194 local who, action, node = args.t, args[1], args[2] |
|
195 local conn = lm.connection.bless ( main.connection () ) |
|
196 if not who then |
|
197 who = main.current_buddy () |
|
198 end |
|
199 if action == 'subscribe' then |
|
200 pubsub.subscribe ( conn, who, node, |
|
201 function ( id ) |
|
202 if id then |
|
203 main.print_info ( who, 'Subscription succeeds with id ' .. id ) |
|
204 else |
|
205 main.print_info ( who, 'Subscription successful' ) |
|
206 end |
|
207 end, |
|
208 function ( mesg ) |
|
209 main.print_info ( who, 'Subscription unsuccessful: ' .. mesg ) |
|
210 end ) |
|
211 elseif action == 'unsubscribe' then |
|
212 pubsub.unsubscribe ( conn, who, node, |
|
213 function () |
|
214 main.print_info ( who, 'Unubscription successful' ) |
|
215 end, |
|
216 function ( mesg ) |
|
217 main.print_info ( who, 'Unsubscription unsuccessful: ' .. mesg ) |
|
218 end ) |
|
219 elseif action == 'retrieve' or action == 'items' or action == 'get' then |
|
220 pubsub.retrieve ( conn, who, node, |
|
221 function ( from, node, item ) |
|
222 main.print_info ( who, 'Item from ' .. from .. ', node ' .. node .. ':\n' .. item:xml () ) |
|
223 end, |
|
224 function ( mesg ) |
|
225 main.print_info ( who, 'Retrieval failed: ' .. mesg ) |
|
226 end, args.m ) |
|
227 elseif action == 'create' or action == 'new' then |
|
228 pubsub.create_node ( conn, who, node, |
|
229 function ( node ) |
|
230 if node then |
|
231 main.print_info ( who, 'Node ' .. node .. ' successfully created' ) |
|
232 else |
|
233 main.print_info ( who, 'Node successfully created' ) |
|
234 end |
|
235 end, |
|
236 function ( mesg ) |
|
237 main.print_info ( who, 'Creation failed: ' .. mesg ) |
|
238 end ) |
|
239 elseif action == 'delete' or action == 'del' then |
|
240 pubsub.delete_node ( conn, who, node, |
|
241 function () |
|
242 main.print_info ( who, 'Node deleted' ) |
|
243 end, |
|
244 function ( mesg ) |
|
245 main.print_info ( who, 'Node deletion failed: ' .. mesg ) |
|
246 end ) |
|
247 elseif action == 'purge' or action == 'del_items' then |
|
248 pubsub.purge_node ( conn, who, node, |
|
249 function () |
|
250 main.print_info ( who, 'Node purged' ) |
|
251 end, |
|
252 function ( mesg ) |
|
253 main.print_info ( who, 'Node purge failed: ' .. mesg ) |
|
254 end ) |
|
255 elseif action:sub ( 1, 4 ) == 'conf' then |
|
256 pubsub.configure_node ( conn, who, node, |
|
257 function ( form, submit, reject ) |
|
258 local id = #forms + 1 |
|
259 forms[id] = { |
|
260 form = form, |
|
261 submit = |
|
262 function ( form ) |
|
263 submit ( form, |
|
264 function () |
|
265 main.print_info ( who, 'Node configuration completed' ) |
|
266 end, |
|
267 function ( mesg ) |
|
268 main.print_info ( who, 'Node configuration failed: ' .. mesg ) |
|
269 end ) |
|
270 end, |
|
271 reject = |
|
272 function ( form ) |
|
273 reject ( form, |
|
274 function () |
|
275 main.print_info ( who, 'Node configuration cancelled' ) |
|
276 end, |
|
277 function ( mesg ) |
|
278 main.print_info ( who, 'Node configuration cancellation failed: ' .. mesg ) |
|
279 end ) |
|
280 end, |
|
281 } |
|
282 print ( 'You have new form ' .. id ) |
|
283 end, |
|
284 function ( mesg ) |
|
285 main.print_info ( who, 'Node configuration failed: ' .. mesg ) |
|
286 end ) |
|
287 elseif action == 'subscriptions' or action == 'subscribers' then |
|
288 pubsub.list_subscriptions ( conn, who, node, |
|
289 function ( s ) |
|
290 local text = '' |
|
291 for i, v in ipairs ( s ) do |
|
292 local subid = v.subid |
|
293 if subid then |
|
294 subid = '(id ' .. subid .. ')' |
|
295 else |
|
296 subid = '' |
|
297 end |
|
298 text = text .. ('\n- [%s] %s %s'):format ( v.subscription, v.jid, subid ) |
|
299 end |
|
300 if text ~= '' then |
|
301 main.print_info ( who, 'Node subscriptions:' .. text ) |
|
302 else |
|
303 main.print_info ( who, 'No subscriptions' ) |
|
304 end |
|
305 end, |
|
306 function ( mesg ) |
|
307 main.print_info ( who, 'Node subscriptions retrieval failed: ' .. mesg ) |
|
308 end ) |
|
309 elseif action == 'subscription' or action == 'modify' then -- XXX |
|
310 pubsub.modify_subscription ( conn, args.t or main.current_buddy (), node, args[3], args[4], |
|
311 function () |
|
312 main.print_info ( who, 'Subscription modified' ) |
|
313 end, |
|
314 function ( mesg ) |
|
315 main.print_info ( who, 'Subsrciption modification failed: ' .. mesg ) |
|
316 end, args[5] ) |
|
317 else |
|
318 print ( 'Error: unknown action' ) |
|
319 end |
|
320 end, true ) |
|
321 |
|
322 -- FIXME |
|
323 commands_help['node'] = "[-t jid] [-m max_items] action [node_name]\n\nAction can be subscribe, unsubscribe, retrieve (items, get), create (new), delete (del), purge (del_items), configure (conf*), subscriptions (subscribers), subscription (modify?)" |
|
324 --[[ |
|
325 commands_help['subscribe'] = "[-t jid] node_name\n\nSends pubsub subscription request to specified node of jid or current buddy." |
|
326 commands_help['unsubscribe'] = "[-t jid] node_name\n\nSends pubsub unsubscription request to specified node of jid or current buddy." |
|
327 commands_help['retrieve'] = "[-t jid] [-m max_items] node_name\n\nSends pubsub items retrieval request to specified node of jid or current buddy.\nNote, that we cannot know, how to deal with these itemss, so, raw xml will be printed as a result." |
|
328 commands_help['create_node'] = "[-t jid] [node_name]\n\nSends pubsub node creation request to specified node of jid or current buddy. If node name is not specified, server can generate unique id for it, if supported." |
|
329 commands_help['configure_node'] = "[-t jid] node_name\n\nSends pubsub node configuration request to specified node of jid or current buddy." |
|
330 commands_help['delete_node'] = "[-t jid] node_name\n\nSends pubsub node deletion request to specified node of jid or current buddy." |
|
331 commands_help['purge_node'] = "[-t jid] node_name\n\nSends pubsub node items purging request to specified node of jid or current buddy." |
|
332 commands_help['subscriptions'] = "[-t jid] node_name\n\nSends pubsub subscription list request to specified node of jid or current buddy." |
|
333 commands_help['subscription'] = "[-t jid] node_name subscriber_jid state [subscription_id]\n\nSends pubsub subscription modification request to change subscription state of 'subscriber_jid' to 'state'. Optional id is used when multiple subscriptions for one jid are available." |
|
334 --]] |
|
335 |
225 |
336 -- vim: se ts=4: -- |
226 -- vim: se ts=4: -- |