#!/usr/bin/perl

######################################################################
#                                                                    #
# (c) Anthony G. Basile, Oct. 20, 2001                               #
#                                                                    #
# Description: Fido for OV                                           #
#                                                                    #
######################################################################
#
# Packages
#

use Socket ;
use POSIX ;


#
# Configuration
#

$master = "Unununium" ;
$dog    = "Tux"   ;
$woof   = "Quack!" ;


#
# Get the arguments.
#

#if ( $ARGV[0] != "" ) { $host = $ARGV[0] ; } else { $host = localhost ; }
#if ( $ARGV[1] != "" ) { $port = $ARGV[1] ; } else { $port = 7000 ; }
$host = "openverse.com" ;
$port = 7000 ;


#
# Get the av data
#
 
%avatars = () ;
 
open( AVDATA, "<avatars/avs.dat" ) ;
while (<AVDATA>) {
   $line = $_ ;
   chomp($line) ;
   $name = $line ;
   $name =~ s/\s+.*// ;
   $line =~ s/^$name\s+// ;
   $avatars{$name} = $line ;
}
close(AVDATA) ;


#
# Prepare a socket for connection
#

$server = gethostbyname($host) ;
$proto  = getprotobyname('tcp') ;
$lsock  = sockaddr_in( $port, $server ) ;
socket ( CSOCK, PF_INET, SOCK_STREAM, $proto ) ;
connect( CSOCK, $lsock ) ;


#
# Start the communication
#

%users = () ;

$currentav = 'basic' . 'penguin' . 'mr' ;

$messout = "AUTH $dog 350 200 $avatars{$currentav}\n" ;
print "-> " . $messout ;
syswrite( CSOCK, $messout, length($messout) ) ; 

while(1) {
   sysread ( CSOCK, $messin, 32767 ) ;
   print "<- " . $messin ;

   if( length($messin) == 0 ) { byebye() ; }

   @lines = split( /\n/, $messin ) ;

   $messout = "" ;

   for( $i = 0 ; $i <= $#lines ; $i++ ) {

      if ( $lines[$i] =~ /^PING/ ) {
         pinged($response) ;
         $messout .= $response ;
      }
      if ( $lines[$i] =~ /^DCCSENDAV/ ) {
         $dcc = $lines[$i] ;
         $dcc =~ s/^DCCSENDAV\s+// ;
         dccsendav( $dcc ) ;
         $messout .= "AVATAR $avatars{$currentav}\n" ;          # AVATAR file.gif x-av y-av size x-bubble y-bubble
      }
      if ( $lines[$i] =~ /^CHAT/ ) {
         $chat = $lines[$i] ;
         $chat =~ s/^CHAT\s+// ;
         chatted( $chat, $response ) ;
         $messout .= $response ;
      }
      if ( $lines[$i] =~ /^SCHAT/ ) {
         $chat =  $lines[$i] ;
         $chat =~ s/^SCHAT\s+\w+\s+// ;
         chatted( $chat, $response ) ;
         $messout .= $response ;
      }
      if ( $lines[$i] =~ /^NEW/ ) {
         $new = $lines[$i] ;
         $new =~ s/^NEW\s+// ;
         newed( $new, $response ) ;
         $messout .= $response ;
      }
      if ( $lines[$i] =~ /^NOMORE/ ) {
         $nomore = $lines[$i] ;
         $nomore =~ s/^NOMORE\s+// ;
         nomored( $nomore ) ;
      }
      if ( $lines[$i] =~ /^MOVE/ ) {
         $move = $lines[$i] ;
         $move =~ s/^MOVE\s+// ;
         moved( $move, $response ) ;
         $messout .= $response ;
      }
   }

   if ( length($messout) > 0 ) {
      print "-> " . $messout ;
      syswrite( CSOCK, $messout, length($messout) ) ;
   }

}




#
# Subtroutines
#

sub pinged {
   @_[0] = "PONG\n" ;
}



sub dccsendav {
   my $dcc, $port, $file, $data ;
   my $server, $proto, $lsock ;
 
   $dcc = shift(@_) ;
 
   $port = $dcc ; $port =~ s/^(\d+)\s+.*$/$1/ ;
   $file = $dcc ; $file =~ s/^\d+\s+(.*)$/$1/ ;
 
   $server = gethostbyname($host) ;
   $proto  = getprotobyname('tcp') ;
   $lsock  = sockaddr_in( $port, $server ) ;
   socket ( DSOCK, PF_INET, SOCK_STREAM, $proto ) or die "no socket\n" ;
   connect( DSOCK, $lsock ) or die "no connection\n" ;
 
   open( FILE, "<avatars/$file" ) ;
   while(1) {
      sysread ( FILE, $data, 256 ) ;
      if ( length($data) > 0 ) {
         syswrite( DSOCK, $data, length($data) ) ;
      } else {
         goto EXIT ;
      }
   }
 
EXIT:
   sleep(5) ;
   close(FILE) ;
   close(DSOCK) ;
}



