Pep splitting
authorMyhailo Danylenko <isbear@ukrpost.net>
Mon, 23 Mar 2009 04:16:22 +0200
changeset 59 4660c4f10ef1
parent 58 aa3376776cf2
child 60 b9fd051c0d7c
Pep splitting
examples/activity.lua
examples/geoloc.lua
examples/mcabberrc.lua
examples/mood.lua
examples/pep.lua
examples/tune.lua
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/activity.lua	Mon Mar 23 04:16:22 2009 +0200
@@ -0,0 +1,79 @@
+
+-- USER ACTIVITY (XEP-0108)
+
+-- library
+
+require 'lm'
+require 'pep'
+
+-- public
+
+activity = { }
+
+function activity.publish ( conn, success, fail, general, specific, message )
+	local item = { xmlns = 'http://jabber.org/protocol/activity' }
+	if general then
+		item[general] = { }
+		if specific then
+			item[general][specific] = { }
+		end
+	end
+	if message then
+		item.text = { message }
+	end
+	pep.publish ( conn, 'http://jabber.org/protocol/activity', { activity = item }, success, fail )
+end
+
+-- mcabber
+
+pep.handlers['http://jabber.org/protocol/activity'] =
+	function ( from, node, data )
+		if not main.yesno ( main.option ( 'lua_pep_notification' ) ) then
+			return true
+		end
+		local item = data:children ()
+		local activity, desc
+		while item do
+			if item:name () == 'text' then
+				desc = item:value ()
+			else
+				activity = item:name ()
+				local subitem = item:children ()
+				if subitem then
+					-- here we can check for non-standard subactivity elements,
+					-- add subactivity child elements handling
+					activity = ("%s: %s"):format ( activity, subitem:name () )
+				end
+			end
+			item = item:next ()
+		end
+		if activity then
+			main.print_info ( from, ("Now %s %s"):format ( activity, desc or '' ) )
+		else
+			main.print_info ( from, "Buddy hides his activity" )
+		end
+		return true
+	end
+
+main.command ( 'activity',
+	function ( args )
+		local activity, text = args[1], args[2]
+		local act, subact = activity:match ( "(.-)%-(.+)" )
+		if not act then
+			act = activity
+		end
+		activity.publish ( lm.connection.bless ( main.connection () ),
+			function ()
+				print ( 'Activity published' )
+			end,
+			function ( mesg )
+				print ( 'Error publishing activity: ' .. mesg )
+			end, act, subact, text )
+	end, true )
+
+commands_help['activity'] = "[activity[-specific_activity] [text]]\n\nPublishes your activity.\nNote, that for now it does not checks for activity validity, so, see xep0108 for valid activity values."
+
+main.add_feature ( 'http://jabber.org/protocol/activity+notify' )
+main.add_feature ( 'http://jabber.org/protocol/activity' )
+
+-- vim: se ts=4: --
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/geoloc.lua	Mon Mar 23 04:16:22 2009 +0200
@@ -0,0 +1,61 @@
+
+-- USER LOCATION (XEP-0080)
+
+-- library
+
+require 'lm'
+require 'pep'
+
+-- public
+
+geoloc = { }
+
+function geoloc.publish ( conn, success, fail, data )
+	local sdata = { xmlns = 'http://jabber.org/protocol/geoloc' }
+	if data then
+		for key, value in pairs ( data ) do
+			sdata[key] = { value }
+		end
+	end
+	pep.publish ( conn, 'http://jabber.org/protocol/geoloc', { geoloc = sdata }, success, fail )
+end
+
+-- mcabber
+
+pep.handlers['http://jabber.org/protocol/geoloc'] =
+	function ( from, node, data )
+		if not main.yesno ( main.option ( 'lua_pep_notification' ) ) then
+			return true
+		end
+		local item = data:children ()
+		local text = ''
+		while item do
+			text = ("%s\n- %s: %s"):format ( text, item:name (), item:value () or '' )
+			item = item:next ()
+		end
+		if text ~= '' then
+			text = 'Now at:' .. text
+		else
+			text = 'Now in unknown location'
+		end
+		main.print_info ( from, text )
+		return true
+	end
+
+main.command ( 'location',
+	function ( args )
+		geoloc.publish ( lm.connection.bless ( main.connection () ),
+			function ()
+				print ( 'Geolocation published' )
+			end,
+			function ( mesg )
+				print ( 'Error geolocation publishing: ' .. mesg )
+			end, args )
+	end, true )
+
+commands_help['location'] = "[-key value [-key value ...]]\n\nPublishes your current geolocation.\nValid keys are accuracy, alt, area, bearing, building, country, datum, description, error, floor, lat, locality, lon, postalcode, region, room, speed, street, text, timestamp and uri, according to xep0080."
+
+main.add_feature ( 'http://jabber.org/protocol/geoloc+notify' )
+main.add_feature ( 'http://jabber.org/protocol/geoloc' )
+
+-- vim: se ts=4: --
--- a/examples/mcabberrc.lua	Mon Mar 23 02:05:26 2009 +0200
+++ b/examples/mcabberrc.lua	Mon Mar 23 04:16:22 2009 +0200
@@ -279,10 +279,26 @@
 
 require 'iq_register'
 
