examples/lm/pubsub.lua
author Myhailo Danylenko <isbear@ukrpost.net>
Tue, 31 Mar 2009 18:35:34 +0300
changeset 68 742878c74b8e
permissions -rw-r--r--
Lm separation, privacy * Library parts moved to lm.* * mc_* renamed to plain names * Privacy lists suppart (not tested)


-- PUBLISH-SUBSCRIBE (BEP-0060)

-- library

local iq     = require 'lm.iq'
local x_data = require 'lm.x_data'

--

local O = {
	handlers = { },
}

local F = { }

function F.handler ( xmlns, handler )
	O.handlers[xmlns] = handler
end

function F.message_handler ( conn, mess )
	local e = mess:child ( 'event' )
	if e and e:attribute ( 'xmlns' ) == 'http://jabber.org/protocol/pubsub#event' then
		local is = e:child ( 'items' )
		if is then
			local from = mess:attribute ( 'from' )
			local node = is:attribute ( 'node' )
			local item = is:child ()
			while item do
				local id = item:attribute ( 'id' )
				local n  = item:child ()
				while n do
					local xmlns = n:attribute ( 'xmlns' )
					if O.handlers[xmlns] then
						O.handlers[xmlns] ( from, node, n, id )
					end
					n = n:next ()
				end
				item = item:next ()
			end
			return true
		end
	end
	return false
end

-- SUBSCRIBER USE CASES

function F.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 F.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 F.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:child ()
				while item do
					success ( from, node, item ) -- XXX use registered xmlns handlers for that?
					item = item:next ()
				end
			else
				-- XXX
			end
		end, fail )
end

-- OWNER USE CASES

-- node may be nil
function F.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 F.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 F.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 F.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 )
			local x = mess:path ( 'pubsub', 'configure', 'x' )
			if x then
				success ( x_data.parse ( x ),
					function ( form, success, fail )
						iq.send ( conn, to, 'set',
							{
								pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner',
									configure = form:format ( { node = node }, 'submit' ),
								},
							}, success, fail )
					end,
					function ( form, success, fail )
						iq.send ( conn, to, 'set',
							{
								pubsub = { xmlns = 'http://jabber.org/protocol/pubsub#owner',
									configure = form:format ( { node = node }, 'cancel' ),
								},
							}, success, fail )
					end )
			else
				fail ( mess:xml () ) -- XXX
			end
		end, fail )
end

function F.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:child ()
				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 F.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

return F

-- vim: se ts=4: --