sub chatted {
   my $chat, $name, $msg, $response, $string, $user, $pos, $x, $y, $speed, $av ;

   $chat = shift(@_) ;

   $name = $chat ; $name =~ s/\s+.*// ;
   $msg  = $chat ; $msg  =~ s/^$name // ; $msg = ' ' . $msg . ' ' ;  # white pad the msg

   $response = "" ;

   if ( $name =~ /$dog/i  or $msg !~ /\s$dog\s/i ) { return   ; }
   if ( $name eq $master and $msg =~ /\squit\s/i ) { byebye() ; }

   if ( $msg =~ /\shelp\s/i ) {
      $response .= "PRIVMSG $name Just say my name and any of the following words in the same sentence: " .
         "sit, good, bad, jump, shiver, speak, fortune, beg, move, dance, play, count to <number>, come, heal (off), " .
         "go to <username>, hug <username>, kiss <username>\n" ;
   }

   if ( $msg =~ /\ssit\s/i ) {
      $response .= "CHAT $woof\n" ;
      $currentav = 'basic' . 'penguin' . 'mr' ;
      $response .= "AVATAR $avatars{$currentav}\n" ;
   }
   if ( $msg =~ /\sgood\s/i ) {
      $response .= "CHAT $woof\n" ;
      $currentav = 'angel' . 'penguin' . 'mr' ;
      $response .= "AVATAR $avatars{$currentav}\n" ;
   }
   if ( $msg =~ /\sbad\s/i ) {
      $response .= "CHAT $woof\n" ;
      $currentav = 'devil' . 'penguin' . 'mr' ;
      $response .= "AVATAR $avatars{$currentav}\n" ;
   }
   if ( $msg =~ /\sjump\s/i )    { $response .= "CHAT $woof\nEFFECT jump\n"   ; }
   if ( $msg =~ /\sshiver\s/i )  { $response .= "CHAT $woof\nEFFECT shiver\n" ; }
   if ( $msg =~ /\sspeak\s/i )   { $response .= "CHAT $woof $name $woof $woof\n" ; }
   if ( $msg =~ /\sfortune\s/i ) {
      $string = `fortune` ;
      $string =~ s/\n/ /g ;
      $response .= "CHAT " . $string . "\n" ;
   }
   if ( $msg =~ /\sbeg\s/i )     {
      $pos = $users{$name} ;
      position( $pos, $x, $y ) ;
      $y += 50 ;
      $response .= "MOVE $dog $x $y 1\nEFFECT jump\nCHAT $woof $woof $woof\n" ;
   }
   if ( $msg =~ /\smove\s/i ) {
      $pos = $users{$dog} ;
      position( $pos, $x, $y ) ;
      $x += int(100*(2*rand()-1)) ;
      $y += int(100*(2*rand()-1)) ;
      $response .= "CHAT $woof\nMOVE $dog $x $y 1\n" ;
   }
   if ( $msg =~ /\sdance\s/i ) {
      $pos = $users{$dog} ;
      position( $pos, $x, $y ) ;
      $response .= "CHAT $woof\n" ;
      $y += 50 ;
      $response .= "EFFECT jump\nMOVE $dog $x $y 1\n" ;
      $x += 50 ;
      $response .= "EFFECT shiver\nMOVE $dog $x $y 1\n" ;
      $y -= 50 ;
      $response .= "EFFECT jump\nMOVE $dog $x $y 1\n" ;
      $x -= 50 ;
      $response .= "EFFECT shiver\nMOVE $dog $x $y 1\n" ;
      $response .= "EFFECT jump\n" ;
   }
   if ( $msg =~ /\splay\s/i ) {
      $response .= "CHAT $woof\n" ;
      for ($i=0;$i<5;$i++) {
         $x = int(640*rand()) ;
         $y = int(480*rand()) ;
         $speed = int(8*rand()) + 1 ;
         $response .= "MOVE $dog $x $y $speed\n" ;
      }
   }
   if ( $msg =~ /\scount\s+to\s/i ) {
      $x = $msg ;
      $x =~ s/^.*count\s+to\s+(\d+).*$/$1/ ;
      $response .= "CHAT" ;
      if ( 0 < $x and $x <= 10 ) {
         for( $i=1 ; $i<=$x ; $i++ ) { $response .= " $woof" ; }
      } else {
         $response .= " eh?" ;
      }
      $response .= "\n" ;
   }
   if ( $msg =~ /\scome\s/i ) {
      $pos = $users{$name} ;
      position( $pos, $x, $y ) ;
      $x += 50 ;
      $y += 50 ;
      $response .= "CHAT $woof\nMOVE $dog $x $y 1\n" ;
   }
   if ( $msg =~ /\sheal\s/i ) {
      if ( $msg =~ /\soff\s/i ) {
         undef($heal) ;
      } else {
         $heal = $name ;
         $pos = $users{$name} ;
         position( $pos, $x, $y ) ;
         $x += 50 ;
         $y += 50 ;
         $response .= "CHAT $woof\nMOVE $dog $x $y 1\n" ;
      }
   }
   if ( $msg =~ /\sgo\s+to\s/i ) {
      $target = $msg ;
      $target =~ s/.*\sgo\s+to\s+(\S+)\s.*\s/$1/ ;
      foreach $user ( keys(%users) ) {
         if ( $target =~ /$user/i or $user =~ /$target/i ) {
            $pos = $users{$user} ;
            position( $pos, $x, $y ) ;
            $x += 50 ;
            $y += 50 ;
            $response .= "CHAT $woof\nMOVE $dog $x $y 1\n" ;
         }
      }
   }
   if ( $msg =~ /\shug\s/i ) {
      $target = $msg ;
      $target =~ s/.*\shug\s+(\S+)\s.*\s/$1/ ;
      foreach $user ( keys(%users) ) {
         if ( $target =~ /$user/i or $user =~ /$target/i ) {
            $pos = $users{$user} ;
            position( $pos, $x, $y ) ;
            $response .= "MOVE $dog $x $y 1\nEFFECT shiver\nSCHAT LOVE $woof\n" ;
            $x -= 50 ;
            $y += 50 ;
            $response .= "MOVE $dog $x $y 1\n" ;
         }
      }
   }
   if ( $msg =~ /\skiss\s/i ) {
      $target = $msg ;
      $target =~ s/.*\skiss\s+(\S+)\s.*\s/$1/ ;
      foreach $user ( keys(%users) ) {
         if ( $target =~ /$user/i or $user =~ /$target/i ) {
            $pos = $users{$user} ;
            position( $pos, $x, $y ) ;
            $y += 50 ;
            $response .= "MOVE $dog $x $y 1\nEFFECT jump\nSCHAT LOVE Smoooches!\n" ;
            $x += 50 ;
            $response .= "MOVE $dog $x $y 1\n" ;
         }
      }
   }
      

#
#   The 'who', 'where', 'avatars' and 'wear' command are used mostly for development
#
   if ( $msg =~ /\swho\s/i )    {
      $response .= "CHAT The users here are :" ;
      foreach $user ( keys(%users) ) {
         $response .= " $user " ;
      }
      $response .= "\n" ;
   }
   if ( $msg =~ /\swhere\s/i )  {
      foreach $user ( keys(%users) ) {
         $pos = $users{$user} ;
         position( $pos, $x, $y ) ;
         $response .= "CHAT $user is at $x $y\n" ;
      }
   }
   if ( $msg =~ /\savatars\s/i ) {
      $response .= "CHAT " ;
      foreach $av ( keys(%avatars) ) {
         $response .= $av . " " ;
      }
      $response .= "\n" ;
   }
   if ( $msg =~ /\swear\s/i ) {
      $av = $msg ;
      $av =~ s/.*\swear\s+(\S+)\s.*/$1/ ;
      if ( exists($avatars{$av}) ) {
         $currentav = $av ;
         $response .= "AVATAR $avatars{$currentav}\n" ;
      }
   }

   @_[1] = $response ;
}



