Unofficial X-Chat Perl Scripting Documentation

     
 
Document Created: February 15th, 1989
Last Modified: October 22nd, 2003
Created By: Dagmar d'Surreal
Updated by: Peter Zelezny
Dave Whiting
Current Version: X-Chat 2.0.5
 
     
Whew! Finally!

It was about time the X-Chat perl scripting documentation has finally updated. Well over three years has passed since the last incarnation of this page was updated, and many things have changed. Much of the old documentation has been used, with many updates and changes. I have made a few perl scripts on my own and have untaken this project as a chance to refresh my scripting skills and update myself (and everyone else) of the many changes that have been made over the past few years.

The purpose of this page is to give people some quick documentation of the functionality available within X-Chat to code scripts using Perl. There are many scripts already available, but they don't always work exactly the way you want. This document, with some other references, should help you create your own scripts.

If you're going to do any perl scripting with X-Chat at all, you will need to know perl. :) It also won't hurt to have had experience writing tcl for eggdrops or ircII scripts. Otherwise you're going to have to be very careful to avoid creating conditions which could flood you offline or do other not-so-optimal things. ;) Thankfully, it shouldn't take most intelligent people more than a week (month on the outside) enough perl to do some nice things in it.

     
 
Standard Disclaimer

This documentation is provided on an "as-is" basis and comes with no warranty of accuracy or usefulness, either expressed or implied. It is subject to change without any notice, and may contain omissions or errors which could cause your genitalia to shrivel and fall off, or spontaneously combust. If you have any further questions, please feel free to seek professional help.
 
     

1. Important References
     
  Before starting to script, you should probably do some reading. The following is a table of references that will definitely aid when creating scripts. It is highly recommended that you save a copy of these documents locally, as you will be looking at them quite often!
  • RFC 1459 - Request For Comments for the Internet Relay Chat Protocol. Pay close attention to section 2.2
  • Server Numerics - List of IRC server message numerics
  • Hybrid 6 - Changes for Hybrid 6 (something everyone on EFNet should read)
 
     

2. Perl
     
  Perl was the first language used for creating scripts in X-Chat, making it the most popular! For those of you who are used to ircII's scripting language, or using eggdrop with tcl, the only thing you will really miss is that the regexps are a lot different, but they're more powerful in perl. For those of you saddled with weak languages for too long, regexps means REGular EXPressions, or "pattern matching wildcard usage" in layman's terms.  
     

3. Handlers
     
  There are currently three basic ways to make things call the subroutines you write for X-Chat. They are message handlers, command handlers, and timeout handlers. Message handlers trigger on messages sent from the IRC server to your client, command handlers are triggered by "/ commands" typed in by the user at the keyboard, and timeout handlers are triggered by GTK+.  
     

4. Exit Codes
     
  These are very important. Every time you set up a handler, it takes precedent over the built-in functions and commands of X-Chat. That is, whatever thing which triggered your subroutine will go to your code before it goes to X-Chat to be dealt with. In this way you can replace almost every built-in function that the client has with your own routines. The thing to remember is that if your code exits by hitting the end of your subroutine, or by a plain 'return' statement, processing of the event will go on to whatever other things have set up hooks for the event, and then (provided nothing else exits with a return value of 1) to X-Chat itself. There is only one problem with this, and that is that you cannot really control what order the custom routines get called. Normally they will execute in order of which ones were installed first, but a single script has no real way of knowing this. Beware.  
     

5. @_
     
  If you've never heard of @_ before, then go read a perl book! When a message handler triggers, the raw line from the IRC server is passed to the subroutine you specify in @_. When a command handler is triggered, only the arguments are passed to the routine through @_ and they are not broken into a list, but left as one long string. You'll have to parse those yourself with split. (You can use s/\s+/ /g to collapse the blank space to single space first.) When a timer handler is triggered, nothing is passed in @_. Be especially careful when setting up message handlers for mode changes, since the modes are not broken up into individual events like they are with eggdrop. The upside of this is that X-Chat has no mode hooks of it's own, so you don't have to worry about it too much.  
     

6. Packages
     
  You never know which scripts may use the same name for a variable, especially if you are using scripts created by many different people. If two scripts use the same variable name, it is very likely that the scripts will walk over each other and clobber data. The reason for this is that perl scripts, by default, share the same environment within X-Chat. By turning a script into a perl package, this separates the namespaces and avoids the clobbering issue. Below is a skeleton of an X-Chat perl script in a package:

package Sky;
...

IRC::add_command_handler("loadconf", "Sky::load_conf");
...