+-- USER LOCATION (XEP-0080)
+
+require 'geoloc'
+
 -- USER AVATAR (XEP-0084)
 
 require 'avatar'
 
+-- USER MOOD (XEP-0107)
+
+require 'mood'
+
+-- USER ACTIVITY (XEP-0108)
+
+require 'activity'
+
+-- USER TUNE (XEP-0118)
+
+require 'tune'
+
 -- REMOTE CONTROLLING CLIENTS (XEP-0146)
 
 require 'remote'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/mood.lua	Mon Mar 23 04:16:22 2009 +0200
@@ -0,0 +1,65 @@
+
+-- USER MOOD (XEP-0107)
+
+-- library
+
+require 'lm'
+require 'pep'
+
+-- public
+
+mood = { }
+
+function mood.publish ( conn, success, fail, mood, message )
+	local item = { xmlns = 'http://jabber.org/protocol/mood' }
+	if mood then
+		item[mood] = { }
+	end
+	if message then
+		item.text = { message }
+	end
+	pep.publish ( conn, 'http://jabber.org/protocol/mood', { mood = item }, success, fail )
+end
+
+-- mcabber
+
+pep.handlers['http://jabber.org/protocol/mood'] =
+	function ( from, node, data )
+		if not main.yesno ( main.option ( 'lua_pep_notification' ) ) then
+			return true
+		end
+		local item = data:children ()
+		local mood, desc
+		while item do
+			if item:name () == 'text' then
+				desc = item:value ()
+			else
+				mood = item:name ()
+				-- here we can add child elements handling (by namespace)
+			end
+			item = item:next ()
+		end
+		if mood then
+			main.print_info ( from, ("Buddy's mood now %s %s"):format ( mood, desc or '' ) )
+		else
+			main.print_info ( from, "Buddy hides his mood" )
+		end
+	end
+
+main.command ( 'mood',
+	function ( args )
+		mood.publish ( lm.connection.bless ( main.connection () ),
+			function ()
+				print ( 'Mood published' )
+			end,
+			function ( mesg )
+				print ( 'Error publishing mood: ' .. mesg )
+			end, args[1], args[2] )
+	end, true )
+
+commands_help['mood'] = "[mood [message]]\n\nPublishes your mood.\nNote, that for now it does not checks for mood validity, so, see xep0107 for valid moods."
+
+main.add_feature ( 'http://jabber.org/protocol/mood+notify' )
+main.add_feature ( 'http://jabber.org/protocol/mood' )
+
+-- vim: se ts=4: --
--- a/examples/pep.lua	Mon Mar 23 02:05:26 2009 +0200
+++ b/examples/pep.lua	Mon Mar 23 04:16:22 2009 +0200
@@ -5,7 +5,6 @@
 
 require 'lm'
 require 'iq'
-require 'mpd'
 
 -- public
 
@@ -41,7 +40,6 @@
 
 -- XXX in fact, it is not a pep handler, it is pubsub handler.
 --     should it go there?
