   This file documents Bobot++ by Clinton Ebadi and Etienne Bernard
(The original author who no longer works on the program).

   This document describes Bobot++ by Clinton Ebadi and Etienne Bernard
(The original author who no longer works on the program).

   This document applies to version 2.2 of the program named Bobot++.

   Copyright 2002,2004,2005 Clinton Ebadi

   Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1 or
any later version published by the Free Software Foundation; with no
Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
Texts.

1 Introduction
**************

This manual feels abused and neglected because it has almost no content.

2 Configuration
***************

Bobot++ is easy to configure. See the `examples' directory for an
example configuration.

   The main configuration file is `bot.conf'. There are several
auxiliary configuration files (a user list, aliases file, ban list, and
a script autoexec).

2.1 Configuration File Placement
================================

Bobot++ will look in `/etc/bobotpp/default/' for its default config if
none is specified on the command line. Put the configuration files you
want to be loaded by default in this directory. If you are not root, or
you want to have your own personal configuration, put it in
`~/.bobotpp/config/default/'.

2.2 Configuration Files
=======================

2.2.1 bot.conf
--------------

`bot.conf' contains key value pairs separated by `='.

   `<key> = <value>'

   Comments are started with a `#' and cause the entire line to be
ignored. _Note that this only works when the `#' is the first character
of the line_.

   bot.conf is the main configuration file for a Bobot++. The available
configuration variables are listed below in the format "VARIABLE
<default-value>: description"

   A few of the options have more complex syntax, they are documented in
their own subsections.

   * NICKNAME <Bobot>: The nickname of the bot (NICK is an alias for
     NICKNAME)

   * USERNAME <bobot>: The IRC username of the bot

   * CMDCHAR <!>: The character that prefixes commands given to the bot
     (COMMAND is an alias for CMDCHAR)

   * IRCNAME <I'm a bobot++!>: The IRC name (or 'real name') of the bot
     (REALNAME is an alias for IRCNAME)

   * USERLIST <bot.users>: Name of the file where the userlist is stored

   * SHITLIST <bot.shit>: Name of the file where the shitlist (ban
     list) is stored

   * LOGFILE <$LOGDIR/bot.log>: Location of the bot logfile (set this
     to `/dev/null' to disable logging).

   * SERVER <None>: This specifies the server to which the bot will
     connect. Note that this has a special syntax server syntax.

   * CHANNEL <None>: This specifies the channels the bot will join when
     it starts up. This has a special syntax channel syntax.

2.2.1.1 server syntax
.....................

The server syntax in `bot.conf' allows you to specify an alternate port
to connect on, and a password to send the server.

   You may use more than one server line; Bobot++ will attempt to
connect to the first one, and will connect to the next one in the list
if it fails. The bot will continue cycling through the server list
until it is able to connect to one. There is a command (`!cycle') to
make the bot to cycle servers.

   SERVER = SERVER_NAME [PORT [PASSWORD]]

   This will make Bobot++ attempt to connect to SERVER_NAME on port
PORT with the password PASSWORD. SERVER_NAME should be the address of
the server. PORT and PASSWORD are optional.

2.2.1.2 channel syntax
......................

The channel syntax in `bot.conf' allows you to specify the initial
modes the bot should set on a channel, the modes the bot should
maintain, and a key if the channel needs it.

   You may have any number of channel lines. When Bobot++ starts it will
attempt to join and gain operator status in every channel listed.

   CHANNEL = NAME:INITIAL_MODES:MODES_TO_KEEP:CHANNEL_KEY

   The bot will join NAME and set the channel modes to INITIAL_MODES
(e.g. "nt") if it is able to gain operator status. It will then
maintain MODES_TO_KEEP. If the channel requires a key to enter simply
set CHANNEL_KEY. Every argument except for NAME is optional.

   A few example lines:

     CHANNEL = #foo:nt:nt:bar

   The bot will join `#foo' with the channel key `bar' and will then
maintain the modes `nt'.

     CHANNEL = #bar:::

   The bot will join `#bar' and will not set any modes nor will it
attempt to maintain any modes.

