examples/xep0060.lua
author Myhailo Danylenko <isbear@ukrpost.net>
Sun, 15 Mar 2009 23:57:49 +0200
changeset 26 fc83934f9b8d
parent 25 38c68c285e41
child 27 92b254b64360
permissions -rw-r--r--
Pubsub interface merged into one command


-- SUBSCRIBER USE CASES

function pubsub_subscribe ( to, node )
	local conn = lm.connection.bless ( main.connection () )
	local jid = conn:jid():gsub ( '/.*', '' )
	conn:send (
		lm.message.create { mtype = 'iq-set', to = to, -- from = conn:jid (),
			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub',
				subscribe = { node = node, jid = jid },
			},
		},
		function ( conn, mess )
			local mtype, smtype = mess:type ()
			if smtype == 'result' then
				local s = mess:path ( 'pubsub', 'subscription' )
				local info
				if s then
					local id = s:attribute ( 'subid' )
					if not id then
						id = 'unspecified'
					end
					info = ('%s is now %s to node %s (id %s)'):format ( s:attribute ( 'jid' ), s:attribute ( 'subscription' ), s:attribute ( 'node' ), id )
				else
					info = 'Subscription successful, but server supplied no info about it...'
				end
				main.print_info ( to, info )
				return true
			elseif smtype == 'error' then
				main.print_info ( to, 'Error response for subscription request: ' .. mess:xml () ) -- FIXME
				-- XXX: handle configuration forms?
				return true
			else
				print ( 'Weird response for subscription request: ' .. mess:xml () )
				return false
			end
		end )
end

function pubsub_unsubscribe ( to, node )
	local conn = lm.connection.bless ( main.connection () )
	local jid = conn:jid():gsub ( '/.*', '' )
	conn:send (
		lm.message.create { mtype = 'iq-set', to = to,
			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub',
				unsubscribe = { node = node, jid = jid },
			},
		},
		function ( conn, mess )
			local mtype, smtype = mess:type ()
			if smtype == 'result' then
				main.print_info ( to, 'Unsubscription successful' )
				return true
			elseif smtype == 'error' then
				main.print_info ( to, 'Error response for unsubscription request: ' .. mess:xml () ) -- FIXME
				return true
			else
				print ( 'Weird response for unsubscription request: ' .. mess:xml () )
				return false
			end
		end )
end

-- I found no servers with subscription options support thus it is not implemented.

-- untested :(
function pubsub_retrieve ( to, node, handler, 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
	local conn = lm.connection.bless ( main.connection () )
	conn:send (
		lm.message.create { mtype = 'iq-set', to = to,
			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub',
				items = items,
			},
		},
		function ( conn, mess )
			local mtype, smtype = mess:type ()
			if smtype == 'result' then
				local items = mess:path ( 'pubsub', 'items' )
				if items then
					local item = items:children ()
					while item do
						-- we cannot know, what item contains
						handler ( item )
						item = item:next ()
					end
				end
				return true
			elseif smtype == 'error' then
				main.print_info ( to, 'Error response for items retrieval request: ' .. mess:xml () ) -- FIXME
				return true
			else
				print ( 'Weird response for items retrieval request: ' .. mess:xml () )
				return false
			end
		end )
end

-- OWNER USE CASES

-- node may be nil
function pubsub_create_node ( to, node )
	local conn = lm.connection.bless ( main.connection () )
	conn:send (
		lm.message.create { mtype = 'iq-set', to = to,
			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub',
				create = { node = node },
			},
		},
		function ( conn, mess )
			local mtype, smtype = mess:type ()
			if smtype == 'result' then
				if node then
					main.print_info ( to, 'Node ' .. node .. ' successfully created' )
				else
					local create = mess:path ( 'pubsub', 'create' )
					if create then
						local nid = create:attribute ( 'node' )
						main.print_info ( to, 'Node created, id ' .. (nid or 'unspecified') )
					else
						main.print_info ( to, 'Node created, but no id provieded' )
					end
				end
				return true
			elseif smtype == 'error' then
				main.print_info ( to, 'Error response for node creation request: ' .. mess:xml () ) -- FIXME
				return true
			else
				print ( 'Weird response for node creation request: ' .. mess:xml () )
				return false
			end
		end )
end

function pubsub_delete_node ( to, node )
	local conn = lm.connection.bless ( main.connection () )
	conn:send (
		lm.message.create { mtype = 'iq-set', to = to,
			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner',
				delete = { node = node },
			},
		},
		function ( conn, mess )
			local mtype, smtype = mess:type ()
			if smtype == 'result' then
				main.print_info ( to, 'Node ' .. node .. ' successfully deleted' )
				return true
			elseif smtype == 'error' then
				main.print_info ( to, 'Error response for node deletion request: ' .. mess:xml () ) -- FIXME
				return true
			else
				print ( 'Weird response for node deletion request: ' .. mess:xml () )
				return false
			end
		end )
end

