Author: Daniel.Stenberg Date: 1997-11-04 Version: 1.1 ############################# -=*( Using FPL in Dancer )*=- ############################# Introduction Setup Hooks FPL Programs Adding New Commands Adding New User Info Timed Events Built-in Function Introduction ============ FPL is a full language interpreter. C syntax, C keywords and C expressions. Only minor incompatibilities. It offers a complete setup of basic functions like strcmp(), atoi(), sprintf(), sscanf() and more. For detailed language documentation, read http://www.fts.frontec.se/~dast/fpl This document is only targeted to Dancer specific information. All general FPL information is left out and should be looked for elsewhere. Setup ===== File Name --------- The name of the file that should contain all FPL setup items, is defined by the 'initfpl' field of the dancer.config file. The default name of the file is 'dancer.fplconf'. File Format ------------ The FPL setup file is contructed by lines using the following format (lines starting with the letter '#' are treated as comments): [+]: "" Where the different data fields mean: [+] - Optional starting '+' letter, that if present, makes this into a "post hook". See the chapter about "Hooks" for details. - The name of the hook this concerns. - A full blown extended regular expression. If this is left empty (""), it will match everything. - A correct FPL program using appropriate syntax. Certain %-codes are supported and will be expanded before this program is run. %-codes available include: i - content sensitive input string (see the hook list for info) n - nick name of the bot u - nick name of the "current user" c - name of the channel t - time(NULL) integer (suggestions welcome of more codes to add) Let's have a look at an example, where we make the bot speak to anyone that joins the channel. It includes the channel name as one of the %-codes: join: "" Say("Welcome to channel %c!"); The same hook name may appear any number of times in the same file to add several different invoke-condiditions. Hooks ===== One way to make Dancer behave differently on different events, is to find which hook is generated at the specific event and then make your prefered fpl function run at that time. There are a large amount of hooks, hopefully at least one for every imaginable situation where you would wanna run your own functions. There are two kinds of hooks, pre and post. Pre hooks are the normal ones and are performed _before_ the internal actions are done and post hooks are surprisingly enough, run _after_ the internal actions. You specify post hooks by prefixing the hook name with a '+' character in the setup file. You can add several functions to a single hook, and each funtion added to a hook has a regex pattern that has to match the input data in order for the function to get run. The 'input' to the hook is the one compared with the regex, and also the data that the %i is expanded to. Although you can add any number of functions to the same hook, you can make one function disable all the rest of the functions from being run by calling the Cancel() function. Some if the internal functions will also be possible to cancel in a pre-hook by the use of the Cancel() function. See the list of built-in functions for more details about Cancel(). Table of Available Hooks (P means that this function's internal actions is prevented from taking place if the pre-hook calls Cancel().) Name Input P Description ---- ----- - ----------- init - - Performed when the bot is started public public msg - A non-command public msg was received action action msg * A /me was read in the channel ctcppub ctcp msg * Public CTCP was received ctcppriv ctcp msg * Private CTCP was received topic topic line * Topic changed kick kick line - A user was kicked off by another user join nick - A user joined signoff nick - A user signed off leave nick - A user left nick nick - A user changes nick (pre hook gets old nick, post hook gets new nick) invite channel * We received an invite request numeric number * Numeric message was received from the server connect server name * When the bot connects to a server: disconnect disconenctmsg * When the bot disconnects from a server: error error msg * Server error alert nick * Alert for nick shown offmsg line * Off-channel message kickbot nick!user * The bot got kicked --- Some hooks that might or might not get added in the future: --- input - easy-to-use (done on action, public, msg and dcc) msg - A non-command msg was received dcc - A non-command dcc line was received note - We received an irc NOTE notice - We received a NOTICE wall - This is activated whenever you receive a WALL mode - Mode change was done in channel user modes are ignored mixed modes are grouped and hook is called for each group banlist etc. must be updated reactions to bans etc. can be overruled send_action - We sent (strongly ircII inspired) send_dcc_chat send_msg send_notice send_public warning - User warning (on join) flood - User flooding (type is given) nethack - Server modechanges netsplit - Detection of netsplit nethead - Detection of netjoin (or timeout) netleave - User left in netsplit netjoin - User joined in netjoin FPL Programs ============ To add functions to Dancer, you must write the functions using the FPL syntax in a file that is run from another FPL file before the function is called (to run an FPL program from within a function, use Runfile()). If you write a function in one source file and intends to call the function from another, you must make the function "exported" which you do with the keyword 'export' in front of the function name. All errors that the FPL interpreter discovers in your FPL programs, are logged in the dancer logfile using the DEBUG flag. If you have that disabled from the log, you won't see any FPL error messages and therefor get a very hard time debugging your mistakes... Adding New Commands =================== Add a new command to your bot by running a FPL program that uses the CmdAdd() function. int CmdAdd(string name, /* name of new command, preferable specified in uppercase like the rest of the commands NO, you can't add aliases to this one. */ int level, /* level required for use */ string syntax, /* syntax string */ string help, /* help string */ string flags, /* flags as below */ string fpl) /* complete FPL program to run at invoke in full fpl-invoke style with %-support */ the flags are strings separated with a '|' letter. Available flags are: showable - Output can be redirected to another person passwd - Password protected needcomma - Comma is part of argument, not argument seperator public - Command can be used in public Example: CmdAdd("TEST", 10, "[nick]", "tests ", "passwd|public", /* publicly available and require password */ "mytestfpl(%i);")); /* this function must be exported prior to the invoke */ Adding New User Info ==================== Adding new user info, soft userdata, is userdata not controlled, used or set by internal functions of Dancer. This kind of data is all controlled by FPL. The data is connected to one user. The FPL program can define a symbol/label and then read/write any number or string to it. That value/string can then be saved attached to a user. It is global and once defined the label and be read/written to/on any user. Non user-connected labels can be made, read and written with the same function setup, just note the flag to LabelDefine(). Define a label -------------- LabelDefine(string name, /* name of the label, any sequence of non-whitespace letters are accepted */ string flags, /* flags as below */ int/string default) /* default value/string */ This function defines a label. Only defined labels (that differs from the default value) are stored/existing. Available flags are: save - save the data per-user (otherwise the data will simply be forgotten when the user leaves the channel and set to default for all users that join the channel) solo - this label is plain alone and is *not* connected to any user, but simply a single global label. (Specifying a userid when reading or writing one of these kind of labels won't affect anything!) The reason for only saving defined ones is that otherwise there wouldn't be any way to remove old, left-over, obsolete or test symbols. Read a label ------------ LabelRead(string name, int userid) Returns the value of the label of the current user or if the userid parameter is specified, of the specified user. Userid is returned from the the function GetUser(). (I've decided to make this a separate call and use the id approach to easier separate and enable FPL programs to separate joined users from regged users and DCC-only users. A mere nick name is not always enough.) Set a label ----------- LabelSet(string name, int/string value, int userid) Sets the label to the specified value. If the userid is specified, that user's label is affected rather than the "current" user. Timed Events ============ TimerAdd(time, action); time - number of seconds until the action is performed action - fpl program to run when the timer goes off EXAMPLE TimerAnnounce.FPL lets the bot call out the time once per hour: void export TellTime() { Say("The time is now %s", GetCurrentTimeString()); TimerAdd(3600, "TellTime();"); } TellTime(); ############################################################################## Built-in Functions ================== This is the complete list of functions Dancer provides to the FPL program environment (as addition to the already present internal functions you can read about in the FPL language documentation). Parameters written with UPPER CASE are optional and will be replaced with default values if not specified. If non-optional parameters are left out, the FPL interpreter will draw your attention to that position by failing hard and report an error! ----- NAME Action - performs a CTCP ACTION, i.e a /me command. SYNOPSIS Action ( string line ); DESCRIPTION Action() outputs the specified line, just as if someone had used the 'SAY' command to the bot. 'SET SAY OFF' does not prevent this from working. RETURN VALUES No return code. ----- NAME BotInfo - returns info about the bot itself SYNOPSIS BotInfo ( string subject ); DESCRIPTION Returns info about the bot. If 'subject' equals "chanop", returns whether the bot is channel operator. If 'subject' equals "nick", returns the current nick name of the bot. RETURN VALUES Depends on the specified 'subject'. ----- NAME Cancel - prevent further execution of more hooks, and possibly the internal functionality too. SYNOPSIS Cancel ( INT STATE ); DESCRIPTION If STATE is undefined or non-zero, this will prevent following hooks to get executed. Some pre-hooks have the capability of disabling the built-in actions by using this function. See the Hooks chapter for more details on that. Cancel() may be called any number of times with different values, it is the state of the last Cancel() that has precedence. Calling this from a non-hook function won't have any effect. RETURN VALUES The state of the cancel before this function was called. ----- NAME ChanInfo - returns information about the channel. SYNOPSIS ChanInfo ( string subject ); DESCRIPTION ChanInfo() returns information about the subject entered as parameter. If subject equals "guests", the function will return the number of guests currently joined. RETURN VALUES Depends on the input parameter. ----- NAME CmdAdd - adds a new command. SYNOPSIS CmdAdd ( string name, int level, string syntax, string help, string flags, string fpl ); DESCRIPTION This command creates a new command named 'name', which becomes available for users with at least 'level'. Whenever this new command name is entered by a valid user, the 'fpl' parameter is run. 'flags' are specified by separating keywords with the '|' character and the flags available at this point are: showable - Output can be redirected to another person passwd - Password protected needcomma - Comma is part of argument, not argument seperator public - Command can be used in public NOTE: there is no check at all at add-time that the fpl program added as the last parameter really is a valid FPL program. RETURN VALUES No return code. ----- NAME GetUser - returns a unique identifier of the specified user. SYNOPSIS GetUser ( string nick, STRING FLAGS ); DESCRIPTION This function returns a number which can be used to identify the specified user in later calls to other functions which use the user id. 'FLAGS' are specified by separating keywords with the '|' character and the flags available at this point are: join - return id of a joined user reg - return id of a regged user If no flags are specified, this function scans for the nick in the following order: 1. joined guests 2. split guests 3. registered users with that nick 4. users connected with dcc only RETURN VALUES The numerical user id. ----- NAME Hook - adds a hook as if it was found in the .fplconf file. SYNOPSIS Hook ( string name, string regex, string fpl, STRING TYPE ); DESCRIPTION Hook lets a program add a hook, just as if it was written in the .fplconf. (See the Hooks section for details.) The 'TYPE' parameter is default considered to be "pre", but if set to "post" the hook will be made a post hook. RETURN VALUES Returns non-zero if it failed. ----- NAME Join - joins a channel. SYNOPSIS Join ( STRING CHANNEL, STRING KEY ); DESCRIPTION Makes the bot join the default or specified channel using the default or specified key. RETURN VALUES No return code. ----- NAME Kick - kick a user off the channel SYNOPSIS Kick ( string nick, string message ); DESCRIPTION Performs a regular kick. If the bot isn't channel operator or in case it has already been kicking a lot, the kick might be queued up to prevent the bot from flooding itself off the channel. Read more about that in a flood description somewhere else. RETURN VALUES No return code. ----- NAME LabelDefine - define a label. SYNOPSIS LabelDefine ( string name, STRING FLAGS, STRING/INT DEFAULT ); DESCRIPTION As described in the Adding New User Info chapter, this function adds a new label connected to the user data structs. 'FLAGS' are keywords separated with the '|' characters. Available flags are: save - Makes the info get saved in the user file solo - This info is not user-connected, but only one instance of this label exists. string - This label contains string data, as opposed to integer data which a label holds by default. The 'DEFAULY' parameter sets the default value of the label if nothing else has been set. RETURN VALUES No return code. ----- NAME LabelRead - reads the value off a label. SYNOPSIS LabelRead ( string label, INT USERID ); DESCRIPTION LabelRead returns the value of the label of the current user or if the userid parameter is specified, of the specified user. USERID is the return code of the function GetUser(). NOTE: I decided to make this (GetUser()) a separate call and use the id approach to easier separate and enable FPL programs to separate joined users from regged users and DCC-only users. A mere nick name is not always enough. RETURN VALUES The contents of the label. ----- NAME LabelSet - sets a label's contents. SYNOPSIS LabelSet ( string label, string/int value, INT USERID ); DESCRIPTION Sets the label to the specified value. If USERID is specified, that user's label is affected rather than the "current" user. RETURN VALUES No return code. ----- NAME Leave - leaves the current channel. SYNOPSIS Leave ( ); DESCRIPTION Makes the bot leave the channel. RETURN VALUES No return code. ----- NAME Match - wildcard compare with string. SYNOPSIS Match ( string string, string pattern ); DESCRIPTION Returns non-zero if the specified 'pattern' matches the specified 'string'. ? and * are suppored wildcard characters. RETURN VALUES The result of the match. ----- NAME Mode - sets channel mode. SYNOPSIS Mode ( string line ); DESCRIPTION Sets the mode of the channel. The specified 'line' must be properly formatted. RETURN VALUES No return code. ----- NAME Output - writes to stderr. SYNOPSIS Output ( string line ); DESCRIPTION This function is used for script debugging purposes only. It sends the 'line' sent as parameter to the stderr stream. RETURN VALUES No return code. ----- NAME Rnd - returns a random number. SYNOPSIS Rnd ( int roof ); DESCRIPTION Returns a random number that is between 0 and 'roof'-1. RETURN VALUES The random number. ----- NAME Regex - performs a regex match. SYNOPSIS Regex ( string line, string regex ); DESCRIPTION Returns whether the entered 'regex' expression matches the entered 'line'. RETURN VALUES Non-zero if it matched, otherwise zero. ----- NAME Runfile - execute a file as an FPL program. SYNOPSIS Runfile ( string filename ); DESCRIPTION Executes the specified file name as an FPL program. RETURN VALUES Non-zero if the program failed in any way, otherwise zero. ----- NAME Say - talk. SYNOPSIS Say ( string line ); DESCRIPTION Send the given line to the channel. RETURN VALUES No return code. ----- NAME Send - send a line of text to a user SYNOPSIS Send ( string nick, string line ); DESCRIPTION Sends the given line to the user. This will use the DCC chat if such a one is available and in use, otherwise a /msg will be used. RETURN VALUES No return code. ----- NAME TimerAdd - adds a timer. SYNOPSIS TimerAdd ( int time, string fpl ); DESCRIPTION Adds a timer that will run the specified fpl program when the time is up. 'time' is specified in number of seconds, although the exactness of this timer will never be better than +-2 seconds. RETURN VALUES Timer id ----- NAME TimerKill - kills a started timer. SYNOPSIS TimerKill ( int timerid ); DESCRIPTION Kills the timer with the specified 'timerid'. The timerid is the return code from the TimerAdd() function. RETURN VALUES Number of seconds left until the timer would have expired. ----- NAME Time2Secs - convert a HH:MM:SS string to seconds. SYNOPSIS Time2Secs ( string time ); DESCRIPTION Returns the number of seconds that the specified input 'time' equals. The input format is ::. RETURN VALUES Number of seconds. ----- NAME UserInfo - returns info about a user SYNOPSIS UserInfo ( string nick, string subject ); DESCRIPTION Returns information about 'nick' regarding 'subject'. If 'subject' equals "level", returns the status level of the user. If 'subject' equals "ircop", returns whether the user was ircop when he/she joined. If 'subject' equals "voice", returns whether the user has the +v flag set. If 'subject' equals "chanop", returns whether the user has the +o flag set. RETURN VALUES Depends on the 'subject'. For the booleans, non-zero means true (yes), zero means false (no). -----