#!perl -W #[00:21] < bt> netking sits on his internet throne which is a really nice thinkgeek desk and a riced out computer with 3 apple cinema displays #[00:21] < bt> And he has a crown which is some wearable wi-fi computer VR goggles contraption thing use strict; use warnings; use Megahal; use Net::IRC; use Time::HiRes qw(time alarm); use Getopt::Long; my $quitmsg = 'lolz'; my $hub_bot = '[RH]Mitsuki'; my $RECONNECT_TIME = 300; my @fail_servers = (); my @ignore=('[RH]Tomoyo'); # other bots and idiots to ignore my $last_save = time(); my %opts = ( quiet => 0, debug => 0, save_interval => 60 * 200, # how often to save megahal's brain nick => 'hal', ); sub dprint { print @_ if $opts{debug} }; GetOptions(\%opts, 'debug!', 'quiet!', 'save_interval=i', 'nick=s') or die "options parsing failed"; # list of server hashrefs, suitable for passing into Net::IRC::new() my @servers = ( { Nick => "netking", Server => "mint.sayuri.ca", Ircname => "megahal", Quitmsg => "$quitmsg", Channels => ["#raspberryheaven","#marimite"] }, { Nick => "megahal", Server => 'irc.freenode.net', Ircname => "megahal", Quitmsg => "$quitmsg", Channels => ["#fink","#opendarwin","#iThink","#macdev"] }, # { # Nick => $opts{nick}, # Server => 'irc.bloodandcoffee.net', # Ircname => "megahal", # Quitmsg => "$quitmsg", # Channels => ["#kilonet"] # }, { Nick => 'netking', Server => 'irc.zirc.org', Ircname => "megahal", Quitmsg => "$quitmsg", Channels => ["#onebutan","#iichan"] }, { Nick => 'netking', Server => 'irc.corezx.com', Ircname => "megahal", Quitmsg => "$quitmsg", Channels => ["#4chan","#1"] }, ); # set up alarm callback and start alarm $SIG{ALRM} = \&reconnect_servers; alarm($RECONNECT_TIME); my $irc = new Net::IRC; #my $gimmick = new Megahal( # 'AutoSave' => 1, # save brain on exit #); Megahal::megahal_initialize(); # ignore myself push @ignore,$opts{nick}; foreach my $server (@servers) { dprint "setting up server: $server->{Server}\n"; $server->{conn} = $irc->newconn(%$server); if (defined($server->{conn})) { $server->{conn}->add_handler('endofmotd', \&on_connect); $server->{conn}->add_handler('public', \&irc_public); $server->{conn}->add_handler('disconnect', \&irc_disconnect); $server->{conn}->add_handler('msg', \&irc_privmsg); } else { push @fail_servers, $server; } } dprint "starting irc...\n"; $irc->start; ##################################### # What to do when the bot successfully connects. # Net::IRC::Event handler sub on_connect { dprint "on_connect: entering\n"; my $self = shift; my $server = find_server($self); dprint "on_connect: my server is $server->{Server}\n"; $self->privmsg("NickServ","identify 3mv33b33"); dprint "on_connect: joining channels...\n"; foreach my $channel (@{$server->{Channels}}) { dprint "on_connect: joining $channel\n"; $self->join($channel); } } sub irc_privmsg { my ($self, $event) = @_; my $txt = $event->{args}[0]; my $to = $event->{to}[0]; my $from = $event->{from}; $txt =~ s/^\s+//; #if ($from =~ s/NickServ//) {return;} if ($txt =~ s/^!rejoin (.*)//) {$self->join("$1"); print "joining $1";} else { my $reply = Megahal::megahal_do_reply($txt,0); $from =~ s/!.*$//; $self->privmsg("$from", "$from: $reply"); } } # Listen to dialog on the channel and send it to megahal for processing. # Net::IRC::Event handler sub irc_public { my ($self, $event) = @_; my $txt = $event->{args}[0]; my $from = $event->{from}; my $to = $event->{to}[0]; my $server = find_server($self); my $mynick = $server->{Nick}; # strip speaker's host info $from =~ s/!.*$//; dprint "$to: <$from> $txt\n"; # if speaker on ignorelist, don't even process the line return if grep {$from eq $_} @ignore; # convert hubchat to normal chat if ($from eq $hub_bot) { if ($txt =~ s/^<(.+?)> //) { $from = $1; }; }; # see if they're talking to somebody in particular my $audience = ''; if ($txt =~ s/^([^\s]+?)[:;,] //) { $audience = $1; }; # process the message and think up a response $txt =~ s/^\s+//; dprint "thinking about: $txt\n"; # my $reply = $gimmick->megahal_learn_no_reply($txt,0); # $reply =~ s/nurupo//; # if they're talking to me, talk back if (lc($audience) eq lc($mynick)) { if ($opts{quiet} || "$to" eq "#4chan") { # dprint "(muted) >> $from: $reply\n"; # my $reply = $gimmick->megahal_learn_no_reply($txt,0); } else { # my $reply = $gimmick->megahal_learn_no_reply($txt,0); my $reply =Megahal::megahal_do_reply($txt,0); # dprint ">> $from: $reply\n"; $self->privmsg("$to", "$from: $reply"); }; } else { Megahal::megahal_learn_no_reply($txt,0); # dprint "(to myself) >> $from: $reply\n"; }; # see if it's time to force a brain save CheckSave(); } # try to reconnect to any servers we failed to connect to before # runs on an alarm() sub reconnect_servers { dprint "reconnect_servers: entering\n"; my @retry_servers = (); while (my $server = pop(@fail_servers)) { dprint "reconnect_servers: trying server: $server->{Server}\n"; my $self = $server->{conn}; if (defined($self)) { $self->connect(%$server); if (not $self->connected) { push @retry_servers, $server; } } else { $server->{conn} = $irc->newconn($server); if (not defined($server->{conn})) { push @retry_servers, $server; } } } @fail_servers = @retry_servers; alarm($RECONNECT_TIME); } # given a Net::IRC::Connection object, figure out # which of our servers it belongs to sub find_server { my $self = shift; foreach my $server (@servers) { if ($server->{conn} eq $self) { return $server; } } return undef; # uh-oh } # Net::IRC::Event handler sub irc_disconnect { my $self = shift; my $server = find_server($self); push @fail_servers, $server; } # Check to see if it's been long enough since the last save for us to save # megahal's brain again. sub CheckSave { my $time = time(); if ($last_save + $opts{save_interval} < $time) { $last_save=$time; rename("megahal.dic","megahal.dic.".$time); rename("megahal.brn","megahal.brn".$time); Megahal::megahal_cleanup(); } } # sub _stop { # foreach my $server (@servers) { # $server->{conn}->disconnect; # } # printlog("Exiting..."); # close(LOGFILE); # } # sub printlog { # my($date) = scalar localtime(); # my $t = $_[0]; # $t =~ s/%/%%/g; # $t =~ s/\cC/%C/g; # $t =~ s/\cB/%B/g; # $t =~ s/\cR/%R/g; # $t =~ s/\cV/%V/g; # $t =~ s/\cO/%O/ig; # $t =~ s/\n//g; # print(LOGFILE "$date: $t\n"); # }