Kデスクトップ環境

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");