# 5.7. Bots

It is possible to make bots in sirc script, just like you make bots in ircII. It's even probably not a bad idea, since you have a proper and powerful programming language (perl) at your disposition, with all the boring network programming and parsing of server stuff already done for you.

However, sirc was never meant as a bot client, and I have no intention of filling it up with bells and whistles for bot support, so I've only provided minimal support for this, with the -l and -q options.

The idea is, you program your bot as a set of internal functions and hooks and a calls to `&addhook` and to `&docommand`, and then load the sirc this way (obviously without ssfe):

`nohup sirc -d -q -l <botfile> -i <bot's ircname> <nick> <server> >/dev/null &`

All of this without the `<>'s`, of course. The `>/dev/null` is there to suppress the output, since you won't be reading it on the screen anyway.

In the bot, make sure you catch (with a numeric hook) the lines that tell `"nick in use"` or `"invalid nick"`, and send lines to the server with some random nick, and get them skipped, or the bot will freeze trying to ask the user for a nick. You should also set up a hook on `"disconnect"`, and make it do a `&docommand("server 0")` or `"server some.server"`.

Also remember that the file gets loaded even before the server connection is made, so calls to `&sl` and most `&docommand's` at that point will fail.

Here's an example of a bot that connects, joins a channel, reconnects if disconnected, responds to a few commands, ops its owner, and logs all it sees except public stuff to a file; you'd load this one, assuming you saved it in a file called "mybot" and want to call it BubbleBot, with:

`nohup sirc -d -q -l mybot -i "bot in sirc" BubbleBot some.server.edu >/dev/null`

     $botowner="espel\@clipper.ens.fr";	# change it to your address

     $logfile=$ENV{'HOME'}."/.botlog";
     &docommand("log on");

     sub hook_publicstuff {		# don't print the public chatter (so it
       $silent=1;			# doesn't fill the logfile
     }
     &addhook("public", "publicstuff");

     sub hook_connected {
       &sl("JOIN #BotTub");
     }
     &addhook("376", "connected");   # join on the "end of MOTD" numeric

     srand;				# init random number generator

     sub hook_badnick {
       local($n);
       $n="B".(int(rand(1000000))+4587454);  # send a garbage nick...
       &sl("NICK $n");
       $skip=1;
     }
     &addhook("432", "badnick");             # if told that ours is taken
     &addhook("433", "badnick");

     sub hook_disc {         # if we got disconnectedj
       sleep(30);		# wait 30 seconds (so we don't bring the machine
     			# down to a crawl if the server is down)
       &docommand("server 1"); # reconnect to the same server
     }
     &addhook("disconnect", "disc");

     sub hook_joined {	# whenever someone joins
       local($ch)=($_[0]);
       $ch =˜ tr/A-Z/a-z/;	# put channel in lowercase
       if (&eq($botowner, "$user\@$host") && $haveops{$ch}) {
         &sl("MODE $ch +o $who");	# op if that's the owner and we have ops
       }
     }
     &addhook("join", "joined");

     sub hook_message {
       if (&eq($botowner, "$user\@$host")) {  # if it's a msg from the owner
         if ($_[0] =˜ /^die$/i) {             # die -> die
           &docommand("quit");
         } elsif ($_[0] =˜ /^say /i) {        # say <something> -> say it
           &say($');
         } elsif ($_[0] =˜ /^nick /i) {       # nick <nick> -> change nicks
           &sl("NICK $'");
         }
     # add more commands here
       }
     }
     &addhook("msg", "message");