function pubsub_purge_node ( to, node )
	local conn = lm.connection.bless ( main.connection () )
	conn:send (
		lm.message.create { mtype = 'iq-set', to = to,
			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner',
				purge = { node = node },
			},
		},
		function ( conn, mess )
			local mtype, smtype = mess:type ()
			if smtype == 'result' then
				main.print_info ( to, 'Node ' .. node .. ' items successfully purged' )
				return true
			elseif smtype == 'error' then
				main.print_info ( to, 'Error response for node items purging request: ' .. mess:xml () ) -- FIXME
				return true
			else
				print ( 'Weird response for node items purging request: ' .. mess:xml () )
				return false
			end
		end )
end

function pubsub_configure_node ( to, node )
	local conn = lm.connection.bless ( main.connection () )
	conn:send (
		lm.message.create { mtype = 'iq-get', to = to,
			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner',
				configure = { node = node },
			},
		},
		function ( conn, mess )
			local mtype, smtype = mess:type ()
			if smtype == 'result' then
				local x = mess:path ( 'pubsub', 'configure', 'x' )
				if x then
					local fid = parse_form ( x )
					forms[fid].send =
						function ( form )
							conn:send (
								lm.message.create { mtype = 'iq-set', to = to,
									pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner',
										configure = { node = node,
											x = { xmlns = 'jabber:x:data', type = 'submit',
												field = form.val,
											},
										},
									},
								},
								function ( conn, mess )
									local mt, st = mess:type ()
									if st == 'result' then
										main.print_info ( to, 'Now you can run /form del ' .. fid .. ' to delete form from list' )
										form.status = 'acquired'
									elseif st == 'error' then
										main.print_info ( to, 'Got non-successful response to form:\n' .. mess:xml () )
										form.status = 'rejected'
									else
										print ( 'Weird response to submitted form:\n' .. mess:xml () )
										form.status = 'unknown'
										return false
									end
									return true
								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
				return true
			elseif smtype == 'error' then
				main.print_info ( to, 'Error response for node configuration request: ' .. mess:xml () ) -- FIXME
				return true
			else
				print ( 'Weird response for node configuration request: ' .. mess:xml () )
				return false
			end
		end )
end

function pubsub_list_subscriptions ( to, node )
	local conn = lm.connection.bless ( main.connection () )
	conn:send (
		lm.message.create { mtype = 'iq-get', to = to,
			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner',
				subscriptions = { node = node },
			},
		},
		function ( conn, mess )
			local mtype, smtype = mess:type ()
			if smtype == 'result' then
				local s = mess:path ( 'pubsub', 'subscriptions' )
				if s then
					local sub = s:children ()
					main.print_info ( to, "List of subscriptions for node " .. node )
					while sub do
						local subid = sub:attribute ( 'subid' ) or 'unspecified'
						main.print_info ( to, ("%s is %s (id %s)"):format ( sub:attribute ( 'jid' ), sub:attribute ( 'subscription' ), subid ) )
						sub = sub:next ()
					end
				else
					main.print_info ( to, 'Weird response to node subscription list request: ' .. mess:xml () )
				end
				return true
			elseif smtype == 'error' then
				main.print_info ( to, 'Error response for node subscription list request: ' .. mess:xml () ) -- FIXME
				return true
			else
				print ( 'Weird response for node subscription list request: ' .. mess:xml () )
				return false
			end
		end )
end

function pubsub_modify_subscription ( to, node, who, state, id )
	local conn = lm.connection.bless ( main.connection () )
	conn:send (
		lm.message.create { mtype = 'iq-get', to = to,
			pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner',
				subscriptions = { node = node,
					subscription = { jid = who, subscription = state, id = id },
				},
			},
		},
		function ( conn, mess )
			local mtype, smtype = mess:type ()
			if smtype == 'result' then
				main.print_info ( to, ('Subscription of %s to %s is successfully set to %s (id %s)'):format ( who, node, state, id or 'unspecified' ) )
				return true
			elseif smtype == 'error' then
				main.print_info ( to, 'Error response for node subscription list request: ' .. mess:xml () ) -- FIXME
				return true
			else
				print ( 'Weird response for node subscription list request: ' .. mess:xml () )
				return false
			end
		end )
end

-- INTERFACE

main.command ( 'node',
	function ( args )
		args = parse_args ( args )
		local who, action, node = args.t, args[1], args[2]
		if not who then
			who = main.current_buddy ()
		end
		if action == 'subscribe' then
			pubsub_subscribe ( who, node )
		elseif action == 'unsubscribe' then
			pubsub_unsubscribe ( who, node )
		elseif action == 'retrieve' or action == 'items' or action == 'get' then
			pubsub_retrieve ( who, node,
				function ( item )
					main.print_to ( who, item:xml () ) 
				end, args.m )
		elseif action == 'create' or action == 'new' then
			pubsub_create_node ( who, node )
		elseif action == 'delete' or action == 'del' then
			pubsub_delete_node ( who, node )
		elseif action == 'purge' or action == 'del_items' then
			pubsub_purge_node ( who, node )
		elseif action:sub ( 1, 4 ) == 'conf' then
			pubsub_configure_node ( who, node )
		elseif action == 'subscriptions' or action == 'subscribers' then
			pubsub_list_subscriptions ( who, node )
		elseif action == 'subscription' or action == 'modify' then -- XXX
			pubsub_modify_subscription ( args.t or main.current_buddy (), node, args[3], args[4], args[5] )
		else
			print ( 'Error: unknown action' )
		end
	end )

-- 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: --