sub newed {
   my $new, $name, $info, $response ;

   $new  = shift(@_) ;

   $name = $new ; $name =~ s/\s+.*// ;
   $info = $new ; $info =~ s/^$name // ;

   $users{$name} = $info ;

   $response = "" ;

   if ( $name ne $dog ) {
      $response  = "PRIVMSG $name Hello, I am DrTony\'s bot.\n" ;
      $response .= "PRIVMSG $name To find out how I work, just say \"$dog help\"\n" ;
   }

   @_[0] = $response ;
}



sub nomored {
   my $name ;
   $name = shift(@_) ;
   $name =~ s/\s+.*// ;
   delete($users{$name}) ;
}



sub moved {
   my $move, $name, $pos, $x, $y, $response ;

   $move = shift(@_) ;

   $name = $move ; $name =~ s/\s+.*// ;

   $pos  = $move ; $pos  =~ s/^$name\s+// ;
   position( $pos, $x, $y ) ;

   $users{$name} =~ s/^\d+ \d+/$x $y/ ;

   $response = "" ;

   if ( defined($heal) ) {
      if ( $heal eq $name ) {
         $x += 50 ;
         $y += 50 ;
         $response .= "MOVE $dog $x $y 1\n" ;
      }
   }

   @_[1] = $response ;
}



sub position {
   my $pos, $x, $y ;

   $pos = @_[0] ;

   $pos =~ s/^(\d+)\s+(\d+).*$/$1 $2/ ;
   $x = $pos ; $x =~ s/ \d+$// ;
   $y = $pos ; $y =~ s/^\d+ // ;

   @_[1] = $x ;
   @_[2] = $y ;
}



sub byebye {
   close CSOCK ;
   exit ;
}