load_conf();
...

sub Sky::load_conf {
...
}
 
     

7. Context
     
  There are some really nice things about coding for X-Chat, and the biggest one is that it's fairly good about determining the proper context for things. If a server sends something that triggers a message handler, then you can be sure that unless you specify otherwise, that your IRC::print() or IRC::command() function call will go back to that server and that server alone. If you really really need to know what the current context is, use the IRC::get_info() function as detailed below.  
     

8. Functions
     
 
$version = IRC::register(scriptname, version, shutdown_callback, unused);
Description: This is the first function your script will call. It is used to register your script with x-chat. Each registered script should have it's own scriptname and version.
Parameters:
  • scriptname: the name of the script
  • version: the version number of the script
  • shutdown_callback: the function to be called when the script is unloaded
  • unused: reserved for future use (for now provide "")
Returns: current X-Chat version.
Notes: The shutdown_callback function is often used to save settings or close files which are in use, but is not limited to these operations.
Examples: $ver = IRC::register("my script", "0.9a", "save_settings", "");

IRC::register("other script", "1.2", "", "");
 
     
     
 
IRC::add_message_handler(message_type, handler_name)
Description: Each message which comes from the IRC server has an associated message type. This function allows you to set up a subroutine which will be triggered when a particular message_type arrives from the server. The message argument is essentially the second solid token from the raw line sent by the IRC server. The entire line is passed to the subroutine in @_.
Parameters:
  • message_type: the message type arriving from the IRC server.
  • handler_name: the subroutine called when message arrives.
Notes: X-Chat does not know that some server numeric messages have associated test messages, so for now setup a handler for both if you want to be sure odd (read, IRCNet) servers don't screw up your expectations.

A special pseudo-message type "INBOUND" can be used to capture ALL incoming events.
Examples: IRC::add_message_handler("NOTICE", "notice_handler");
sub notice_handler() {
my $line = shift(@_);
...
}


IRC::add_message_handler("dcc", "dcc_chat_handler");
sub dcc_chat_handler() {
my $line = shift(@_);
...
}
 
     
     
 
IRC::add_command_handler(command, handler_name)
Description: This function is used to create custom commands to be typed into the text entry. Arguments to the command are passed to handler_name in @_ as a single line
Parameters:
  • command: the command name
  • handler_name: the subroutine to be called when command is used
Notes: It is recommended to collapse the excess whitespace of the arguments with s/\s+/ /g before attempting to chop up the line with split.

By using the empty string ("") as the command will call the subroutine with what you type into the text entry for everything that is not a command (begins with '/').
Examples: IRC::add_command_handler("no", "private_notice_handler");
sub private_notice_handler() {
my $line = shift(@_);
$line =~ s/\s+/ /g;
...
return 1; # Don't pass to x-chat for further parsing
}

IRC::add_command_handler("", "input_entry_handler");
sub input_entry_handler {
my $line = shift(@_);
...
return 0; # Let x-chat handle input
}
 
     
     
 
IRC::add_print_handler(event_message, handler_name);
Description: Each event which is listed under "Settings->Lists->Text Events" can be associated with a subroutine, which will be run every time that event appears. Arguments are sent to handler_name in $_[0] separated by spaces.
Parameters:
  • event_message: the name of the event
  • handler_name: the subroutine called when event appears
Notes: The possible names for the events can be found in the Edit Events box under the "Events" column.

All non-standard numeric events are handled by "Server Text. These include event 307 (identified for nick) and event 401 (no such user).
Examples: IRC::add_print_handler("Join", "join_print_handler");
 
     
     
 
IRC::add_timeout_handler(timeout, handler_name);
Description: This is a one-shot timer which calls a subroutine after a given timeout has occurred. Nothing can be passed to the subroutine via @_ and return values do not affect anything.
Parameters:
  • timeout: time, in milliseconds
  • handler_name: the subroutine called after timeout
Notes: The timeout handler will have to be reinstalled if you want it to be called regularly.

The timeout is in milliseconds (1000ms = 1 seconds), so don't use particularly small value unless you want to drive the CPU load through the roof.

There is currently no way to remove a timeout handler once it has been installed. If you wish to stop a repeatedly triggered timeout handler, simply include a condition where it will NOT be reinstalled.
Examples: IRC::add_timeout_handler(1000, "update_settings");
sub update_settings {
...
IRC::add_timeout_handler(1000, "update_settings"); # reinstall
}
 
     
     
 
IRC::print(text);
Description: This is a very simple function which takes the contents of text and prints them to the current window. The current window will be whichever window a command was typed into when called from a command handler, or whichever window the message command is appropriate for if it called from within a message handler.
Parameters:
  • text: the content to output
