#!/usr/bin/perl use strict; use warnings; use IO::Socket; ## globals use vars qw/@buckleyisms $sock %CONF %results $hyp/; $|=1; $CONF{file} = shift; if (not $CONF{file}) { $CONF{file}=$0; $CONF{file}=~s/\.pl$/\.conf/i; } &readconf(); $sock=&connect($CONF{server},$CONF{port}); &error("socket: $! $@") if ($sock eq ""); &send("NICK $CONF{nick}"); &send("USER $CONF{ident} 0 * :$CONF{gecos}"); &forks() if (not $CONF{debug});; my ($auth, @buffer) ; $auth =""; @buffer=(); my ($from,$command,@data); #list of friends (people who get buttified more often) and enemies (people who dont get butted.) my (%friends, %enemies); #frequency that normal people and friends get butted my ($normalfrequency, $friendfrequency); #last thing said by someone in the channel my (@previousdata); my ($previouschannel); my (@channels); my ($starttime); my (%linestotal); my (%timeoflastbutting); my ($fullstring); my $graceperiod = 240; #pre-setting frequencies $friendfrequency = 23; $normalfrequency = 37; #remove whitespace! $CONF{channel} =~ s/\s+//; #add friends from conf file if (exists $CONF{friends}) { @_ = split(/s*,s*/,$CONF{friends}); foreach $_ (@_) { $friends{$_} = 1; } } #add enemies from conf file if (exists $CONF{enemies}) { @_ = split(/s*,s*/,$CONF{enemies}); foreach $_ (@_) { $enemies{$_} = 1; } } getbuckleyisms(); #main execution loop while (1) { #check for errors. &error("main: $! $@") if (($! ne "" ) || ($@ ne "")); #Otherwise move through the buffer. @buffer=split(/\n/,&gets()); foreach my $thing (@buffer) { print "$thing\n"; $fullstring = $thing; #putting the message from $thing into a full string to preserve the whitespace, just in case. $fullstring =~ s/(.*?)\s+(.*?)\s+(.*?)\s+(.*)/$4/; $fullstring =~ s/^://; ($from,$command,@data)=split(/\s+/,$thing); $from ||= ''; $command ||= ''; #if server pings, ping back. if ($from eq "PING") { if ($command=~/^:\d+$/) { &send("PONG $command"); } else { &send("PONG :$CONF{nick}"); } } &error("from server: @data") if ($from eq "ERROR"); #If it has successfully connected to the server, join a channel. if ($command eq "001") { if (defined $CONF{channel}) { &send("JOIN $CONF{channel}") ; $starttime = time; #&send("PRIVMSG $CONF{channel} : BUTTING SYSTEMS ONLINE!"); } } #otherwise, if it's a message elsif ($command eq "PRIVMSG") { #get destination of message my $to=shift(@data); #get first word of message (might be command) my $sub=shift(@data); ## remove preceding ':' $sub=~s/^://; ##if a user private messages the bot... if ($to eq $CONF{nick}) { $to = $from; $to =~ s/^:(.*)!.*$/$1/; #!help helps a brotha out, yo if ($sub eq "!help") { &send("PRIVMSG $to : Buckleybot helpfully points out the humor in the current situation."); } ##if the first word in the string is equal to the password, set the user to be the admin if ($sub eq $CONF{pass}) { $auth=$from; &send("PRIVMSG $to : ADMIN POWERS ENABLED!!"); } ##ADMIN FUNCTIONS if ($auth eq $from) { ##if the first word is "!quote", send the string that follows to the server ## e.g. "!quote PRIVMSG #testing : HELLO" prints out "HELLO" to #testing if ($sub eq "!quote" and @data >0 ) { &send(@data) ; } ##!echo #channel spits out whatever to the channel elsif ($sub eq "!echo" and @data >1 ) { $_ = shift(@data); &send("PRIVMSG $_ :".join(" ",@data)); } #!boom spits out whatever to every channel elsif ($sub eq "!boom" and @data > 0) { &send("PRIVMSG $CONF{channel} :".join(" ",@data)); } elsif ($sub eq "!join" and @data > 0) { $CONF{channel} = $CONF{channel}.","; $CONF{channel} = $CONF{channel}.$data[0]; &send("JOIN $data[0]"); } elsif ($sub eq "!leave" and @data > 0) { $CONF{channel} =~ s/$data[0]//; &send("PART $data[0]"); } elsif ($sub eq "!reset" ) { getbuckleyisms(); } } } #if messages come from channel, start buttifying elsif ($to =~ /^#/ ) { my $sender = $from; $sender =~ s/^:(.*)!.*$/$1/; ##ignores statements from cout and users containing the word "bot" if (($from !~/^:cout/) && ($from !~/^:[^!]*bot[^!]*!/i)) { if ($sub eq "!buckley") { &send("PRIVMSG $to :".join(" ",&buckleyism())); } if ($sub eq "!addbuckley" and @data > 0) { $fullstring =~ s/!addbuckley\s+//; addbuckleyism($fullstring); } } } } } } sub buckleyism{ return $buckleyisms[int(rand(@buckleyisms))]; } #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #THIS IS WHERE IT BLOWS UP!!!!!!! #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! sub addbuckleyism{ push @buckleyisms, $_[0]; $_[0] = $_[0] . "\n"; open(FILE2, ">>buckleys.txt"); print FILE2 $_[0]; close FILE2; } sub connect { my ($remote_host,$remote_port,$local_host)=(shift,shift,shift); my $socket=IO::Socket::INET->new( PeerAddr => $remote_host, PeerPort => $remote_port, proto => "tcp", Type => SOCK_STREAM, Timeout => 10 ); return $socket; } sub gets { my $data = ""; $sock->recv($data,1024) ; #or &error("get: $! $@"); return $data; } sub send { my ($text) = join(" ",@_); $text.="\n"; $sock->send($text); } sub forks { my $spoon=fork(); if (defined $spoon) { if ($spoon==0) { return; } else { print "exiting, child pid=$spoon\n"; exit; } } else { &error("fork: $! $@"); } } sub error { print "\nerror: @_\n"; exit; } sub readconf { our %CONF; my ($conffile)=@_; open(CONF,"$CONF{file}") or &error("readconf: cannot open $CONF{file}"); while (my $line=) { if (substr($line,0,1) ne "#") { if ($line =~/^\s*([^\s]+)\s*=\s*(.+)$/) { $CONF{lc($1)}=$2; } } } close(CONF); } #open buckleys.txt and read in all the lines sub getbuckleyisms{ @buckleyisms = (); open(FILE1, "buckleys.txt"); while (my $line= ){ push(@buckleyisms, $line); } close FILE1; }