2.2.2 bot.users
---------------

`bot.users' is the default file name of the userlist. It may be changed
in `bot.conf'. The file contains lines with the format:

   `MASK:CHANNEL:LEVEL:PROTECTION:AUTO-OP'

   * MASK is the host mask (e.g. `*!*username
     .domain.com') of the user

   * CHANNEL is a channel mask of the channels that the user has
     priviliges to use the bot in (e.g. `*' for all channels, `#*' for
     all non-local channel, `#foo*' for all channels starting with
     "foo," `#bar' for channel "#bar" only, etc.)

   * LEVEL is the user level of the user (see User Levels).

   * PROTECTION is the protection level of the user (see
     Protection).

   * AUTO-OP is set to control whether a user is automatically given
     operator priviliges on channel entry (see Automatic Op).

3 Using Bobot++
***************

FIXME: stuff here...

3.1 Starting the Bot
====================

The bot is usually installed with the binary name `bobotpp'. It accepts
the following command line arguments.

   * `[--help][-h]' - Shows detailed help and exits

   * `[--version][-v]' - Shows version information and exits

   * `[--no-background][-b]' - Run bobot++ in the foreground

   * `[--config-file file][-f]' - Use file instead of `bot.conf'

   * `[--config-dir dir][-d]' - Use dir as dir to load config file from

   * `[--config dir][-c]' - Search your config path (defaults to
     `$HOME/.bobotpp/config/' and then `/etc/bobotpp/') for dir and
     then loads your config data using dir

   * `[--sys-config dir][-s]' - Looks for config in `/etc/bobotpp/dir'.
     Note that the user dir is still searched first

   * `[--user-config dir][-u]' - Looks for config in
     `$HOME/.bobotpp/config/dir/'. Note that the system dir is still
     searched after this if dir is not found.

   * `[--debug][-D]' Makes Bobot++ print debugging info and run in the
     foreground

   * `[--debug-scripts][-S]' Enabled the Guile debugging evaluator for
     verbose script errors and backtraces while still running the bot
     in the background.

   The default configuration is read from
`$HOME/.bobotpp/config/default/' and then `/etc/bobotpp/default/' if
the user config is not found.

   The bot defaults to running in the background as a daemon.

3.2 User Levels
===============

There are several user levels available in Bobot++ to provide gradated
access to commands. `!adduser' and `bot.users' use the numeric code;
Scheme uses the textual name for the level. By default (if the user is
not found in the userlist) a user has access to commands with the level
`bot:user-none'.

  0. `bot:user-none' - No *built-in* commands may be executed _by
     default_ (commands may be added from Scheme that can be executed
     by users of level none and the level required to execute a command
     may be changed from Scheme).

  1. `bot:user-user' - Will be able to execute most commands but not
     all and cannot use masks on kicks and bans.

  2. `bot:user-trusted' - For built-ins with a default configuration
     this user has access to the same set of commands as an `user' but
     may use masks on kicks and bans. Scheme commands may be added
     which require a user to be of this level.

  3. `bot:user-friend' - In the default configuration a user who is a
     friend will be able to do everything short of stopping the bot.
     Again, there may be user added commands that require a higher user
     level.

  4. `bot:user-master' - This is the highest user level and has access
     to every feature of the bot.

3.3 Protection
==============

A user added via Scheme, the `bot.users' file, or `!adduser' may be
protected from being deoped, kicked, or banned. The user list and IRC
commands use the numeric codes, Scheme uses the symbolic names.

  0. `bot:protection/none' No protection

  1. `bot:protection/no-ban' No ban. If a user is banned the bot will
     unban him..

  2. `bot:protection/no-kick' No kick. The user may still be kicked but
     the bot will kickban the user who kicked the protected user.

  3. `bot:protection/no-deop' No deop. The bot will ensure that the
     user always maintains operator status.

3.4 Automatic Op
================

A user may be automatically given operator status upon entering a
channel. Scheme uses the symbolic name, the user list (`bot.users') and
IRC commands use the numeric value.

  0. `bot:aop/no' Do not automatically op the user

  1. `bot:aop/yes' Do automatically op the user

3.5 Built-In Commands
=====================

Bobot++ has many built-in commands that make it useful without
scripting support. The reference leaves off the command char; remember
to use whatever you defined the command char to be in `bot.conf'. If a
command needs the channel name then you must specify the channel as the
first argument to the command when private messaging the bot a command.

COMMAND        NEEDS       MIN LEVEL   DESCRIPTION
               CHANNEL     TO USE
`action' `do'  Yes         USER         Causes the bot to perform the
                                       action `do' in the current channel.
`adduser'
`addserver'                            Adds the server specified by HOST
                                       NAME or IP ADDRESS to the server
                                       list.
`addshit'
`alias'                                Makes an alias, and adds the
                                       function NEW NAME, that will do
                                       exactly the same command as OLD
                                       NAME.
`ban'                                  Bans MASK or NICK from CHANNEL. You
                                       need to be a trusted user to ban
                                       with a MASK.
`banlist'
`channels'                             Prints the channel(s) where the bot
                                       is currently.
`cycle'        Yes                     Makes the bot leave and join
                                       CHANNEL.
`dcclist'                              Gives the list of all DCC Chat
                                       connections.
`deban'        Yes                     Debans MASK or NICK from CHANNEL.
                                       You need to be a trusted user to
                                       deban with a MASK.
`delserver'                            Deletes server from server list
                                       whose number in the server list is
                                       SERVER NUMBER.
`deluser'                              Removes NICK or MASK from the
                                       userlist.
`delshit'                              Removes NICK or MASK from the
                                       shitlist.
`deop'         Yes                     Deops MASK or NICK on CHANNEL.
`die'                                  Makes the bot stop immediately.
`do'
`execute'                              *Only available if scripting
                                       support is enabled*
`help'
`ident'                                Identifies you on the bot. Note
                                       that you should not use this
                                       command in public ...
`invite'       Yes                     Invites NICK on CHANNEL.
`join'                                 Makes the bot join CHANNEL.
`keep'         Yes                     Sets the MODES that the bot will
                                       keep for CHANNEL.
`kick'         Yes                     Kicks MASK or NICK out of CHANNEL,
                                       because of REASON. You need to be a
                                       trusted user to use a MASK.
`kickban'      Yes                     Bans then kicks MASK or NICK out of
                                       CHANNEL, because of REASON. You need
                                       to be a trusted user to use a MASK.
`load'                                 Reloads the userlist from disk.
`loadscript'                           *Only available if scripting
                                       support is enabled*
`lock'                                 Locks topic on CHANNEL.
`mode'         Yes                     Sends MODE STRING as mode for
                                       CHANNEL.
`msg'
`names'        Yes                     Shows the nicknames and status of
                                       users on CHANNEL.
`nextserver'                           Makes the bot connect to the next
                                       server in its server list.
`nick'                                 Makes the bot use nickname NICK.
`nslookup'                             Does a nameserver query about NICK
                                       host, HOST or IP ADDRESS.
`op'           Yes                     Ops NICK on CHANNEL.
`part'         Yes                     Makes the bot leave CHANNEL.
`password'                             Changes your password on the bot.
                                       Use `NONE' as password if you want
                                       to clear it. Do not use this
                                       command in public!
`reconnect'                            Makes the bot reconnect to its
                                       current server.
`rspymessage'                          Removes you from the spy list.
`save'                                 Saves the userlist.
`say'          Yes                     Makes the bot say MESSAGE on
                                       CHANNEL.
`server'                               Select the server to connect to.
                                       SERVER NUMBER is the number of the
                                       server in the serverlist.
`serverlist'                           Shows the bot's serverlist.
`setfloodrate'
`setversion'
`shitlist'                             Shows the bot's shitlist.
`spylist'                              Shows the bot's spylist.
`spymessage'                           Adds you to the spylist
`stats'        Yes                     Gives CHANNEL's statistics.
`tban'         Yes                     Bans NICK or MASK from CHANNEL for
                                       TIME seconds.
`tkban'        Yes                     Bans NICK or MASK from CHANNEL for
                                       TIME seconds, then kicks him/them
                                       because of REASON.
`topic'        Yes                     If no TOPICis given, prints
                                       CHANNEL's topic. Otherwise, the bot
                                       will change CHANNEL's topic to
                                       TOPIC.
`unlock'       Yes                     Makes the bot unlock topic on
                                       CHANNEL
`userlist'                             Shows the bot's userlist
`who'          Yes                     Show your level on CHANNEL
`whois'        Yes                     Shows information about NICK on
                                       CHANNEL

4 Scripting
***********

Bobot++'s most powerful feature is its scripting system. You write
scripts using Guile Scheme. This manual does not cover how to use Guile
or how to learn Scheme. See Guile Reference Manual (guile), for
the Guile reference manual and
`http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme.html' for a
good tutorial on Scheme.

   Note that in previous versions the scripting commands where in the
form `bot-FUNCTION'. They are now in the form `bot:FUNCTION'. The old
names are still available, but are deprecated and will be removed in
Bobot++ 3.0. New commands are only available with the `bot:' prefix.
The command `perl -pi -e ``s/bot-/bot:/g'' YOUR-FILES' should be enough
to convert your code to use the new functions.

   *NOTE*: All arguments to functions and hooks called by the bot are
strings unless otherwise specified.

4.1 Adding New Commands
=======================

Adding a new command is simple. To register a new command use
`bot:addcommand'.

 -- Function: bot:addcommand name func needs-channel? num-of-args
          min-level
     The NAME is a string representing the name of the command being
     added.  FUNC is a function accepting NUM-OF-ARGS arguments.
     NEEDS-CHANNEL? is a bool that is true if the function needs the
     channel name as its first arg, and false otherwise.  NUM-OF-ARGS
     is the number of args FUNC will take and must be within zero (0)
     and twenty (20).  MIN-LEVEL is one of the Scheme User Levels.
     A user must be at least a `min-level' user to use the
     new command.  None of the arguments are guaranteed to be passed;
     if they aren't they are set to the empty string `""'.  An example
     of a new command would be:

          (define (hello channel name)
            (if (string=? name "")
              (bot:say channel "Hello world!")
              (bot:say channel (string-append "Hello " name "!")))

          (bot:addcommand "hello" hello #t 2 0)

     This will display "Hello World!" if called as `!hello' and "Hello
     World USER" if called as `!hello USER'.

4.2 Hooks
=========

Hooks are a powerful feature of Bobot++. Hooks are a hybrid of ircII
and tiny fugue (a MUD bot) hooks with a little bit of extra stuff added
in. A hook is called when a regular expression is matched against a
message sent to or by the bot.

   Bobot++ uses different hook types for each IRC message type, and also
includes a hook for accessing raw irc messages. Hooks are tagged with a
priority and a flag that specifies whether to call the next hook that
matches after calling the current one or to stop processing.

   Hooks are processed from the highest to lowest priority, with
fallthrough hooks of equal priority to non-fallthrough hooks being
executed first.

4.2.1 Creating a Hook
---------------------

To add a new hook you use the function `bot:addhook'.

 -- Function: bot:addhook type regex function [pri fall name]
     TYPE specifies the type of hook (the types of hooks are listed in
     Hook Types).

     REGEX is a standard regular expression. If REGEX is matched,
     FUNCTION will be called.

     FUNCTION will take a different number of args depending on the
     hook type.

     PRI specifies the priority of the hook--higher priority hooks are
     executed first. This argument is optional and defaults to `0'.

     FALL is `#t' if the hook is a fallthrough hook and `#f' is the
     hook is not a fallthrough hook. This arg is also optional and
     defaults to `#t'.

     NAME is the optional name of the hook that defaults to
     `"DEFAULT"'. If you set the name then you can have more than one
     hook that matches the same regexp, as long as they have the same
     name. E.g. in a log script you could have the regexps for the log
     function all be `".*"' and set their names to `"log"' to avoid a
     conflict with other hooks.

4.2.2 Hook Types
----------------

The following sections document the different hooks Bobot++ exposes.

   The general format of each hook description is as if it were a
function to be defined, but these describe the function to be passwd to
`bot:add-hook'.  Do _not_ name your functions these names.

   That said, here is the list of available hooks functions.  FIXME:
write docs

4.2.2.1 Receieved Message Hooks
...............................

The following hooks are triggered when a mesage is received by the bot.

 -- Function: hooks/action from to action
     This hook is triggered when someone performs an action.

     FROM is the nickname the person that performed the action.

     TO is the target of the action, which is either a channel or the
     Bot's nick if the user private messages the bot.

     ACTION is the text of the action. E.g. if someone did `* foobar
     does baz', then ACTION would be the string `"does baz"'.

 -- Function: hooks/nickname old-nick new-nick
     This hook is called when someone changes his nickname from
     OLD-NICK to NEW-NICK.

 -- Function: hooks/signoff nick message
     This hook is called when someone signs off of IRC.

     NICK is the nickname of the person signing off.

     MESSAGE is his quit message

 -- Function: hooks/ctcp nick to command rest
     This hook is called when a CTCP request is received by the bot.

     NICK is the nickname of the sender.

     TO is the target of the CTCP request. This will either be a
     channel the bot is in, or the nickname of the bot.

     COMMAND is the CTCP command issued.

     REST contains the arguments to the CTCP command.

 -- Function: hooks/ctcp-reply nick command rest
     This hook is called when a CTCP REPLY is received. This occurs when
     the bot has sent a CTCP request to another client. The CTCP REPLY
     is always addressed to the bot directly.

     NICK is the nickname of the person who replied.

     COMMAND is the command to which NICK is replying.

     REST contains the body of the reply.

 -- Function: hooks/disconnect server intentional
     This is called when the bot is disconnected from a server.

     SERVER is the hostname of the server from which the bot was
     disconnected.

     INTENTIONAL is a flag set to `#t' when the bot disonnected from
     the server as the result of a command (issued by a user from IRC,
     SIGHUP, or from a script), or `#f' when the bot disconnected from
     the server unintentionally..

 -- Function: hooks/invite nick channel
     This hook is called when a user invited the bot to join a channel.

     NICK is the nickname of the user who sent the invite.

     CHANNEL is the channel to which the bot was invited.

 -- Function: hooks/join nick channel
     This is called when a user or the bot joins a channel.

     NICK is the nickname of the user who joined CHANNEL. This may be
     the bot's nickname (the IRC server sends the JOIN command back to
     the the bot after it joins a channel).

     CHANNEL is the channel that was joined

 -- Function: hooks/kick target from channel reason
     This hook is called when a user, including the bot, is kicked out
     of a channel.

     TARGET is the nick of the user who was kicked. This may be the
     bot's nick.

     FROM is the nick of the user who issued the kick. This may also be
     the bot's nick.

     CHANNEL is the channel the kick was issued in.

     REASON is the reason the user was kicked.

 -- Function: hooks/part nick channel
     This hook is called when a user parts a channel.

     NICK is the user who parted the channel. This may be the bot.

     CHANNEL is the channel from which the user parted.

 -- Function: hooks/mode nick target modes
     This hook is called when someone sets the modes of TARGET.

     NICK is the user who set the modes. This may be the bot.

     TARGET is the target of the MODE command. This may be a channel or
     a user. If it is a user, it may be the bot.

     MODES is the MODE string.

 -- Function: hooks/message nick message
     This hook is called when someone sends a private message to the
     bot.

     NICK is the nickname of the user who sent the message.

     MESSAGE is the message the user sent.

 -- Function: hooks/notice nick message
     This hook is called when a user send a private notice to the bot.

     NICK is the user who sent the notice.

     MESSAGE is the message the user sent.

 -- Function: hooks/public nick channel message
     This hook is called when a user sends a normal message to a
     channel.

     NICK is the user who sent the message.

     CHANNEL is the channel to which the message was sent.

     MESSAGE is the message that was sent.

 -- Function: hooks/public-notice nick channel message
     This hook is called when a user send a notice to a channel.

     NICK is the user who sent the notice.

     CHANNEL is the channel to which the notice was sent.

     MESSAGE is the message that was sent.

 -- Function: hooks/raw raw-message
     This hook is called every time a message is received. This matches
     on the raw message text and passes the hook function the raw IRC
     message.

     RAW-MESSAGE is the raw IRC message.

 -- Function: hooks/topic nick channel new-topic
     This hook is called when a user changes the topic in a channel.

     NICK is the user who set the topic. This may be the bot.

     CHANNEL is the channel that's topic was changed.

     NEW-TOPIC is the new topic.

4.2.2.2 Sent Message Hooks
..........................

These hooks are called when the bot sends a message. MYNICK is always
the bot's nick and will not be documented in each hook description.

 -- Function: hooks/send/public mynick channel message
     This hook is called when the bot sends a normal message to a
     channel.

     CHANNEL is the channel to which the bot sent the message.

     MESSAGE is the message the bot sent.

 -- Function: hooks/send/message mynick to message
     This hook is called when the bot sends a private message to a user.

     TO is the nick of the user to whom the message was sent.

     MESSAGE is the message that was sent.

 -- Function: hooks/send/action mynick to message
     This hook is called when the bot sents an action to a channel or a
     user.

     TO is the channel or nick of the user to which the action was sent.

     MESSAGE is the text of the action.

 -- Function: hooks/send/ctcp mynick to command message
     This hook is called when the bot sends a CTCP message _other than_
     an ACTION to a channel or user.

     TO is the channel or nick of the user to which the CTCP was sent.

     COMMAND is the CTCP command that was sent.

     MESSAGE is a string containing the arguments to the CTCP command.

4.2.2.3 DCC CHAT Hooks
......................

These hooks are called when a user initializes a DCC CHAT and when the
bot receives messages from the user in a DCC CHAT.

 -- Function: hooks/dcc/chat-begin from
     This hook is called when a user begins a DCC CHAT with the bot.
     FROM is the user's address in the form `nick!user@host'.

 -- Function: hooks/dcc/chat-end address
     This hook is called when a DCC CHAT is purged after being idle for
     a while, or when the user closes the DCC CHAT. As such, you cannot
     write any more data to the DCC CHAT.

     ADDRESS is the address (nick!user@host) of the person on the other
     side of the DCC.

 -- Function: hooks/dcc/chat-message from message
     This hook is called when a user sends a message to the bot through
     a DCC CHAT.

     FROM is the user's address in the form `nick!user@host'.

     MESSAGE is the message the user sent to the bot.

4.2.2.4 Miscellaneous Hooks
...........................

 -- Function: hooks/flood nick
     This hook is called when a user is detected flooding the bot.

     NICK is the nickname of the user flooding the bot.

 -- Function: hooks/timer time
     This hook is called once a minute. The regex is *not* used.

     TIME is the in zero-padded `hh:mm' format.

4.3 Scheme User Levels
======================

There are five levels that a user may be when interfacing with a bot:
NONE, USER, TRUSTED_USER, FRIEND, MASTER. The Scheme variables for the
user levels are `bot:user-none', `bot:user-user', `bot:user-trusted',
`bot:user-friend', and `bot:user-master'. See User Levels for
more information on User Levels.

   When adding a new command, think about who should be able to use it.
Is your command a general purpose command that helps the channel (e.g.
`!seen') that everyone should be able to use? Or is it something that
should be restricted? See User Levels for information on what
level users can do what with the built in bot commands and think about
what level a user your command is targetted towards. You must be _very_
careful when giving new commands to lower level users because you can
do basically everything the bot can do with a script. As the scripting
interface becomes more powerful, you must think more about what users
can use new commands you add.

4.4 Sending Messages
====================

There are several types of messages you can send with Bobot++ from
scripts. There is the simple, but rather limited, `bot:say',
`bot:action' and `bot:msg', and the more powerful, but lower level,
`bot:send-MESSAGE' functions. Most bots will probably only need the
higher level functions, but for the sake of why-not Bobot++ lets you
use the lower level functions (in progress).

4.4.1 "High Level" Message Functions
------------------------------------

 -- Function: bot:say channel message
     Send a public or private MESSAGE to CHANNEL.

     Sends a normal text message, as if a user had typed it in.  The
     DEST can be a nickname or a channel.

 -- Function: bot:action channel message
     Send an "action" type  MESSAGE to CHANNEL

 -- Function: bot:msg nick message
     The same as if a user typed `/msg nick message' to their IRC
     client.

 -- Function: bot:notice target message
     Sends MESSAGE as a NOTICE to TARGET. TARGET may be a user (nick)
     or a channel. This returns 0 on success.

4.4.2 "Low Level" Message Functions
-----------------------------------

The "Low Level" messaging functions allow you to do things like send
CTCP messages. You probably want to read rfc 2812 and the CTCP spec
before using these. If you have no idea what these do, read rfc 2812
(IRC Client Protocol) and CTCP spec. These functions all return
`*unspecified*' always, so don't use the return value for anything.

 -- Function: bot:send-ctcp to command message
     TO is the target of your CTCP message, COMMAND is the CTCP
     command, and MESSAGE is the message (or arguments) of the command.
     Make sure to `bot:ctcp-quote' the message!

 -- Function: bot:send-ctcp-reply to command message
     TO is the target of your CTCP reply, COMMAND is the CTCP command,
     and MESSAGE is the message (or arguments) of the command. Make
     sure to `bot:ctcp-quote' the message!

     This is used to reply to a ctcp that the bot has received.

4.5 Misc. Scripting Stuff
=========================

These are a few useful things that I thought people writing scripts
might want to know.

   If you want to execute code when the bot exits, just do `add-hook!
bot:exit-hook THUNK' where THUNK is an argumentless procedure (a
thunk). When the bot exits your thunk will be called.

     [ I didn't know where to put any of these, so I just stuck them in
     here.

     There probably needs to be several sections added, like dealing
     with users (kicking, added, etc), dealing with the bot (channels,
     nickname of the bot, etc), server issues (serverlist), useful
     tools (nslookup, whois), and do on. ]

 -- Function: bot:adduser nick-or-mask cbannel-mask level prot auto-op
     Adds an user to the userlist, for a `nick!user@host' matching the
     one given, on a channel matching the CHANNELMASK given.

     The LEVEL can be:      The PROT can be:       The AUTO-OP can be:
     0 - No level           0 - No protection      0 - No auto-op
     1 - User               1 - No ban             1 - Op on join
     2 - Trusted User       2 - No kick
     3 - Friend             3 - No deop
     4 - Master

 -- Function: bot:addserver hostname ip-address [portnumber]
     Adds the server specified by HOSTNAME or IP-ADDRESS to the server
     list.

 -- Function: bot:addshit nick-or-mask channel-mask level [time reason]
     Adds an user to the shitlist, for a nick!user@host matching the
     one given, on a channel matching the CHANNELMASK given.

          The LEVEL can be:
            0 - No shit
            1 - No op
            2 - Kick and Ban on join
            3 - Kick and Ban on join, no deban

 -- Function: bot:ban channel mask-or-nick
     Bans MASK or NICK from CHANNEL. You need to be a trusted user to
     ban with a MASK.

 -- Function: bot:change-command-level nick-or-mask channel-mask
          new-level
     Gives NICK or MASK level NEW-LEVEL on channel(s) CHANNEL-MASK.
     Note that you can not change level for someone whose level is
     greater than yours, and that you can not give a level greater than
     yours.

 -- Function: bot:cycle channel
     Makes the bot leave and join CHANNEL.

 -- Function: bot:deban channel mask-or-nick
     Debans MASK or NICK from CHANNEL. You need to be a trusted user to
     deban with a MASK.

 -- Function: bot:delserver server-number
     Deletes server from server list whose number in the server list is
     SERVER-NUMBER

 -- Function: bot:deluser nick-or-mask channel-mask
     Removes NICK or MASK from the userlist.

 -- Function: bot:delshit nick-or-mask channel-mask
     Removes NICK or MASK from the shitlist.

 -- Function: bot:deop channel mask-or-nick
     Deops MASK or NICK on CHANNEL.

 -- Function: bot:die reason
     Makes the bot stop immediately.

 -- Function: bot:do ?

 -- Function: bot:invite channel nick
     Invites NICK on CHANNEL.

 -- Function: bot:join channel
     Makes the bot join CHANNEL.

 -- Function: bot:keep channel modes
     Sets the MODES that the bot will keep for CHANNEL.  See also STATS.

 -- Function: bot:kick channel mask-or-nick [reason]
     Kicks MASK or NICK out of CHANNEL, because of REASON.  You need to
     be a trusted user to use a MASK.

 -- Function: bot:kickban channel mask-or-nick [reason]
     Bans then kicks MASK or NICK out of CHANNEL, because of REASON.
     You need to be a trusted user to use a MASK.

 -- Function: bot:lock channel
     Locks topic on CHANNEL.

 -- Function: bot:logport
     [ Probably returns the log port? ]

 -- Function: bot:mode channel mode-string
     Sends MODE-STRING as mode for CHANNEL.

 -- Function: bot:nextserver
     Makes the bot connect to the next server in its server list.

 -- Function: bot:nick nick
     Makes the bot use nickname NICK.

 -- Function: bot:op channel nick
     Ops NICK on CHANNEL.

 -- Function: bot:part channel
     Makes the bot leave CHANNEL.

 -- Function: bot:reconnect
     Makes the bot reconnect to its current server.

 -- Function: bot:server server-number
     Select the server to connect to. SERVER-NUMBER is the number of
     the server in the serverlist.

 -- Function: bot:setfloodrate ?

 -- Function: bot:setversion ?

 -- Function: bot:tban channel nick-or-mask time
     Bans NICK or MASK from CHANNEL for TIME seconds.

 -- Function: bot:tkban channel nick-or-mask time [reason]
     Bans NICK or MASK from CHANNEL for TIME seconds, then kicks
     him/them because of REASON.

 -- Function: bot:topic channel topic
     If no TOPIC is given, prints CHANNEL's topic. Otherwise, the bot
     will change CHANNEL's topic to TOPIC.

 -- Function: bot:unlock channel
     Makes the bot unlock topic on CHANNEL.

 -- Function: bot:getnickname
     [ Gets the bot's nickname? ]

 -- Function: bot:getserver

 -- Function: bot:getserverlist

 -- Function: bot:flush
     [ Flushes the socket to the server? ]

 -- Function: bot:flushport
     [ Flushes the log port? ]

 -- Function: bot:random ?
     [ Returns a random number?  What range?  Why? ]

 -- Function: bot:delcommand
     [ Probably deletes a command added with `bot:addcommand' ? ]

 -- Function: bot:addtimer ? ?

 -- Function: bot:deltimer ?

 -- Function: bot:dcc-chat-send ? ?

     [ And what about the stuff defined in `bobot-utils.scm' ? I just
     added it here so it could be somewhere.  There should also be a
     section dealing with modules.  How to use them.  What module
     scripts are in.  What module bobot++ provided primites are in.
     And so on. ]

 -- Function: bot:log . messages
     Write as many MESSAGES as you want to the log.  If the arg is a
     thunk it will be executed and it's output will be written to the
     log.

 -- Function: bot:load file

 -- Function: bot:load-module module-spec

 -- Function: bot:use-module module-spec

 -- Function: bot:match-not-channel regex
     match-not-channel adds a prefix regex to your REGEX so it doesn't
     match the sender or channel in a PUBLIC message

 -- Function: bot:match-to-me regex
     match-to-me matches text that was addressed to the bot with a ':',
     ',',  or nothing after the bot name.

 -- Function: bot:sent-to-me? message

 -- Function: bot:ctcp-quote message
     Returns the CTCP quoted message Input _MUST NOT_ contain the
     trailing `\r\n' (it is added by the message sending code).

 -- Variable: %bot:loadpath

 -- Function: %bot:load-extensions