Notes: Newlines are not assumed, as with any perl program, so do not forget to end the text with \n if you don't want things to look screwy.

The following codes can be used to output color and other text modes:
Style Input Text Print Text
Bold %B \002
Foreground Color %C04 \00304
Background Color %C04,00 \00304,00
Reverse Foreground/Background %R \026
Reset Color and Format %O \017
Reset Color %C \003
Underline %U \037
Examples: IRC::print("Plain \00302,08Blue with Yellow Background \017Reset\n");
 
     
     
 
IRC::print_with_channel(text, channel, [server]);
Description: Perhaps you want to print to different context than the subroutine is currently in. This function allows you to control which window you wish to print to by specifying the channel and server which the window is connected to.
Parameters:
  • text: the text to output
  • channel: the channel/tab to which to print.
  • server: the server on which channel is connected.
Returns: 1 on success, 0 on fail
Notes: The server parameter is optional. If you do not use it, specify ""

This function will only work if the channel/tab already exists.
Examples: $server = "irc.dal.net";
IRC::print_with_channel("this is in server window", $server, $server);

IRC::print_with_channel("this is in Bob query window", "Bob", "");

IRC::print_with_channel("this is in channel #test", "#test", $server);
 
     
     
 
IRC::send_raw(text);
Description: This function allows you to send a string directly to the IRC server you are connected to. If there is no clear context for the command, it is assumed that the server will be the one to which you first connected. Otherwise, it will go to whatever server triggered the message handler or comnmand handler window.
Parameters:
  • text: a proper RAW IRC message.
Notes: Newlines are not assumed here, as with the IRC::print() function. The RFC specifies that newlines are a CR+LF pair, even if most servers will accept a mere newline. It's best to play it safe and use \r\n instead of just \n.
Examples: # Send an action (\cA is ^A)
IRC::send_raw("PRIVMSG $channel :\cAACTION $text\cA\r\n");

# Send a CTCP MP3 message with some song name ($channel is channel or nick)
IRC::send_raw("PRIVMSG $channel :\cAMP3 $song\cA\r\n");
 
     
     
 
IRC::command(text);
Description: This function allows the execution of commands in the current context.
Parameters:
  • text: a proper command to execute
Notes: The text string will be parsed by everything that would normally parse a command. This includes any command handlers which may have been setup.

Newlines are assumed.
Examples: # Send text to current channel context
IRC::command("Hello");

# Issue away command to all servers
IRC::command("/allserv /nick $awaynick");
IRC::command("/allserv /away away");
 
     
     
 
IRC::command_with_server(text, server);
Description: Similarly to IRC::command(), this function allows the execution of commands. However, the server context must be specified, such that there are no assumptions made. Although not overly useful, this function exists for doing things like managing a BNC connection.
Parameters:
  • text: a proper command to execute.
  • server: the server on which command will the executed.
Notes: Newlines are assumed.
Examples: # Issue away command to specific server
IRC::command_with_server("/nick $awaynick", $server);
IRC::command_with_server("/away away", $server);
 
     
     
 
IRC::command_with_channel(text, channel, [server]);
Description: Similarly to IRC::command(), this function allows the execution of commands. However, the channel context must be specified, such that there are no assumptions made.
Parameters:
  • text: a proper command to execute.
  • channel: the channel on which command will be executed.
  • server: the server on which command will be executed.
Notes: The server is optional. If not specified, use "".

Newlines are assumed.
Examples: # Issue away command to specific server
IRC::command_with_channel("/topic New Topic", $channel, $server);
IRC::command_with_channel("/banlist", $channel, $server);
 
     
     
 
IRC::channel_list();
Description: This command would probably be better renamed tab_list(). It returns the current tab, server, and nickname for all tabs the client currently has open.
Parameters: None
Returns: A flat list that is in groups of three elements - tab, server, and nickname.
Notes: You'll have to break the list up into groups of three yourself.

Since this function returns all tabs, you may have to parse the tab name to determine whether it is a channel or not.
Examples: my @list = IRC::channel_list();
my ($tab, $server, $nick) = splice(@list, 0, 3);
while ($tab) {
IRC::print "$tab $server $nick\n";
($tab, $server, $nick) = splice(@list, 0, 3);
}
 
     
     
 
IRC::server_list();
Description: This function retrieves a list of all servers to which the client is currently connected. This has no bearing on which tabs are currently displayed, or whether server messages have their own window.
Parameters: None
Returns: A flat list of servers.
Notes: As each item only contains a single entry, there is no need to break up (splice) them.
Examples: my @list = IRC::server_list()
foreach $server (@list) {
IRC::print "$server\n";
}
 
     
     
 
IRC::user_list(channel, server);
Description: Retrieve information about all users on a given channel / server.
Parameters:
  • channel: The channel for which to retrieve userlist
  • server: The server where the channel resides
