Pubsub use lib interface
authorMyhailo Danylenko <isbear@ukrpost.net>
Sat, 21 Mar 2009 15:43:35 +0200
changeset 47 aba4bbe32cba
parent 46 c2210e9b3e34
child 48 d31ae73038f7
Pubsub use lib interface
examples/mcabberrc.lua
examples/pubsub.lua
--- a/examples/mcabberrc.lua	Sat Mar 21 14:06:42 2009 +0200
+++ b/examples/mcabberrc.lua	Sat Mar 21 15:43:35 2009 +0200
@@ -263,7 +263,7 @@
 
 -- PUBLISH-SUBSRIBE (XEP-0060)
 
-dopath 'xep0060'
+dopath 'pubsub'
 
 -- OUT OF BAND DATA (XEP-0066)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/pubsub.lua	Sat Mar 21 15:43:35 2009 +0200
@@ -0,0 +1,319 @@
+
+-- PUBLISH-SUBSCRIBE (BEP-0060)
+
+-- library
+
+require 'lm'
+require 'iq'
+
+-- public
+
+pubsub = { }
+
+-- SUBSCRIBER USE CASES
+
+function pubsub.subscribe ( conn, to, node, success, fail )
+	local jid = conn:jid():gsub ( '/.*', '' )
+	iq.send ( conn, to, 'set',
+		{
+			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub',
+				subscribe = { node = node, jid = jid },
+			},
+		},
+		function ( mess )
+			local s = mess:path ( 'pubsub', 'subscription' )
+			if s then
+				success ( s:attribute ( 'subid' ) )
+			else
+				success ()
+			end
+		end,
+		fail )
+end
+
+function pubsub.unsubscribe ( conn, to, node, success, fail )
+	local jid = conn:jid():gsub ( '/.*', '' )
+	iq.send ( conn, to, 'set',
+		{
+			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub',
+				unsubscribe = { node = node, jid = jid },
+			},
+		}, success, fail )
+end
+
+-- I found no servers with subscription options support thus it is not implemented.
+
+-- untested :(
+function pubsub.retrieve ( conn, to, node, success, fail, max, ids )
+	local items = { node = node, max_items = max }
+	if ids then
+		items.item = { }
+		for k, id in pairs ( ids ) do
+			table.insert ( items.item, { id = id } )
+		end
+	end
+	iq.send ( conn, to, 'get',
+		{
+			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub',
+				items = items,
+			},
+		},
+		function ( mess )
+			local items = mess:path ( 'pubsub', 'items' )
+			if items then
+				local from = mess:attribute ( 'from' )
+				local node = items:attribute ( 'node' )
+				local item = items:children ()
+				while item do
+					success ( from, node, item ) -- XXX use registered xmlns handlers for that?
+					item = item:next ()
+				end
+			end
+		end, fail )
+end
+
+-- OWNER USE CASES
+
+-- node may be nil
+function pubsub.create_node ( conn, to, node, success, fail )
+	iq.send ( conn, to, 'set',
+		{
+			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub',
+				create = { node = node },
+			},
+		},
+		function ( mess )
+			if node then
+				success ()
+			else
+				local create = mess:path ( 'pubsub', 'create' )
+				if create then
+					success ( create:attribute ( 'node' ) )
+				else
+					success ()
+				end
+			end
+		end, fail )
+end
+
+function pubsub.delete_node ( conn, to, node, success, fail )
+	iq.send ( conn, to, 'set',
+		{
+			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner',
+				delete = { node = node },
+			},
+		}, success, fail )
+end
+
+function pubsub.purge_node ( conn, to, node, success, fail )
+	iq.send ( conn, to, 'set',
+		{
+			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner',
+				purge = { node = node },
+			},
+		}, success, fail )
+end
+
+function pubsub.configure_node ( conn, to, node, success, fail )
+	iq.send ( conn, to, 'get',
+		{
+			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner',
+				configure = { node = node },
+			},
+		},
+		function ( mess ) -- FIXME
+			local x = mess:path ( 'pubsub', 'configure', 'x' )
+			if x then
+				local fid = parse_form ( x )
+				forms[fid].send =
+					function ( form )
+						iq.send ( conn, to, 'set',
+							{
+								pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner',
+									configure = { node = node,
+										x = { xmlns = 'jabber:x:data', type = 'submit',
+											field = form.val,
+										},
+									},
+								},
+							},
+							function ( mess )
+								success ()
+								main.print_info ( to, 'Now you can run /form del ' .. fid .. ' to delete form from list' )
+								form.status = 'acquired'
+							end,
+							function ( mesg )
+								if mesg then
+									form.status = 'rejected'
+								else
+									form.status = 'unknown'
+								end
+								fail ( mesg )
+							end )
+						form.status = 'sent'
+					end
+				forms[fid].status = 'filling'
+				main.print_info ( to, 'You have new form. To fill it, use /form ' .. fid .. ' fieldname value' )
+			else
+				main.print_info ( to, 'Weird, no error and no node configuration form: ' .. mess:xml () )
+			end
+		end, fail )
+end
+
+function pubsub.list_subscriptions ( conn, to, node, success, fail )
+	iq.send ( conn, to, 'get',
+		{
+			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner',
+				subscriptions = { node = node },
+			},
+		},
+		function ( mess )
+			local s = mess:path ( 'pubsub', 'subscriptions' )
+			if s then
+				local sub = s:children ()
+				local ret = { }
+				while sub do
+					table.insert ( ret, { jid = sub:attribute ( 'jid' ), subscription = sub:attribute ( 'subscription' ), subid = sub:attribute ( 'subid' ) } )
+					sub = sub:next ()
+				end
+				success ( ret )
+			else
+				fail ( mess:xml () ) -- XXX
+			end
+		end, fail )
+end
+
+function pubsub.modify_subscription ( conn, to, node, jid, state, success, fail, id )
+	iq.send ( conn, to, 'set',
+		{
+			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner',
+				subscriptions = { node = node,
+					subscription = { jid = jid, subscription = state, id = id },
+				},
+			},
+		}, success, fail )
+end
+
+-- mcabber
+
+main.command ( 'node',
+	function ( args )
+		local who, action, node = args.t, args[1], args[2]
+		local conn = lm.connection.bless ( main.connection () )
+		if not who then
+			who = main.current_buddy ()
+		end
+		if action == 'subscribe' then
+			pubsub.subscribe ( conn, who, node,
+				function ( id )
+					if id then
+						main.print_info ( who, 'Subscription succeeds with id ' .. id )
+					else
+						main.print_info ( who, 'Subscription successful' )
+					end
+				end,
+				function ( mesg )
+					main.print_info ( who, 'Subscription unsuccessful: ' .. mesg )
+				end )
+		elseif action == 'unsubscribe' then
+			pubsub.unsubscribe ( conn, who, node,
+				function ()
+					main.print_info ( who, 'Unubscription successful' )
+				end,
+				function ( mesg )
+					main.print_info ( who, 'Unsubscription unsuccessful: ' .. mesg )
+				end )
+		elseif action == 'retrieve' or action == 'items' or action == 'get' then
+			pubsub.retrieve ( conn, who, node,
+				function ( from, node, item )
+					main.print_info ( who, 'Item from ' .. from .. ', node ' .. node .. ':\n' .. item:xml () ) 
+				end,
+				function ( mesg )
+					main.print_info ( who, 'Retrieval failed: ' .. mesg )
+				end, args.m )
+		elseif action == 'create' or action == 'new' then
+			pubsub.create_node ( conn, who, node,
+				function ( node )
+					if node then
+						main.print_info ( who, 'Node ' .. node .. ' successfully created' )
+					else
+						main.print_info ( who, 'Node successfully created' )
+					end
+				end,
+				function ( mesg )
+					main.print_info ( who, 'Creation failed: ' .. mesg )
+				end )
+		elseif action == 'delete' or action == 'del' then
+			pubsub.delete_node ( conn, who, node,
+				function ()
+					main.print_info ( who, 'Node deleted' )
+				end,
+				function ( mesg )
+					main.print_info ( who, 'Node deletion failed: ' .. mesg )
+				end )
+		elseif action == 'purge' or action == 'del_items' then
+			pubsub.purge_node ( conn, who, node,
+				function ()
+					main.print_info ( who, 'Node purged' )
+				end,
+				function ( mesg )
+					main.print_info ( who, 'Node purge failed: ' .. mesg )
+				end )
+		elseif action:sub ( 1, 4 ) == 'conf' then
+			pubsub.configure_node ( conn, who, node,
+				function ()
+					main.print_info ( who, 'Node configuration accepted' )
+				end,
+				function ( mesg )
+					main.print_info ( who, 'Node configuration failed: ' .. mesg )
+				end )
+		elseif action == 'subscriptions' or action == 'subscribers' then
+			pubsub.list_subscriptions ( conn, who, node,
+				function ( s )
+					local text = ''
+					for i, v in ipairs ( s ) do
+						local subid = v.subid
+						if subid then
+							subid = '(id ' .. subid .. ')'
+						else
+							subid = ''
+						end
+						text = text .. ('\n- [%s] %s %s'):format ( v.subscription, v.jid, subid )
+					end
+					if text ~= '' then
+						main.print_info ( who, 'Node subscriptions:' .. text )
+					else
+						main.print_info ( who, 'No subscriptions' )
+					end
+				end,
+				function ( mesg )
+					main.print_info ( who, 'Node subscriptions retrieval failed: ' .. mesg )
+				end )
+		elseif action == 'subscription' or action == 'modify' then -- XXX
+			pubsub.modify_subscription ( conn, args.t or main.current_buddy (), node, args[3], args[4],
+				function ()
+					main.print_info ( who, 'Subscription modified' )
+				end,
+				function ( mesg )
+					main.print_info ( who, 'Subsrciption modification failed: ' .. mesg )
+				end, args[5] )
+		else
+			print ( 'Error: unknown action' )
+		end
+	end, true )
+
+-- FIXME
+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?)"
+--[[
+commands_help['subscribe']      = "[-t jid] node_name\n\nSends pubsub subscription request to specified node of jid or current buddy."
+commands_help['unsubscribe']    = "[-t jid] node_name\n\nSends pubsub unsubscription request to specified node of jid or current buddy."
+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."
+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."
+commands_help['configure_node'] = "[-t jid] node_name\n\nSends pubsub node configuration request to specified node of jid or current buddy."
+commands_help['delete_node']    = "[-t jid] node_name\n\nSends pubsub node deletion request to specified node of jid or current buddy."
+commands_help['purge_node']     = "[-t jid] node_name\n\nSends pubsub node items purging request to specified node of jid or current buddy."
+commands_help['subscriptions']  = "[-t jid] node_name\n\nSends pubsub subscription list request to specified node of jid or current buddy."
+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."
+--]]
+
+-- vim: se ts=4: --