#!/util/bin/perl						#CONFIGURE

# local defines

$OPERPASSFILE = './pw';						#CONFIGURE

# variables:
#    $port, $server    - server to connect to
#    $servername       - name of the server we're on
#                        (what the server calls itself)
#    $nick             - nickname
#    $fullname         - full name field
#    $username         - username to use with server
#    S                 - socket file handle
#    $source           - source of a remote message
#    $quitflag         - set to 1 to quit
#    $owner            - my owner
#    $magicword        - how do you make me leave?
#    $eavesdrop        - forward MSGs to owner
#    $Debug            - debugging mode
#    $talk             - like stuff a lot
#    $guard            - act as a guardian
#    %lastpriv         - last msg from whoever

# primitive support functions

sub Upcase {			# upcase the arg & return it
    local($string) =@_;
    $string =~ tr/a-z/A-Z/;
    $string;
}

sub StripLeadingColon {		# strips the leading colon if any from $arg
    local($string) = @_;	# and returns the str without the :
    $string =~ s/^://;		# (written because IRC has so many :msgs)
    $string;
}
# cmdline parsing now uses getopt.pl for ease of expansion

push(@INC,'.');
require 'getopts.pl';
require 'ircclient.pl';

do Getopts('p:s:n:f:u:O:c:m:d:k:L:D:oevgrl');
# port, server, nick, fullname, username, Debug, revenge
# Owner, channel, magicword, delay, kill target, Log file
# Booleans: o = oper, e = eavesdrop,
# g = guard, l = logging

@mnth=("jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec");
($sec,$min,$hour,$date,$month,$year,$rest)=localtime();
$month = @mnth[$month];
$date = "0".$date if ($date < 10);
$hour = "0".$hour if ($hour < 10);
$min = "0".$min if ($min < 10);
$sec = "0".$sec if ($sec < 10);
$started = "$date-$month-$year at $hour:$min:$sec";

$fullname = $opt_f || $ENV{'IRCAUTONAME'} || 'What's My Line?';	#CONFIGURE
$nick = $opt_n || $ENV{'IRCAUTONICK'} || "NICK_GOES_HERE";	#CONFIGURE
$owner = $opt_O || $ENV{'USER'} || (getpwuid($<))[0] || die "Ooops";
$port = $opt_p || $ENV{'IRCPORT'} || 6667;
$server = $opt_s || $ENV{'IRCSERVER'} || 'SOME_SERVER';		#CONFIGURE
$username = $opt_u || $nick;

$channel = $opt_c || "##";					#CONFIGURE
$debug = $opt_D || 0;
$delay = $opt_d || 1;
$kickveng = 0;
$log = $opt_l;
$logfile = $opt_L || "log";
$magicword = $opt_m || 'MAGIC_WORD_GOES_HERE';			#CONFIGURE
$reply = "does ch-op and invite.";				#CONFIGURE
$secret = "PASSWORD";						#CONFIGURE
$tries = "1";
$vengeance = $opt_r || 0;

$WhoisUnlocked = 1;						#XXX

$eavesdrop = $opt_e;
$guard = $opt_g;
$wantinvite = "";
$original_nick = $nick;

foreach $i (@seed) {};

open(LOG, ">>$logfile") if ($logfile);
open(DLOG, ">>D$logfile") if ($logfile);
select(LOG); $| = 1; select(STDOUT); $| = 1;

if ($opt_o || $opt_k) {
    chop($operpass = `head -1 $OPERPASSFILE`);
}

# connect to server
&ircclient'bindsocket('S',$server,$port);

# first, signon as a client
&SignOn();
&ircclient'join($channel);

# next, completely ignore the message of the day
# while getting the server's name for itself

# munchmotd:
#    while (<S>) {
#	chop;
#	($servername) = m/.*Your host is ([^ ,]+),.*/
#	    if m/Your host is/;
#	if (( m!End of /MOTD command! ) ||
#	    ( m!Message-of-today is missing! )) {
#	    last munchmotd;
#	}
#}

$servername = $server unless $servername; # do some simple trapping for oldies

#&ircclient'away();
$help = "help message";

 mainloop:
    while (<S>) {
	chop;
	$_ = ":$servername $_" unless /^:/;
	($source, $command, $parms) = split(/ /,$_,3);
	$source = &StripLeadingColon($source);
	$cmd = &Upcase($command);
      cmdcase:			# treated as a switch/case type thingy
	{			# as long as you're careful about eq
	    if ($cmd eq '311') {&SetWhois($parms); last cmdcase;};
	    if ($cmd eq '312') {&SetWherefrom($parms); last cmdcase;};
	    if ($cmd eq '313') {&SetOperStat($source,$cmd,$parms);
	                        last cmdcase;};
	    if ($cmd eq '318') {$WhoisUnlocked = 1; last cmdcase;};
	    if ($cmd eq '351') {&ParseVersion(); last cmdcase;};
	    if ($cmd eq '364') {&ParseLinks(); last cmdcase;};
	    if ($cmd eq '365') {&ParseLinkEnd(); last cmdcase;};
	    if ($cmd eq '433') {&SetNick(); &SignOn(); last cmdcase;};
	    if ($cmd eq '461') {&SetOper(); last cmdcase;};
	    if ($cmd eq 'CHANNEL') {&ParseChan($source,$cmd,$parms);
				    last cmdcase;};
	    if ($cmd eq 'INVITE') {&ParseInvite($source,$parms);
				   last cmdcase;};
	    if ($cmd eq 'JOIN') {&ParseChan($source,$cmd,$parms);
	    			 last cmdcase;};
	    if ($cmd eq 'KICK') {&ParseKick($source,$parms); last cmdcase;};
	    if ($cmd eq 'KILL') {&ParseKill($source); last cmdcase;};
	    if ($cmd eq 'MODE') {&ParseMode($source,$cmd,$parms);
				 last cmdcase;};
	    if ($cmd eq 'MSG') {&ParseMsg($source,$parms);
				last cmdcase;};
	    if ($cmd eq 'NOTICE') {&ParseNotice($source,$parms);
				   last cmdcase;};
	    if ($cmd eq 'PART') {&ParseChan($source,$cmd,$parms);
				 last cmdcase;};
	    if ($cmd eq 'PING') {&ircclient'pong($nick);
				 last cmdcase;};
	    if ($cmd eq 'PRIVMSG') {&ParsePriv($source,$parms);
				    last cmdcase;};
	    if ($cmd eq 'QUIT') {&ParseQuit($source,$cmd,$parms);
				 last cmdcase;};
	    if ($cmd eq 'WALL') {&ParseWall($source,$parms);
				last cmdcase;};
	    if ($cmd eq 'WALLOPS') {&ParseWallop($source,$parms);
				last cmdcase;};
	    if ($cmd eq 'WHOREPLY') {&ParseWhoreply($parms);
				 last cmdcase;};
	}	    
	    
    } continue {
	if ($PendingWhois && $WhoisUnlocked) {
	    &ircclient'whois($PendingWhois);
	    $PendingWhois = "";
	}
	if ($quitflag) {&Quit;}
    }

if ($gotme) {
    close(LOG);
    open(OPPED, ">>opped");
    print (OPPED "@opped\n");
    close(OPPED);
    $delay += 5;
    sleep $delay;
    if (!fork()){
      exec("./tzoserv -d $delay -k $gotme -n $nick -o -l -L $logfile -s $server -c $channel") if ($vengeance);
      exec("./tzoserv -d $delay -n $nick -o -l -L $logfile -s $server -c $channel");
    }
}

sub ParseCTCP{
    local($src, $args) = @_;
    local($err) = $args;
    $err =~ s///g;
    &ircclient'notice($src,
        "FINGER Idle 0 seconds, on since $started.")	#CONFIGURE
        if ($args =~ /FINGER.+/);
    &ircclient'notice($src, "USERINFO This is a program.")
        if ($args =~ /USERINFO.+/);
    &ircclient'notice($src,
                      "VERSION BUPerlbot pjg 3 3 Perl :BUPerlbot.pjg.3.3 Perl original code ckd, this version pjg")
        if ($args =~ /VERSION.+/);
    &ircclient'notice($src, "ERRMSG Nothing is wrong.")
        if ($args =~ /ERRMSG/);
    &ircclient'notice($src, "ERRMSG $err Nothing is wrong.")
        if ($args =~ /ERRMSG.+/);
    &ircclient'notice($src,
                      "CLIENTINFO CLIENTINFO ERRMSG FINGER VERSION USERINFO")
        if ($args =~ /CLIENTINFO.+/);
}

sub ParseChan {
    local ($who, $cmd, $chan)= @_;
    &ircclient'notice($owner, "ch:$who:$cmd:$chan") if ($debug & 1);
    if ($cmd eq "JOIN") {
        &WriteLog("jn:$who:$cmd:$chan\n") if ($log);
	if ($WhoisUnlocked) {
	    $WhoisUnlocked = 0;
            &ircclient'whois($who);
	} else {
	    $PendingWhois = $who;
	}
    }
    if ($cmd eq "PART") {
        &WriteLog("pt:$who:$cmd:$chan\n") if ($log);
    }
}

sub ParseChanMsg {
    local($src,$target,$message) = @_;
    if ($message =~ /.+/) {
        &ParseCTCP($src, $message);
    }
    &ircclient'notice($owner,"<$src:$target> $message") if ($eavesdrop);
    &WriteLog("<$src:$target>:$message\n") if $log;
}

sub ParseInvite {
    local ($who, $args) = @_;

    ($me,$chan) = split(/ /,$args,2);
    if ($who eq $owner) {
        &ircclient'join($chan);
        $channel = $chan;
    }
}

sub ParseKick {
    local($src, $args) = @_;
    &WriteLog("kick:$src $args\n") if ($log);
    &ircclient'kick($src, $channel) if ($args =~ /pjg/ && $kickveng);
}

sub ParseKill { # someone killed me
    local($src) = @_;
    $gotme = $src;
}

sub ParseMode {
    local ($who, $cmd, $chan)= @_;
    &WriteLog("mo:$who:$cmd:$chan\n") if ($log);
}

sub ParseMsg {
    local ($who, $msg) = @_;
    $msg = &StripLeadingColon($msg);
    &ParseChanMsg($who,$channel,$msg);
}

sub ParseNotice { # just does kills for now
    local($src,$args) = @_;
    local($to, $msg) = split(/ /, $args, 2);
    &ircclient'notice($owner,"no:$src \"$args\"") if ($eavesedrop);
    &WriteLog("no:$src:$args\n") if ($log && $to !~ /\*/);
    return unless $vengeance;
    ($killee,$killer) =
      ($args =~ m/Received KILL message for (.+)\.\s+Path:\s+.*\!(\S+)/);
    if (&Upcase($killer) ne &Upcase($nick)) {
	&ircclient'kill($killer,"killing $killee.");
    }
}

sub ParsePriv {
    local($src,$args) = @_;
    local($target,$message) = split(/ /,$args,2);

    $message = &StripLeadingColon($message);
    if (&Upcase($target) eq &Upcase($nick)) { # for me?
	if ($message =~ /$magicword/i) {
	    &ircclient'notice($owner, "$src said the magic word");
	    $quitflag = 1;
	} elsif ($message =~ /.+/) {
	    &ParseCTCP($src, $args);
	} elsif (&Upcase($src) eq &Upcase($owner) && $message =~ /$secret/) {
	    &DoDuties($message);
	} else {
	    &RespondAppropriately($src,$message);
	}
    } else {
	&ParseChanMsg($src,$target,$message);
    }
}

sub ParseQuit {
    local ($who, $cmd, $chan)= @_;
    &WriteLog("qt:$who:$cmd:$chan\n") if ($log);
}

sub ParseWall {
    local($who, $msg) = @_;
    $msg = &StripLeadingColon($msg);
    &ircclient'notice($owner,"!!$who!! $msg") if ($eavesdrop);
    &WriteLog("wa:$who:$msg\n") if $log;
}

sub ParseWallop {
    local($who, $msg) = @_;
    $msg = &StripLeadingColon($msg);
    &ircclient'notice($owner,"!$who! $msg") if ($eavesdrop);
    #&WriteLog("wo:$who:$msg\n") if ($log);
    &WriteDLog("wo:$who:$msg\n") if ($log && $msg =~ /be eradicated/);
    &WriteLog("wo:$who:$msg\n") if ($log && $msg !~ /be eradicated/);
}

sub ParseWhoreply {
    local($args) = @_;
    local($l_chan, $l_user, $l_host, $l_server, $l_nick, $l_status, $l_name) =
        split(' ', $args, 7);
    $check = ($l_server !~ /odu/i && $l_host !~ /odu/i);
    $check = ($check && $l_status =~ /.\*/ && $l_status !~ /..\@/);
    if ($check && ($l_nick eq $wantop) ) {
        &ircclient'mode($l_chan, "+o $l_nick");
	if (!@opped{"$l_nick"}) {
            &ircclient'notice($l_nick, "$reply") if ($nick =~ /$reply/);
	    @opped{"$l_nick"} = 1;
	}
    }
    elsif ($l_nick eq $wantop) {
	@notopped{"$l_nick"} = 1;
    }
    if ($debug & 2) {
	&ircclient'notice($owner, "$l_nick has $l_status status.")
	    unless $l_nick eq "Nickname";
    }
}