Returns: A flat list that is in groups of five elements - nickname, hostname, op status (1 for true, 0 for false), voice status, and a ":" (for future use, I assume)
Notes: You must be connected to the server and in the channel in order to retrieve the channel's user list.

If a user has both op and voice, only the op flag will be 1.

The hostname for the user may be "FETCHING" if it's unknown. For example, this may occur just after joining the channel or with the "send /who #chan on join" xchat setting off.
Examples: my @users = IRC::user_list($chan,$server);
while (@users) {
my ($nick, $host, $op, $voice, undef) = splice(@users, 0, 5);
IRC::print("$nick on host $host, has " . ($op > "" : "no ") . "op, and " . ($voice ? "" : "no ") . "voice.\n");
}
 
     
     
 
IRC::user_info(nickname);
Description: Retrieve the nickname, hostname, op and voice of the specified nick. Similar to IRC::user_list(channel, server), but just for the one specified user.
Parameters:
  • nickname: the nickname of the user for which you wish to obtain the information.
Returns: A flat list containing the elements described above
Notes: If a user has both op and voice, only the op flag will be 1.

The hostname for the user may be "FETCHING" if it's unknown. For example, this may occur just after joining the channel or with the "send /who #chan on join" xchat setting off.
Examples: # Get all info for "Chuck"
my @info = IRC::user_info("Chuck");
my ($nick, $host, $op_indicator, $voice_indicator) = @info; # indicators are either 1 (true) or 0 (false)

# Check for OP status on current channel, 1 is true, 0 is false
sub have_op {
my @info = IRC::user_info(IRC::get_info(1));
return $info[2];
}
 
     
     
 
IRC::ignore_list();
Description:
Parameters: None
Notes:
Examples:
 
     
     
 
IRC::notify_list();
Description:
Parameters: None
Notes:
Examples:
 
     
     
 
IRC::dcc_list();
Description:
Parameters: None
Notes:
Examples:
 
     
     
 
IRC::get_info(integer);
Description: Retrieve useful information about xchat configuration and current channel context
Parameters:
  • integer: The following details what different integer values will return:
    • 0 - xchat version
    • 1 - nickname
    • 2 - channel
    • 3 - server name
    • 4 - configuration dir (usually ~/.xchat, ~/.xchat2, or the one specified using the command line -d switch)
    • 5 - away notification in the current context
    • 6 - network
    • 7 - hostname
    • 8 - channel topic
Returns: Value corresponding to the integer passed
Notes: This function should always be used to retrieve the xchat dir, rather than assuming it is the default (Many scripts I have seen have always assumed the default, and this definitely doesn't work for users who do not use this default (winblows users, for example). Note: I am not advocating the use of winblows.
Examples: # Get current context nickname and channel
my $nick = IRC::get_info(1);
my $chan = IRC::get_info(2);
IRC::print("$nick is on channel $chan\n");
 
     
     
 
IRC::get_prefs(pref);
Description: Fetch a value from the current xchat vars (see /set command for variable list)
Parameters:
  • pref: the variable name for which to retrieve the value
Notes: Rather than list all the possible preference variables, a larger list of preferences can be found in xchat.conf in your configuration directory.
Examples: # Get the download directory
$dcc_dir = IRC::get_pref("dcc_dir");

# Get the secondary IRC nick
$secondary_nick = IRC::get_pref("irc_nick2");
 
     
     
 
IRC::user_list_short(channel, server);
Description: This function is a stripped down version of IRC::user_list(): It leaves out the operator (+o) and voice (+v) status, but keeps the nickname and addresses.
Parameters:
  • channel: the channel from which to retrieve list.
  • server: the server the channel is on.
Returns: A flat list of two elements: nickname and address (user@host)
Notes: Return value is suitable for assigning into a hash.
Examples: my %UserList = IRC::user_list_short($channel, $server);
 
     
     
 
IRC::perl_script_list();
Description: This function allows you to get all perl scripts, and corresponding script versions, which are currently loaded in X-Chat.
Parameters: None
Returns: A flat list of two elements: script name and version
Notes: I have no idea why this is useful. :)
Examples: