Hooks unification
authorMyhailo Danylenko <isbear@ukrpost.net>
Tue, 24 Feb 2009 09:14:00 +0200
changeset 6 90dceae3ed1f
parent 5 cba039bd6f13
child 7 eb6d89bf1fbf
Hooks unification * hook naming scheme unification * one handler for all * handler name from option * multiple transports * dopath returns error message
CMakeLists.txt
TODO
config.h.in
examples/lua.rc
examples/mcabberrc.lua
main.c
--- a/CMakeLists.txt	Mon Feb 23 23:23:42 2009 +0200
+++ b/CMakeLists.txt	Tue Feb 24 09:14:00 2009 +0200
@@ -6,7 +6,6 @@
 option(DEBUG "Enable debugging output" ON)
 option(LLM_LOG_HANDLER "Enable registration of log messages handler for lua-loudmouth library's messages" ON)
 set(MCABBER_INCLUDE_DIR "/home/isbear/src/mcabber/hglm/mcabber/src" CACHE FILEPATH "Path to mcabber headers")
-set(LUA_HOOK_NAME "hook_handler" CACHE STRING "Lua function name to be called on hook invocation")
 
 ## Define targets
 add_library(mcabber-lua MODULE main.c util.c)
--- a/TODO	Mon Feb 23 23:23:42 2009 +0200
+++ b/TODO	Tue Feb 24 09:14:00 2009 +0200
@@ -5,4 +5,5 @@
 non-setting settings?
 set package searching paths?
 do uninitialization of commands and features with objects?
+debug module reloading issue
 
--- a/config.h.in	Mon Feb 23 23:23:42 2009 +0200
+++ b/config.h.in	Tue Feb 24 09:14:00 2009 +0200
@@ -8,9 +8,6 @@
 // define this to enable lua-loudmouth log messages handler
 #cmakedefine LLM_LOG_HANDLER
 
-// define this to a lua function name that will handle hooks
-#define LUA_HOOK_NAME ( "${LUA_HOOK_NAME}" )
-
 // hack for mcabber headers
 #define MODULES_ENABLE
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/lua.rc	Tue Feb 24 09:14:00 2009 +0200
@@ -0,0 +1,5 @@
+
+# lua function name to be called on hooks invocation
+set lua_hook_function = hook_handler
+load mcabber-lua
+
--- a/examples/mcabberrc.lua	Mon Feb 23 23:23:42 2009 +0200
+++ b/examples/mcabberrc.lua	Tue Feb 24 09:14:00 2009 +0200
@@ -69,9 +69,9 @@
 
 -- OPTIONS, COMMON SUPPORT ROUTINES
 