-local pep_handler_registered       = false
 local pep_incoming_message_handler = lm.message_handler.new (
 	function ( conn, mess )
 		local e = mess:child ( 'event' )
@@ -74,264 +72,13 @@
 
 -- mcabber
 
-local tune_enabled = false
-local mpd_pub_song = { }
-
--- XXX in fact, we should separate library code from client code here, but it is silly.
---     seting up four registrators, four default handlers, four handler storage variables...
---     and, in fact, we cannot do much about complex datatypes of mood and activity.
-pep.handlers['http://jabber.org/protocol/tune'] =
-		function ( from, node, data )
-			local self = false
-			if from == lm.connection.bless ( main.connection () ):jid():gsub ( '/.*', '' ) then -- o_O
-				self         = true
-				mpd_pub_song = { }
-			end
-			local item = data:children ()
-			local text = ''
-			while item do
-				local name  = item:name ()
-				local value = item:value ()
-				if self then
-					mpd_pub_song[name] = { value or '' }
-				end
-				text = ("%s\n- %s: %s"):format ( text, item:name (), item:value () or '' )
-				item = item:next ()
-			end
-			if main.yesno ( main.option ( 'lua_pep_notification' ) ) then
-				if text ~= '' then
-					text = 'Now listening to:' .. text
-				else
-					text = 'Now not listening to anything'
-				end
-			end
-			main.print_info ( from, text )
-			return true
-		end
-pep.handlers['http://jabber.org/protocol/mood'] =
-		function ( from, node, data )
-			if not main.yesno ( main.option ( 'lua_pep_notification' ) ) then
-				return true
-			end
-			local item = data:children ()
-			local mood, desc
-			while item do
-				if item:name () == 'text' then
-					desc = item:value ()
-				else
-					mood = item:name ()
-					-- here we can add child elements handling (by namespace)
-				end
-				item = item:next ()
-			end
-			if mood then
-				main.print_info ( from, ("Buddy's mood now %s %s"):format ( mood, desc or '' ) )
-			else
-				main.print_info ( from, "Buddy hides his mood" )
-			end
-		end
-pep.handlers['http://jabber.org/protocol/activity'] =
-		function ( from, node, data )
-			if not main.yesno ( main.option ( 'lua_pep_notification' ) ) then
-				return true
-			end
-			local item = data:children ()
-			local activity, desc
-			while item do
-				if item:name () == 'text' then
-					desc = item:value ()
-				else
-					activity = item:name ()
-					local subitem = item:children ()
-					if subitem then
-						-- here we can check for non-standard subactivity elements,
-						-- add subactivity child elements handling
-						activity = ("%s: %s"):format ( activity, subitem:name () )
-					end
-				end
-				item = item:next ()
-			end
-			if activity then
-				main.print_info ( from, ("Now %s %s"):format ( activity, desc or '' ) )
-			else
-				main.print_info ( from, "Buddy hides his activity" )
-			end
-			return true
-		end
-pep.handlers['http://jabber.org/protocol/geoloc'] =
-		function ( from, node, data )
-			if not main.yesno ( main.option ( 'lua_pep_notification' ) ) then
-				return true
-			end
-			local item = data:children ()
-			local text = ''
-			while item do
-				text = ("%s\n- %s: %s"):format ( text, item:name (), item:value () or '' )
-				item = item:next ()
-			end
-			if text ~= '' then
-				text = 'Now at:' .. text
-			else
-				text = 'Now in unknown location'
-			end
-			main.print_info ( from, text )
-			return true
-		end
-
-local function mpd_getstatus ()
-	local status = mpd.call_command { 'status' }
-	if not tune_enabled or ( status.state ~= 'play' and status.state ~= 'pause' ) then
-		for k, v in pairs ( mpd_pub_song ) do -- if there is anything published, publish nothing
-			return { }
-		end
-		return nil
-	end
-	
-	local song      = mpd.call_command { 'currentsong' }
-	local dir, file = song.file:match ( '(.+)/(.-)' )
-	-- populate according to currentsong fields: artist - artist, length - time, source - album, title - title, track - id, rating - ?, uri - ?
-	local ret = {
-		artist = { song.artist or 'Unknown' },
-		length = { song.time                },
-		source = { song.album  or dir       },
-		title  = { song.title  or file      },
-		track  = { song.id                  },
-	}
-
-	if not song.time or song.time == '0' then -- XXX
-		ret.length = nil
-	end
-
-	local modified = false
-	for k, v in pairs ( ret ) do
-		if not mpd_pub_song[k] or mpd_pub_song[k][1] ~= v[1] then
-			modified = true
-			break
-		end
-	end
-	if not modified then
-		for k, v in pairs ( mpd_pub_song ) do
-			if not ret[k] or ret[k][1] ~= v[1] then
-				modified = true
-				break
-			end
-		end
-	end
-
-	if modified then
-		return ret
-	else
-		return nil
-	end
-end
-
-local function dummy ()
-end
-
-local function mpd_callback ()
-	local sdata = mpd_getstatus ()
-	if sdata then
-		sdata.xmlns = 'http://jabber.org/protocol/tune'
-		pep.publish ( lm.connection.bless ( main.connection () ), 'http://jabber.org/protocol/tune', { tune = sdata }, dummy, dummy )
-	end
-	if tune_enabled then
-		return true
-	else
-		return false
-	end
-end
-
--- do not call it too fast, or you end up with many daemons at once
-local function enable_tune ( yn )
-	if yn == nil then
-		yn = true
-	end
-	if yn then
-		if not tune_enabled then
-			main.timer ( 15, mpd_callback )
-			tune_enabled = true
-			-- update status
-		end
-	else
-		if tune_enabled then
-			tune_enabled = false
-			-- update status
-		end
-	end
-end
-
-main.command ( 'tune',
-	function ( args )
-		local enable = main.yesno ( args )
-		if enable == nil then
-			if tune_enabled then
-				print ( "Tune notifications enabled" )
-			else
-				print ( "Tune notifications disabled" )
-			end
-		else
-			enable_tune ( enable )
-		end
-	end, false, 'yesno' )
-main.command ( 'mood',
-	function ( args )
-		local data = { xmlns = 'http://jabber.org/protocol/mood' }
-		local mood, text = args[1], args[2]
-		if text then
-			data.text  = { text }
-		end
-		if mood then
-			data[mood] = { }
-		end
-		pep.publish ( lm.connection.bless ( main.connection () ), 'http://jabber.org/protocol/mood', { mood = data }, dummy, dummy )
-	end, true )
-main.command ( 'activity',
-	function ( args )
-		local data = { xmlns = 'http://jabber.org/protocol/activity' }
-		local activity, text = args[1], args[2]
-		if text then
-			data.text = { text }
-		end
-		local act, subact = activity:match ( "(.-)%-(.+)" )
-		if not act then
-			act = activity
-		end
-		if act ~= '' then
-			data[act] = { }
-			if subact then
-				data[act][subact] = { }
-			end
-		end
-		pep.publish ( lm.connection.bless ( main.connection () ), 'http://jabber.org/protocol/activity', { activity = data }, dummy, dummy )
-	end, true )
-main.command ( 'location',
-	function ( args )
-		local data = { xmlns = 'http://jabber.org/protocol/geoloc' }
-		for key, val in pairs ( args ) do
-			data[key] = { val }
-		end
-		pep.publish ( lm.connection.bless ( main.connection () ), 'http://jabber.org/protocol/geoloc', { geoloc = data }, dummy, dummy )
-	end, true )
-
-commands_help['tune']     = "[enable|disable|on|off|yes|no|true|false]\n\nEnables or disables publishing of notifications about playing music in your player (currently only mpd is supported)."
-commands_help['mood']     = "[mood [message]]\n\nPublishes your mood.\nNote, that for now it does not checks for mood validity, so, see xep0107 for valid moods."
-commands_help['activity'] = "[activity[-specific_activity] [text]]\n\nPublishes your activity.\nNote, that for now it does not checks for activity validity, so, see xep0108 for valid activity values."
-commands_help['location'] = "[-key value [-key value ...]]\n\nPublishes your current geolocation.\nValid keys are accuracy, alt, area, bearing, building, country, datum, description, error, floor, lat, locality, lon, postalcode, region, room, speed, street, text, timestamp and uri, according to xep0080."
+local pep_handler_registered = false
 
 hooks_d['hook-post-connect'].pep =
 	function ( args )
 		lm.connection.bless( main.connection () ):handler ( pep_incoming_message_handler, 'message', 'normal' )
 		pep_handler_registered = true
-		if tune_enabled then
-			mpd_callback ()
-		end
-		-- XXX may it confuse pairs()?
-		hooks_d['hook-post-connect'].pep =
-			function ( args )
-				if tune_enabled then
-					mpd_callback ()
-				end
-			end
+		hooks_d['hook-post-connect'].pep = nil
 		hooks_d['hook-quit'].pep =
 			function ( args )
 				if pep_handler_registered then
@@ -341,16 +88,4 @@
 			end
 	end
 
--- XXX this really should be initialized after connection establishment (?)
---     but as this thing is implemented by now, it will be cached by server,
---     and, thus, we will be unable to get notifications.
-main.add_feature ( 'http://jabber.org/protocol/tune+notify' )
-main.add_feature ( 'http://jabber.org/protocol/tune' )
-main.add_feature ( 'http://jabber.org/protocol/mood+notify' )
-main.add_feature ( 'http://jabber.org/protocol/mood' )
-main.add_feature ( 'http://jabber.org/protocol/activity+notify' )
-main.add_feature ( 'http://jabber.org/protocol/activity' )
-main.add_feature ( 'http://jabber.org/protocol/geoloc+notify' )
-main.add_feature ( 'http://jabber.org/protocol/geoloc' )
-
 -- vim: se ts=4: --
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/tune.lua	Mon Mar 23 04:16:22 2009 +0200
@@ -0,0 +1,167 @@
+
+-- USER TUNE (XEP-0118)
+
+-- library
+
+require 'lm'
+require 'pep'
+require 'mpd'
+
+-- public
+
+tune = { }
+
+function tune.publish ( conn, node, success, fail, data )
+	local item = { xmlns = 'http://jabber.org/protocol/tune' }
+	if data then
+		for key, value in pairs ( data ) do
+			item[key] = { value }
+		end
+	end
+	pep.publish ( conn, 'http://jabber.org/protocol/tune', { tune = item }, success, fail )
+end
+
+-- mcabber
+
+local tune_enabled = false
+local mpd_pub_song = { }
+
+pep.handlers['http://jabber.org/protocol/tune'] =
+	function ( from, node, data )
+		local self = false
+		if from == lm.connection.bless ( main.connection () ):jid():gsub ( '/.*', '' ) then -- o_O
+			self         = true
+			mpd_pub_song = { }
+		end
+		local item = data:children ()
+		local text = ''
+		while item do
+			local name  = item:name ()
+			local value = item:value ()
+			if self then
+				mpd_pub_song[name] = value or ''
+			end
+			text = ("%s\n- %s: %s"):format ( text, item:name (), item:value () or '' )
+			item = item:next ()
+		end
+		if main.yesno ( main.option ( 'lua_pep_notification' ) ) then
+			if text ~= '' then
+				text = 'Now listening to:' .. text
+			else
+				text = 'Now not listening to anything'
+			end
+		end
+		main.print_info ( from, text )
+		return true
+	end
+
+local function mpd_getstatus ()
+	local status = mpd.call_command { 'status' }
+	if not tune_enabled or ( status.state ~= 'play' and status.state ~= 'pause' ) then
+		for k, v in pairs ( mpd_pub_song ) do -- if there is anything published, publish nothing
+			return { }
+		end
+		return nil
+	end
+	
+	local song      = mpd.call_command { 'currentsong' }
+	local dir, file = song.file:match ( '(.+)/(.-)' )
+	-- populate according to currentsong fields: artist - artist, length - time, source - album, title - title, track - id, rating - ?, uri - ?
+	local ret = {
+		artist = song.artist or 'Unknown',
+		length = song.time,
+		source = song.album  or dir,
+		title  = song.title  or file,
+		track  = song.id,
+	}
+
+	if not song.time or song.time == '0' then -- XXX
+		ret.length = nil
+	end
+
+	local modified = false
+	for k, v in pairs ( ret ) do
+		if mpd_pub_song[k] ~= v then
+			modified = true
+			break
+		end
+	end
+	if not modified then
+		for k, v in pairs ( mpd_pub_song ) do
+			if ret[k] ~= v then
+				modified = true
+				break
+			end
+		end
+	end
+
+	if modified then
+		return ret
+	else
+		return nil
+	end
+end
+
+local function mpd_callback ()
+	local sdata = mpd_getstatus ()
+	if sdata then
+		pep.publish ( lm.connection.bless ( main.connection () ), 'http://jabber.org/protocol/tune',
+			function ()
+			end,
+			function ( mesg )
+				print ( 'Error publishing tune: ' .. mesg )
+			end, sdata )
+	end
+	if tune_enabled then
+		return true
+	else
+		return false
+	end
+end
+
+-- do not call it too fast, or you end up with many daemons at once
+local function enable_tune ( yn )
+	if yn == nil then
+		yn = true
+	end
+	if yn then
+		if not tune_enabled then
+			main.timer ( 15, mpd_callback )
+			tune_enabled = true
+			-- update status
+		end
+	else
+		if tune_enabled then
+			tune_enabled = false
+			-- update status
+		end
+	end
+end
+
+main.command ( 'tune',
+	function ( args )
+		local enable = main.yesno ( args )
+		if enable == nil then
+			if tune_enabled then
+				print ( "Tune notifications enabled" )
+			else
+				print ( "Tune notifications disabled" )
+			end
+		else
+			enable_tune ( enable )
+		end
+	end, false, 'yesno' )
+
+commands_help['tune'] = "[enable|disable|on|off|yes|no|true|false]\n\nEnables or disables publishing of notifications about playing music in your player (currently only mpd is supported)."
+
+hooks_d['hook-post-connect'].tune =
+	function ( args )
+		if tune_enabled then
+			mpd_callback ()
+		end
+	end
+
+main.add_feature ( 'http://jabber.org/protocol/tune+notify' )
+main.add_feature ( 'http://jabber.org/protocol/tune' )
+
+-- vim: se ts=4: --