sub DoDuties {
    local($cmdline) = @_;
    local($key, $cmd,$args) = split(/ /,$cmdline,3);

    &ircclient'notice($owner, "$key $cmd $args") if ($debug & 4);
    return if ($key ne $secret);

  choose:
    {
	if ($cmd =~ /^msg/i)   {&ircclient'msg($args); last choose;};
	if ($cmd =~ /^priv/i)  {&ircclient'privmsg(split(/ /,$args,2));
			        last choose;};
	if ($cmd =~ /^noti/i)  {&ircclient'notice(split(/ /,$args,2));
			        last choose;};
	if ($cmd =~ /^join/i)  {&ircclient'join($args); last choose;};
	if ($cmd =~ /^away/i)  {&ircclient'away($args); last choose;};
	if ($cmd =~ /^top/i)   {&ircclient'topic($args); last choose;};
	if ($cmd =~ /^quo/i)   {&ircclient'quote($args); last choose;};
	if ($cmd =~ /^whoi/i)  {&ircclient'whois($args); last choose;};
        if ($cmd =~ /^inv.*/i) {&ircclient'invite($args, $channel);
	                        last choose;};
	if ($cmd =~ /^op/i)    {&ircclient'mode($channel, "+o $owner");
	                        last choose;};
	if ($cmd =~ /^say/i)   {&ircclient'privmsg($channel, $args);
	                        last choose;};
	if ($cmd =~ /^set/i)   {&DoSets($args); last choose;};
	if ($cmd =~ /^stat/i)  {&DumpState($args); last choose;};
        if ($cmd =~ /hel.*/i)  {&ircclient'notice($owner,$help); last choose;};
    }
}

sub DoSets {
    local($input) = @_;
    local($cmd, $args) = split(/ /, $input, 2);

    &ircclient'notice($owner, "cmd:$cmd args:$args\n") if ($debug & 8);

    $channel = $args if ($cmd =~ /cha.*/i);
    $delay = $args if ($cmd =~ /del.*/i);
    $owner = $args if ($cmd =~ /own.*/i);
    $magicword = $args if ($cmd =~ /magic.*/i);
    $reply = $args if ($cmd =~ /repl.*/i);
    $secret = $args if ($cmd =~ /secr.*/i);
    $debug = $args if ($cmd =~ /deb.*/i);
    $guard = !$guard if ($cmd =~ /gua.*/i);
    $eavesdrop = !$eavesdrop if ($cmd =~ /eav.*/i);
    $log = !$log if ($cmd =~ /log.*/i);
    $kickveng = !$kickveng if ($cmd =~ /kickv.*/i);
    $vengeance = !$vengeance if ($cmd =~ /ven.*/i);
}

sub DumpState {
    local(@opped) = keys(%opped);
    local(@notopped) = keys(%notopped);

    &ircclient'notice($owner, "started $started owner $owner");
    &ircclient'notice($owner, "channel $channel debug $debug delay $delay");
    &ircclient'notice($owner, "logfile $logfile guard $guard log $log");
    &ircclient'notice($owner, "eavesdrop $eavesdrop server $server");
    &ircclient'notice($owner, "wantop $wantop wantinvite $wantinvite");
    &ircclient'notice($owner, "kickveng $kickveng vengeance $vengeance");
    &ircclient'notice($owner, "reply $reply");
    &ircclient'notice($owner, "opped @opped");
    &ircclient'notice($owner, "notopped @notopped");
}

sub Quit {
    local(@opped) = keys(%opped);

    &ircclient'notice($owner,"Leaving.");
    open(OPPED, ">>opped");
    print (OPPED "@opped\n");
    &ircclient'quit;
}

sub RespondAppropriately {
    local($src,$msg) = @_;

    &ircclient'privmsg($owner,"pm:$src \"$message\".") if ($eavesdrop);

    if ($msg =~ /op/) {
        $wantop = $src;
	&ircclient'who($channel);
	return;
    };
    if ($msg =~ /inv.*/) {
        $wantinvite = $src;
#	$WhoisUnlocked = 0;
	&ircclient'whois($src);
	return;
    };
    if ($msg =~ /hel.*/i) {
        &ircclient'notice($src, $help);
	return;
    };
    &ircclient'notice($src, "/msg help for help");
}

sub SetNick {
    $nick = $original_nick . $tries;
    $tries += 1;
}

sub SetOper {
    if ($operpass) {
        &ircclient'oper('pjg',$operpass);
        &ircclient'kill($opt_k,'Self defense.') if $opt_k;
    }
}

sub SetOperStat {
    local($src, $code, $params) = @_;
    local($to, $lnick, $rest) = split(/ /, $params);
    &ircclient'notice($owner, "ops $lnick") if ($debug & 16);
    if($lnick eq $wantinvite) {
        &ircclient'invite($lnick, $channel);
	$wantinvite .= ":";  # don't invite them again
        &ircclient'notice($owner,"$wantinvite invite $channel")
            if ($debug & 32);
    }
}

sub SetWherefrom {
    local($args) = @_;
    local($to, $host, $rest) = split(' ', $args);
#    if ($host eq "ucscb.ucsc.edu") {
#        &ircclient'mode($channel, "-o $whois") if ($debug & 64);
#        &ircclient'privmsg($channel, "$whois is from $host.");
#    }
    &ircclient'notice($owner, "$whois from $host") if ($debug & 64);
}

sub SetWhois {
    local($args) = @_;
    local($to, $lnick, $user, $host, $status, $name) = split(' ', $args);
    $whois = $lnick;
}

sub SignOn {
    &ircclient'user($username,$username,$server,$fullname);
    &ircclient'nick($nick);
    if ($operpass) {
        &ircclient'oper('pjg',$operpass);
        &ircclient'kill($opt_k,'Self defense.') if $opt_k;
    }
}

sub WriteLog {
    ($sec,$min,$hour,$date,$month,$year,$rest)=localtime();
    $month += 1;
    $date = "0".$date if ($date < 10);
    $hour = "0".$hour if ($hour < 10);
    $min = "0".$min if ($min < 10);
    $month = "0".$month if ($month < 10);
    print(LOG "$month/$date:$hour:$min-");
    print(LOG "@_");
}

sub WriteDLog {
    ($sec,$min,$hour,$date,$month,$year,$rest)=localtime();
    $month += 1;
    $date = "0".$date if ($date < 10);
    $hour = "0".$hour if ($hour < 10);
    $min = "0".$min if ($min < 10);
    $month = "0".$month if ($month < 10);
    print(DLOG "$month/$date:$hour:$min-");
    print(DLOG "@_");
}

sub ParseVersion { last cmdcase;}
sub ParseLinks { last cmdcase;}
sub ParseLinkEnd { last cmdcase;}
//E*O*F perlserver//