-url_file      = main.config_file ( 'urls.log' )
-transport_jid = 'icq.jabber.kiev.ua' -- TODO: allow multiple transports
-beep_enable   = false
+url_file       = main.config_file ( 'urls.log' )
+transport_jids = { 'icq.jabber.kiev.ua', 'mrim.unixzone.org.ua' }
+beep_enable    = false
 
 -- XXX: to C?
 char2status = {
@@ -135,7 +135,18 @@
 	end
 end
 
--- COMMANDS
+function online ( jid )
+	local info = main.buddy_info ( jid )
+	if not info then
+		return false
+	end
+	for resource, params in pairs ( info.resources ) do
+		if params.status ~= '_' then
+			return true
+		end
+	end
+	return false
+end
 
 function yesno ( value )
 	if value == 'enable' or value == 'yes' or value == 'true' or value == 'on' or value == true then
@@ -168,6 +179,8 @@
 	return ret
 end
 
+-- COMMANDS
+
 -- Help strings should not contain command, only arguments. This is necessary to support soft aliases.
 commands_help = {
 	file      = "filename\n\nSends file as a message. Just shorthand.",
@@ -289,7 +302,6 @@
 
 delayed_jobs = {}
 
--- FIXME: do only if it exists
 dopath 'jobs.lua'
 
 function save_jobs ()
@@ -353,55 +365,31 @@
 
 ibb_handler_registered = false
 
--- Soft hooks, implemented through mcabber options
-function hook_post_connect ()
-	main.run ( 'group fold テフノ' )
-	main.run ( 'group fold にゃ' )
-	main.run ( 'group fold にゃ - Друзі' )
-
-	main.run ( 'color muc * on' )
-
-	main.run ( ("color roster * *@%s red"):format ( transport_jid ) )
-	main.run ( ("color roster dn_? *@%s red"):format ( transport_jid ) )
-
-	if mpd_enabled then
-		mpd_callback ()
-	end
-
-	-- FIXME
-	if not ibb_handler_registered then
-		lm.connection.bless( main.connection () ):handler ( ibb_incoming_iq_handler, 'iq', 'normal' )
-		main.add_feature ( 'http://jabber.org/protocol/ibb' )
-		ibb_handler_registered = true
-	end
-end
-
-function hook_pre_disconnect ()
-	main.run ( ("color roster * *@%s white"):format ( transport_jid ) )
-	main.run ( ("color roster dn_? *@%s brightblack"):format ( transport_jid ) )
-end
-
 -- Hard hooks, implemented in C
 
--- hook
--- - message_in
+-- hook:
+-- - hook-message-in
 --   jid
 --   groupchat
 --   message
--- - message_out
+-- - hook-message-out
 --   jid
 --   message
--- - status_change
+-- - hook-status-change
 --   jid
 --   resource
 --   new_status
 --   old_status
 --   message
--- - my_status_change
+-- - hook-my-status-change
 --   new_status
 --   message
+-- - hook-post-connect
+-- - hook-pre-disconnect
+-- - hook-start
+-- - hook-quit
 function hook_handler ( args )
-	if args.hook == 'message_in' then
+	if args.hook == 'hook-message-in' then
 
 		-- beep on ALL messages, no matter, is it chat or something else.
 		if beep_enable then
@@ -419,7 +407,7 @@
 			end
 		end
 
-	elseif args.hook == 'status_change' then
+	elseif args.hook == 'hook-status-change' then
 
 		-- delayed actions
 		if delayed_jobs[args.jid] and delayed_jobs[args.jid][args.new_status] then
@@ -428,29 +416,55 @@
 		end
 		
 		-- transported buddies availability indication
-		if args.jid == transport_jid then
-			if args.new_status == '_' then
-				main.run ( ("color roster * *@%s red"):format ( transport_jid ) )
-				main.run ( ("color roster dn_? *@%s red"):format ( transport_jid ) )
+		for k, jid in pairs ( transport_jids ) do
+			if args.jid == jid then
+				if args.new_status == '_' then
+					main.run ( ("color roster * *@%s red"):format ( jid ) )
+					main.run ( ("color roster dn_? *@%s red"):format ( jid ) )
+				else
+					main.run ( ("color roster * *@%s white"):format ( jid ) )
+					main.run ( ("color roster dn_? *@%s brightblack"):format ( jid ) )
+				end
+			end
+		end
+
+	elseif args.hook == 'hook-post-connect' then
+	
+		if mpd_enabled then
+			mpd_callback ()
+		end
+	
+		-- FIXME
+		if not ibb_handler_registered then
+			lm.connection.bless( main.connection () ):handler ( ibb_incoming_iq_handler, 'iq', 'normal' )
+			main.add_feature ( 'http://jabber.org/protocol/ibb' )
+			ibb_handler_registered = true
+		end
+
+	elseif args.hook == 'hook-start' then
+
+		-- XXX: for some reason, after module reloading, this is not working properly.
+		for k, jid in pairs ( transport_jids ) do
+			if not online ( jid ) then
+				main.run ( ("color roster * *@%s red"):format ( jid ) )
+				main.run ( ("color roster dn_? *@%s red"):format ( jid ) )
 			else
-				main.run ( ("color roster * *@%s white"):format ( transport_jid ) )
-				main.run ( ("color roster dn_? *@%s brightblack"):format ( transport_jid ) )
+				main.run ( ("color roster * *@%s white"):format ( jid ) )
+				main.run ( ("color roster dn_? *@%s brightblack"):format ( jid ) )
 			end
 		end
 
+	elseif args.hook == 'hook-quit' then
+
+		save_jobs ()
+
+		-- FIXME
+		if ibb_handler_registered then
+			lm.connection.bless( main.connection () ):handler ( ibb_incoming_iq_handler, 'iq' )
+		end
+
 	end
 end
 
--- (hook_start)
-
-function hook_quit ()
-	save_jobs ()
-
-	-- FIXME
-	if ibb_handler_registered then
-		lm.connection.bless( main.connection () ):handler ( ibb_incoming_iq_handler, 'iq' )
-	end
-end
-
 
 -- The End -- vim: se ts=4: --
--- a/main.c	Mon Feb 23 23:23:42 2009 +0200
+++ b/main.c	Tue Feb 24 09:14:00 2009 +0200
@@ -46,11 +46,13 @@
 /// dopath
 /// Loads lua file from default location.
 /// A: string (filename, without ".lua")
+/// R: string (error message, optional)
 static int lua_global_dopath (lua_State *L)
 {
 	const char *name = luaL_checkstring (L, 1);
 	size_t      size = lua_objlen (L, 1);
 	char       *path;
+	int         ret = 0;
 	if (!strncmp (name + size - 4, ".lua", 4))
 		path = mcabber_config_filename (name);
 	else {
@@ -59,13 +61,16 @@
 		g_free (fname);
 	}
 
-	if (luaL_loadfile (L, path))
+	if (ret = luaL_loadfile (L, path))
 		scr_LogPrint (LPRINT_LOGNORM, "lua: Unable to compile file %s: %s", path, lua_tostring (L, -1));
-	else if (lua_pcall (lua, 0, LUA_MULTRET, 0))
+	else if (ret = lua_pcall (lua, 0, LUA_MULTRET, 0))
 		scr_LogPrint(LPRINT_LOGNORM, "lua: Runtime error in file %s: %s", path, lua_tostring (L, -1));
+	g_free (path);
 
-	g_free (path);
-	return 0;
+	if (ret)
+		return 1;
+	else
+		return 0;
 }
 
 /// main.config_file
@@ -533,14 +538,13 @@
 }
 #endif
 
-#ifndef LUA_HOOK_NAME
-#define LUA_HOOK_NAME ( "hook_handler" )
-#endif
-
 static void lua_hook (hk_arg_t *args, lua_State *L)
 {
 	hk_arg_t *arg = args;
-	lua_getglobal (lua, LUA_HOOK_NAME);
+	const char *hook = settings_opt_get ("lua_hook_function");
+	if (!hook)
+		return;
+	lua_getglobal (lua, hook);
 	if (!lua_isfunction (lua, -1)) {
 		lua_pop (lua, 1);
 		return;
@@ -553,7 +557,7 @@
 		arg++;
 	}
 	if (lua_pcall (lua, 1, 0, 0)) {
-		scr_LogPrint (LPRINT_NORMAL, "lua: Error in hook_handler: %s", lua_tostring (lua, -1));
+		scr_LogPrint (LPRINT_NORMAL, "lua: Error in hook handler: %s", lua_tostring (lua, -1));
 		lua_pop (lua, 1);
 	}
 }
@@ -626,13 +630,14 @@
 
 	hk_add_handler ((hk_handler_t) lua_hook, lua);
 
-	lua_getglobal (lua, "hook_start");
-	if (!lua_isfunction (lua, -1))
-		lua_pop (lua, 1);
-	else if (lua_pcall (lua, 0, 0, 0)) {
-		scr_LogPrint (LPRINT_NORMAL, "lua: Error in hook_start: %s", lua_tostring (lua, -1));
-		lua_pop (lua, 1);
+	{
+		hk_arg_t args[] = {
+			{ "hook", "hook-start" },
+			{ NULL,   NULL         },
+		};
+		lua_hook (args, lua);
 	}
+
 	return NULL;
 }
 
@@ -655,13 +660,11 @@
 void g_module_unload (GModule *module)
 {
 	if (lua) {
-		lua_getglobal (lua, "hook_quit");
-		if (!lua_isfunction (lua, -1))
-			lua_pop (lua, 1);
-		else if (lua_pcall (lua, 0, 0, 0)) {
-			scr_LogPrint (LPRINT_NORMAL, "lua: Error in hook_quit: %s", lua_tostring (lua, -1));
-			lua_pop (lua, 1);
-		}
+		hk_arg_t args[] = {
+			{ "hook", "hook-quit" },
+			{ NULL,   NULL        },
+		};
+		lua_hook (args, lua);
 
 		hk_del_handler ((hk_handler_t) lua_hook, lua);