#!/usr/bin/perl # ############################################# # DICEBOT -- The Dice Bag of Holding!!!!!!! # ############################################# # # # This code was written by Matthew Toia. # This is version 0.1 of the code; it is # licensed under the GPL. If you find this # code useful, fun, or interesting email # feedback@fiftyvolts.com # # Special thanks to b0iler, your tutorial was # a big help in making this bot. # # on to the code! ############################################# use IO::Socket; srand(); $DICEBOTNAME = (split(m!/!, $0))[-1]; if($ARGV[0] =~ /^(-h|-help|help)$/i) { print "Usage: $DICEBOTNAME [ ]\n"; exit; } $admin = $ARGV[0] or die("You must specify admin's nick!\n"); $botname = $ARGV[1] ? $ARGV[1] : 'DiceBot'; $botchan = $ARGV[2] ? $ARGV[2] : '#dcrawl'; $addr = $ARGV[3] ? $ARGV[3] : 'washington.dc.us.undernet.org'; $port = $ARGV[4] ? $ARGV[4] : '6667'; $sock = new IO::Socket::INET ( PeerAddr => $addr, PeerPort => $port, Proto => 'tcp') or die "Conld not make connection\n"; ## #Connecting to server and logging in ## while($line = <$sock>) { ($command, $text) = parse_line($line); #send nick and ident if($line =~ /(NOTICE AUTH).*(checking ident)/i) { print "\e[34m$line\e[0m"; print $sock "NICK $botname\nUSER bot 0 0 :it's a dice bot!\n"; } #Respond to PING with PONG elsif($command eq 'PING') { print "\e[33m$line\e[0m"; pong($text, $sock); last; } #unhandled else { print "\e[34m$line\e[0m"; } } #join the chan print $sock "JOIN $botchan\n"; my @peeps; #people who Dice Bot listens to push @peeps, ($admin); #makesure Dice Bot listens to admin ## #action loop ## while($line=<$sock>) { ($command, $text) = parse_line($line); ($nick, $host, $type, $channel) = parse_command($command); ############### # Bot Actions # ############### ## #ping response ## if($command eq 'PING') { print "\e[33m$line\e[0m"; pong($text, $sock); next; } ### #channel commands ### if($channel eq $botchan) { print "\e[32m<$nick>: \e[36m$text\e[0m\n"; if($text =~ /^$botname roll (-?([0-9]+\s*d\s*[0-9]+|[0-9]+)\s*(\+|-)?\s*)+(> [a-zA-Z]*)?$/i) { foreach (@peeps) { if($_ eq $nick) { ($dice, $to, $result) = roll_dice($text); print $sock "PRIVMSG $to :$nick rolled $result on $dice\n"; last; } } } elsif($text =~ /^$botname roll stats?/i) { foreach (@peeps) { if($_ eq $nick) { ($to, @stats) = roll_stat($text); printf $sock ("PRIVMSG $to :$nick: %.2d %.2d %.2d %.2d %.2d %.2d\n", @stats); last; } } } } ### #private message commands ### if($channel eq $botname) { if($text =~ /^($botname )?roll (-?([0-9]+\s*d\s*[0-9]+|[0-9]+)\s*(\+|-)?\s*)+(> [a-zA-Z]*)?$/i) { foreach (@peeps) { if($_ eq $nick) { ($dice, $to, $result) = roll_dice($text); print $sock "PRIVMSG $to :$nick rolled $result on $dice\n"; last; } } } elsif($text =~ /^($botname )?roll stats?/i) { foreach (@peeps) { if($_ eq $nick) { ($to, @stats) = roll_stat($text); printf $sock ("PRIVMSG $to :$nick: %.2d %.2d %.2d %.2d %.2d %.2d\n", @stats); last; } } } } ### #admin commands ### if($nick eq $admin) { #quit bot if($text =~ /goodbye $botname/i) { print $sock "PRIVMSG $botchan :*sniffle* good bye all!\n"; print $sock "QUIT\n"; print "Thanks for using $DICEBOTNAME \n"; exit; } #add to peeps list elsif($type eq 'PRIVMSG' && $channel eq $botname && $text =~ /give dice/) { $peep= (split(/ /, $text))[2]; $exists=0; foreach (@peeps) { if($_ eq $peep) { $exists=1; last; } } if($exists) { next; } push @peeps, ($peep); print $sock "PRIVMSG $peep :Here's some dice!\n"; print $sock "PRIVMSG $admin :$peep has been given dice.\n"; print "\e[31m$peep added to peeps\e[0m\n"; } #remove from peeps list elsif($type eq 'PRIVMSG' && $channel eq $botname && $nick eq $admin && $text =~ /take dice/) { $peep= (split(/ /, $text))[2]; $i=0; foreach (@peeps) { if($_ eq $peep) { last; } $i++; } #if not in list won't splice anything out splice @peeps, $i, 1; print $sock "PRIVMSG $peep :No dice for you!!\n"; print $sock "PRIVMSG $admin :$peep no longer has dice.\n"; print "\e[31m$peep removed from peeps\e[0m\n"; } #make new admin elsif($type eq "PRIVMSG" && $channel eq $botname && $text =~ /^promote \S+/) { $peep = (split(/ /, $text))[1]; $exists=0; foreach (@peeps) { if($_ eq $peep) { $exists=1; last; } } if(!$exists) { push @peeps, ($peep); } print $sock "PRIVMSG $admin :You are no longer admin, $peep is.\n"; $admin=$peep; print $sock "PRIVMSG $admin :You are now my admin.\n"; print "\e[31m$admin now $DICEBOTNAME's admin\e[0m\n"; } } ## #autoremove ## if($type eq 'QUIT') { if($nick eq $admin) { print $sock "PRIVMSG $botchan :*sniffle* good bye all!\n"; print "Thank you for using $DICEBOTNAME\e[0m\n"; print $sock "QUIT\n"; exit; } $peep = $nick; foreach (@peeps) { if($_ eq $peep) { last; } $i++; } #if not in list won't splice anything out splice @peeps, $i, 1; print $sock "PRIVMSG $admin :$peep has left his dice at the door\n"; print "\e[31m$peep removed from peeps\e[0m\n"; } if($type !~ /(QUIT|PRIVMSG)/) { print "\e[34m$line\e[0m\n"; } } #utility functions sub parse_line($line) { my $command, $text; ($command, $text) = split(/ :/, $line); #delete line endings and : while($text =~ m![\r\n]!){ chop($text); } $text =~ s/://; return ($command, $text); } sub parse_command($command) { my $nick, $channel, $type, $host; ($nick, $channel, $type) = split(/ /, $command); ($nick, $host) = split(/!/, $nick); #clean up nick $nick =~ s/://; return ($nick, $host, $channel, $type); } sub pong($text, $sock) { print "\e[33mPONG $text\e[0m\n"; print $sock "PONG $text\n"; } sub roll_dice($) { my $text, $dice, $to, @rolls, $roll, $n, $s, $result; $text = shift @_; $result=0; #strip out roll command $text =~ s/($botname|roll)//ig; ($dice,$to) = split(/>/, $text); #buzz out white space, make dice lowercase $dice =~ s/\s//g; $dice=lc($dice); if($to) { $to =~ s/\s//g; } else { $to = $botchan; } $dice =~ s/-/n-/; @rolls = split(/(\+|n)/, $dice); foreach $roll (@rolls) { ($n, $s) = split(/d/, $roll); $n=int($n); $s=int($s); if($s==0) { $result+=$n; } else { for($i=0;$i<$n;$i++) { $result += int(rand($s))+1; } } } $dice =~ s/n//; return ($dice, $to, $result); } sub roll_stat($) { my $text, $to, $junk, $results, $i; $text = shift @_; #parse $to, clean it up ($junk, $to) = split(/>/, $text); if($to) { $to =~ s/\s//; } else { $to = $botchan; } for($i=0;$i<6;$i++) { for($j=0;$j<4;$j++) { $rolls[$j]=int(rand(6)+1); } @rolls = sort {return $a <=> $b;} @rolls; #sort ascending $results[$i]=$rolls[1]+$rolls[2]+$rolls[3]; } return ($to,@results); }