xchat lua plugin X-Chat 2.x LUA-API Introduction Download Installing Sample script Predefined constants Function reference * xchat.hook_command() * xchat.hook_server() * xchat.hook_print() * xchat.hook_timer() * xchat.unhook() * xchat.event() * xchat.command() * xchat.commandf() * xchat.print() * xchat.printf() * xchat.emit_print() * xchat.send_modes() * xchat.find_context() * xchat.get_context() * xchat.get_info() * xchat.get_prefs() * xchat.set_context() * xchat.nickcmp() * xchat.strip() * xchat.list_fields() * xchat.list_get() * xchat.gettext() * xchat.bits() Contact Introduction NOTE: the order of the arguments for xchat.hook_(server|print|command) changed in rev 80: These can now be written as xchat.hook_command(event, func_name), i.e. the priority is now optional and defaults to xchat.PRI_NORM... or the full form: xchat.hook_command(event, func_name, prio, help, data) if you need to pass prio, data and/or a help text). Each script runs in it's own lua state. Currently no data can be passed from one script to another (except via commands). The base, table, io, string and math libs are loaded. All scripts in the xchat dir (usually ~/.xchat2/) ending in ".lua" are autoloaded. After loading of all these scripts, the lua function xchat_register() in each script is called, it must return three strings: script name, description, version. If you load a script with /LOAD script.lua, xchat_register() is immediately called after loading. After a script is registered (i.e. nothing was wrong in calling xchat_register()) the lua function xchat_init() is called. You should add your hooks here, open file descriptors, ... This is an optional call. If your script doesn't have an xchat_init() function, nothing bad happens. Before unloading (just one script or the plugin) xchat_unload() is called if it exists. You must do cleanup stuff here, like closing all open file descriptors or removing menu entries (see http://xchat.org/docs/plugin20.html#menu). There's no need to unhook explicitly, as it's automa(t|g)ically done when unloading a script/the plugin. Manually unloading of single scripts is supported with /UNLOAD script.lua. All constants and functions of the xchat API are located in the table xchat. One line lua scripts can be executed with the /LUA command, like in this (more or less usless ;-)) example: /LUA xchat.printf("my nick is %s", tostring(xchat.get_info("nick"))) This line is executed in it's own lua state. All xchat.hook_* are disabled for the /LUA command. Predefined constants Return values for callback functions: xchat.EAT_NONE pass event along xchat.EAT_XCHAT don't let xchat see this event xchat.EAT_PLUGIN don't let other plugins see this event xchat.EAT_ALL don't let xchat and other plugins see this event Priority of the event hook xchat.PRI_HIGHEST xchat.PRI_HIGH xchat.PRI_NORM xchat.PRI_LOW xchat.PRI_LOWEST Stripping color codes (for xchat.strip()) xchat.STRIP_COLOR strip just colors xchat.STRIP_ATTR strip just attributes xchat.STRIP_ALL strip both Setting tab color (for xchat.commandf("GUI COLOR %d", xchat.TAB_NEWMSG)) new in revision 76 xchat.TAB_DEFAULT set tab color to default color xchat.TAB_NEWDATA set tab color to "new data arrived" xchat.TAB_NEWMSG set tab color to "new messages" xchat.TAB_HILIGHT set tab color to "highlighted messages available" Misc xchat.ARCH "Windows" or "Unix" ... depending on system :) X-Chat API functions xchat.hook_command(name, func_name, prio, help_str, data) * description Adds a new /command. This allows your program to handle commands entered at the input box. To capture text without a "/" at the start (non-commands), you may hook a special name of "". i.e xchat.hook_command("", ...) Starting from version 2.6.8, commands hooked that begin with a period ('.') will be hidden in /HELP and /HELP -l. * return values true... or false if something went wrong while registering hook * arguments * name (string): the name of the new command * func_name (string): the lua function to be called when command is entered * prio (number): use one of the xchat.PRI_* use nil, for xchat.PRI_NORM * help_str (string): help for the new command... use nil for no help * data (table): table with strings, numbers and booleans, which will be passed to func_name as last argument. xchat.hook_server(name, func_name, prio, data) * description Registers a function to be called when a certain server event occurs. You can use this to trap PRIVMSG, NOTICE, PART, a server numeric etc... If you want to hook every line that comes from the IRC server, you may use the special name of "RAW LINE". * return values true... or false if something went wrong while registering * arguments * name (string): the event name / numeric (yes, also as a string) * func_name (string): the function to be called, when the event happens * prio (number): one of the xchat.PRI_* constants (or nil for xchat.PRI_NORM * data (table)... see xchat.hook_command() ... both (xchat.hook_command() and xchat.hook_server()) callback functions are called like func_name(word, word_eol, data) * description your previously hooked callback function for hook_command() and hook_server(), you must return one of the xchat.EAT_* constants * return values none * arguments * word (table): the incoming line split into words (max 32) * word_eol (table): for both see http://xchat.org/docs/plugin20.html#word * data (table): the data table you passed to the hook_command() / hook_server() as 5th/4th arg xchat.hook_print(name, func_name, prio, data) * description Registers a function to trap any print events. The event names may be any available in the "Advanced > Text Events" window. There are also some extra "special" events you may hook using this function, see: http://xchat.org/docs/plugin20.html#xchat_hook_print * return values true... or false if something went wrong while registering hook * arguments * name (string): the name of the new command * func_name (string): the lua function to be called when command is entered * prio (number): use one of the xchat.PRI_*, or nil for xchat.PRI_NORM * data (table): table with strings, numbers and booleans, which will be passed to func_name as last argument. The callback function for this hook is called like func_name(word, data) * description your previously hooked callback function for hook_print(), you must return one of the xchat.EAT_* constants return values none arguments * word (table): the incoming line split into words (max 32) (see http://xchat.org/docs/plugin20.html#word) * data (table): the data table you passed to the hook_print() as 4th arg xchat.hook_timer(timeout, func_name, data) * description Registers a function to be called every "timeout" milliseconds. * return values the timer name (string) or false if something went wrong while setting up the timer. Use this timer name to unhook the timer (or return false from the timer func, see below). * arguments * timeout (number): Timeout in milliseconds (1000 is 1 second). * func_name (string): Callback function. This will be called every "timeout" milliseconds. * data (table): see xchat.hook_command() The callback for hook_timer() is called like func_name(data) * description the callback function for the registered timer hook, return true to keep this timer going, false to stop it * return values none * arguments * data (table): the table you gave the hook_timer() as last argument xchat.unhook(name) * description unhooks a previously hooked hook * return values true if the hook existed, else false * arguments * name (string): name of a registered hook (e.g. with xchat.hook_command("whois", ... ) you would unhook "whois" ... or the timer name returned from a xchat.hook_timer). xchat.event() * description new in rev. 69 returns the name of the currently running hook, i.e. the name of what you hooked with xchat.hook_server() or xchat.hook_print() * return values the name of the hook * arguments * none xchat.command(command) * description executes a command as if it were typed in xchat's input box. * return values none * arguments * command (string): command to execute, without the forward slash "/". xchat.commandf(fmt, arg1, ...) * description executes a command as if it were typed in xchat's input box.... with string formatting. This command is function xchat.commandf(...) xchat.command(string.format(unpack(arg))) end * return values none * arguments * like string.format() xchat.print(text) * description Prints some text to the current tab/window. * return values none * arguments * text (string): the text to print xchat.printf(fmt, arg1, ...) * description Prints some formatted text to the current tab/window. This is implemented as function xchat.printf(...) xchat.print(string.format(unpack(arg))) end * return values none * arguments like string.format() xchat.emit_print(event, text, [text2, ...]) * description Generates a print event. This can be any event found in the "Preferences > Advanced > Text Events" window. The number of parameters after the event must not be more than four (4), else you will raise a lua error. Special care should be taken when calling this function inside a print callback (from xchat.hook_print()), as not to cause endless recursion. * return values true on success, false on error * arguments * event (string): the event name from the "Preferences > Advanced > Text Events" window * text (string) text2 (string) ... (string(s)): parameters for the given event xchat.send_modes(targets, sign, mode [, modes_per_line]) * description Sends a number of channel mode changes to the current channel. For example, you can Op a whole group of people in one go. It may send multiple MODE lines if the request doesn't fit on one. Pass 0 for modes_per_line to use the current server's maximum possible (this is also the default). This function should only be called while in a channel context. * return values none * arguments note: the order of the arguments is not the same as in the C or perl API... * targets (table): list of names (strings) * sign (string): mode sign, i.e. "+" or "-", only the first char of this is used (it is checked if it is really "+" or "-") * mode (string): mode char, i.e. "o" for opping, only the first char of this is used (checked if it's an ASCII char) * modes_per_line (number): [optional] number of modes per line xchat.find_context(srv, chan) * description Finds a context based on a channel and servername. If servname is nil, it finds any channel (or query) by the given name. If channel is nil, it finds the front-most tab/window of the given servname. If nil is given for both arguments, the currently focused tab/window will be returned. Changed in 2.6.1. If servname is nil, it finds the channel (or query) by the given name in the same server group as the current context. If that doesn't exists then find any by the given name. * return values context number (DON'T modify) * arguments * srv (string or nil): server name * chan (string or nil): channel / query name xchat.get_context() * description Returns the current context for your plugin. You can use this later with xchat.set_context(). * return values context number ... DON'T modifiy * arguments none xchat.get_info(id) * description Returns information based on your current context. * return values the requested string or nil on error * arguments * id (string): the wanted information, for known values see http://xchat.org/docs/plugin20.html#xchat_get_info. xchat.get_prefs(name) * description Provides xchat's setting information (that which is available through the /set command). A few extra bits of information are available that don't appear in the /set list, currently they are: * state_cursor: Current input-box cursor position (characters, not bytes). Since 2.4.2. * id: Unique server id. Since 2.6.1. * return values returns the string/number/boolean for the given config var or nil on error * arguments * name (string): the wanted setting's name xchat.set_context(ctx) * description Changes your current context to the one given. * return values true or false * arguments * ctx (number): the context (e.g. from xchat.get_context(), xchat.find_context()) xchat.nickcmp(name1, name2) * description Performs a nick name comparision, based on the current server connection. This might be a RFC1459 compliant string compare, or plain ascii (in the case of DALNet). Use this to compare channels and nicknames. The function works the same way as strcasecmp. * return values number ess than, equal to, or greater than zero if name1 is found, respectively, to be less than, to match, or be greater than name2. * arguments * name1 (string): nick or channel name * name2 (string): nick or channel name xchat.strip(text, flags) * description strips mIRC color codes and/or text attributes (bold, underlined etc) from the given string. This is implemented in lua for compatibility with older xchat versions (<= 2.4.1): function xchat.strip(str, flags) if flags == nil then flags = xchat.STRIP_ALL end local bits = xchat.bits(flags) if bits[1] then str = string.gsub( string.gsub(str, "\3%d%d?,%d%d?", ""), "\3%d%d?", "") end if bits[2] then -- bold, beep, reset, reverse, underline str = string.gsub(str, "[\2\7\15\22\31]", "") end return str end * return values a "cleaned" string or nil on error * arguments * text (string): string to strip * flags (number): optional, defaults to xchat.STRIP_ALL: what to strip, use the xchat.STRIP_* values for this. xchat.list_fields(name) * description returns the possible keys for name as table * return values a table, see above. * arguments * name (string): name of the wanted list ("channels", "dcc", "ignore", "notify", "users") xchat.list_get(name) * description see http://xchat.org/docs/plugin20.html#lists time_t values are stored as number. Example: os.date("%Y-%m-%d, %H:%M:%S", time_t_value). pointers (channel -> context) as number... untested if this works, but should do the same way as xchat.get_context(). * return values a table with tables with all keys=Name, value=(Type)... or nil on error * arguments * name (string): the wanted list, same valid as for xchat.list_fields() * use chaninfo = xchat.list_get("channels") if chaninfo ~= nil then table.foreach(chaninfo, function(i, list) table.foreach(list, function(k, v) xchat.print(string.format("k=%s, v=%s", k, v)) end ) end ) end xchat.gettext(msgid) * description new in rev. 72 gives access to xchat's gettext. It looks up "msgid" in the message catalogs and returns the translated string according to the current locale. Un*x only: If compiled without LXC_XCHAT_GETTEXT defined: xchat.gettext(msgid [,txtdomain]), where txtdomain is the catalog you want ot get the msg from (e.g. "libc"). * return values string with the translated msgid * arguments * msgid (string) the string to be translated * Un*x only: If compiled without LXC_XCHAT_GETTEXT defined: txtdomain (string) the text domain to fetch the string from, see dgettext(3) xchat.bits(flags) * description returns a table of booleans if the bit at index is set note: bits start counting at 0, so if you want bit 4, index is 5, for bit 0 index is 1, ... * return values table of booleans * arguments * flags (number) ... from flags of xchat.list_get() -> channels, ignore, notify * use see above in xchat.strip() or function has_whox(context) local chaninfo = xchat.list_get("channels") if chaninfo ~= nil then return table.foreach(chaninfo, function(i, list) if context == list.context then -- 'Has WHOX' is bit 4, which is the 5th bit -- counting from 0 return xchat.bits(list.flags)[5] end end ) end return false end ... if has_whox(xchat.get_context()) then ... else ... Sample script Download In case you haven't done it already, you can get the latest version from http://ankh-morp.org/~vetinari/projects/xchat-lua/ Earlier versions are available via SVN from http://svn.ankh-morp.org:8080/xc_lua/ Released versions are * 0.2 - revision 22 * 0.3 - revision 26 * 0.4 - revision 40 * 0.5 - revision 53 "visible" changes: * xchat.strip() last arg (flags) now optional, defaults to xchat.STRIP_ALL now a lua function * xchat.EAT_*, xchat.STRIP_*, xchat.PRI_* read only now (not if you're messing with the metatable... but do you really want to do that?) ... mainly for not accidently changing these constants * 0.5 win32 - win32 build by zed from revision 63, built with lua51.dll. * 0.5.1 - also builds with lua5.1 * 0.6.0 - rev 72 "visible" changes: * new: xchat.gettext() * new: xchat.ARCH * 0.7.0 - rev 81 "visible" changes: * xchat.hook_server(), xchat.hook_command(), xchat.hook_print(): moved prio argument to #3... now last 3 arguments are optional and only have to be set if you need them or one earlier, i.e. set prio if you need the help text for xchat.hook_command(). * 0.7.1 - rev 84 "visible" changes: * xchat.hook_timer() returns the timer name, which may be used to unhook this timer. Compiling NOTE: will wonly work with xchat >= 2.0.9, just tested on 2.6.8. On debian Linux install * liblua50, liblua50-dev, * liblualib50, liblualib50-dev * lua50 and compile with gcc $( lua-config --include ) $( lua-config --libs --extralibs ) \ -Wl,--export-dynamic -Wall -O1 -shared -fPIC \ -I/path/to/your/xchat-plugin.h/dir \ -o lua.so lua.c ...else: gcc -L/path/to/your/lualibs -llua50 -llualib50 -lm \ -I/path/to/your/lua/includes/ \ -Wl,--export-dynamic -Wall -O1 -shared -fPIC \ -I/path/to/your/xchat-plugin.h/dir \ -o lua.so lua.c lua5.1 (debian etch): gcc -I/usr/include/lua5.1 -L/usr/lib -l"lua5.1" \ -Wl,--export-dynamic -Wall -O1 -shared -g -fPIC \ -I/path/to/your/xchat-plugin.h/dir \ -o lua.so lua.c Finally, to install: copy the lua.so to the dir, where `xchat -p` wants it ;-) Contact Feel free to send feedback and bugreports, patches [*g*] to xchat.lua@ankh-morp.org. In case of problems ALWAYS report the revision number (found at top of the lua.c file or in the "Windows > Plugins and Scripts..." window after loading the plugin). ---------------------------------------------------------------------- $Revision$ $Date$