#!/usr/bin/perl -w

#####################################################
# oblio_irc.pl                                      #
# A POE IRC Bot Named Oblio (a bot with no point)   #
# @requires POE, POE::Component::IRC                #
#                                                   #
# @author: Adam Eivy (antic@shadowpuppet.net)       #
  my $Version =  0.7;
  my $Modified=  "2006.08.26";
# @web: http://www.shadowpuppet.net                 #
#                                                   #
# @licence:                                         #
# This script is released under the                 #
# GNU General Public License.                       #
# More information on the GPL can be found          #
# at http://www.gnu.org/copyleft/gpl.html           #
#                                                   #
# @usage:                                           #
# nice -n 19 perl [file].pl                         #
#                                                   #
# @description:                                     #
# IRC bot.                                          #
# rot13 encrypts public messages.                   #
# It responds to "rot13 {text to encrypt}.          #
# Gives ops to user who sends private message to it #
# using "![botname] -o #channel [passphrase]"       # 
# more AI coming soon...                            #
#####################################################

use strict;
use lib "./perl"; # Path to non-global installed perl mods
use POE;
use POE::Component::IRC;
#use Irc::Bot::Log;

#########################
#     Variables         #
#########################

my $BotName = "oblio";
# append a random number to the end of name if we need to run multiple instances
#my $nick = 'oblio' . $$ % 100; 
my $UserName = "Oblio: Helper Bot";
my $IrcName = "type !oblio -h";

# will autojoin these channels after connecting
my @channels = qw(#hack #min3 #go #sccc #jsdesk);

my @Operators = ("antic", "oblio");
my $Server = "localhost";
my $Port = 6667;
my $Passphrase = "YOUR_PASSPHRASE_HERE"; # removed for publication
#my $log = Irc::Bot::Log->new( Path => './logs/' );

# Calculate number of array vars
my $NumOfOps      = scalar(@Operators);
my $NumOfChannels = scalar(@channels);

#############
# CODE      #
#############

# Create the component that will represent an IRC network.
POE::Component::IRC->new("magnet");

# Create the bot session.  The new() call specifies the events the bot
# knows about and the functions that will handle those events.
POE::Session->new
  ( _start => \&bot_start,
    irc_001    => \&on_connect,
    irc_public => \&on_public,
    irc_msg    => \&on_private,
    irc_join   => \&on_join,
    irc_error  => \&on_error,
    irc_disconnected => \&bot_start,
  );

###############################
# Bot Startup                 #
###############################
# The bot session has started.  Register this bot with the "magnet"
# IRC component.  Select a nickname.  Connect to a server.
sub bot_start {
    my $kernel  = $_[KERNEL];
    my $heap    = $_[HEAP];
    my $session = $_[SESSION];

    $kernel->post( magnet => register => "all" );

    $kernel->post( magnet => connect =>
          { 
			Nick     => $BotName,
            Username => $UserName,
            Ircname  => $IrcName,
            Server   => $Server,
            Port     => $Port,
          }
    );
}

###############################
# Connected to Server         #
###############################
# The bot has successfully connected to a server.  Join channels in @channels.
sub on_connect {
    for (my $x=0; $x < $NumOfChannels; $x++) {
		$_[KERNEL]->post( magnet => join => $channels[$x]);
	   
		# list the users of channel joined 
		# useful for identifying users
		$_[KERNEL]->post( 'magnet', 'who', $channels[$x]);
    }
}

###############################
# Server Error Recieved       #
###############################
sub on_error{
	# add detection of particular server, for now call routine
	my $ServError = $_[ARG0];
	print " $ServError !\n";
}

###############################
# Bot Disconnects From Server #
###############################
sub on_discon{
	# add detection of particular server, for now call routine
	my $DisServer = $_[ARG0];
	print " disconnected from $DisServer!\n";
    $_[KERNEL]->post( magnet => connect =>
		{ 
			Nick     => $BotName,
			Username => $UserName,
			Ircname  => $IrcName,
			Server   => $Server,
			Port     => $Port,
		}
   );
}

###########################
# Someone Joins Channel   #
###########################

sub on_join{
	my ( $kernel, $who, $where ) = @_[ KERNEL, ARG0, ARG1 ];
	my $nick = ( split /!/, $who )[0];
	# my $channel = $where->[0];
	# TODO: If new user is in Operator list, send and check code, then op
    for (my $op=0; $op < $NumOfOps; $op++) {
      if ($who =~ $Operators[$op]) 
      {
		$kernel->post( magnet => privmsg => $nick, "Welcome Friend" );
      }
    }

   # TODO: Get list of users, if another oblio exists, ask for op status

}

###########################
# Recieved Public Message #
###########################

sub on_public {
    my ( $kernel, $who, $where, $msg ) = @_[ KERNEL, ARG0, ARG1, ARG2 ];
    my $nick = ( split /!/, $who )[0];
    my $channel = $where->[0];

    my $ts = scalar localtime;

	# Log all activity to a file named with my irc Name
	open LOG, ">>./log/$BotName-$channel.log";
	print LOG " [$ts] <$nick:$channel> $msg\n";
	close LOG;
    
	# bring up help menu on !$BotName -h
    if ( $msg =~ /^(!$BotName -h)$/ ) {
        $kernel->post( magnet => privmsg => $nick, "Oblio version $Version \t : $Modified" );
		$kernel->post( magnet => privmsg => $nick, "            ::Command Menu::" );
        $kernel->post( magnet => privmsg => $nick, "\t" );
        $kernel->post( magnet => privmsg => $nick, "Commands used in Channel     (Public)" );
        $kernel->post( magnet => privmsg => $nick, "!$BotName -h                 help Menu" );
        $kernel->post( magnet => privmsg => $nick, "!$BotName -a                 about OblioBot" );
        $kernel->post( magnet => privmsg => $nick, "!$BotName -r [message]       rot13 encypher a message" );
        $kernel->post( magnet => privmsg => $nick, "\t" );
        $kernel->post( magnet => privmsg => $nick, "Commands over Private message           (Ops only)" );
        $kernel->post( magnet => privmsg => $nick, "!$BotName -o [#channel] [passphrase]    op me in #channel" );
        $kernel->post( magnet => privmsg => $nick, "!$BotName -j [#channel] [passphrase]    tell bot to join #channel" );
        $kernel->post( magnet => privmsg => $nick, "!$BotName -s [user] [filepath] [passphrase]    send me this file" );
        $kernel->post( magnet => privmsg => $nick, "End of Menu" );
        #$kernel->post( magnet => dcc_chat => $nick, "Oblio version $Version \t ::Command Menu:: \n" );
    }

	# bring up about on !$BotName -a
    if ( $msg =~ /^(!$BotName -a)$/ ) {
		$kernel->post( magnet => privmsg => $nick, "Oblio version $Version \t : $Modified" );
		$kernel->post( magnet => privmsg => $nick, "                  ::About::" );
		$kernel->post( magnet => privmsg => $nick, "\t" );
		$kernel->post( magnet => privmsg => $nick, "Oblio is a simple IRC bot in Perl using POE::Component::IRC" );
		$kernel->post( magnet => privmsg => $nick, "Created by Adam Eivy" );
		$kernel->post( magnet => privmsg => $nick, "http://adam.shadowpuppet.net" );
		$kernel->post( magnet => privmsg => $nick, "\t" );
		$kernel->post( magnet => privmsg => $nick, "Bot Hosted by http://www.dreamhost.com/r.cgi?30755" );
    }


	# rot13 encypher text
    if ( my ($rot13) = $msg =~ /^!$BotName -r (.+)/ ) {
        $rot13 =~ tr[a-zA-Z][n-za-mN-ZA-M];
        $kernel->post( magnet => privmsg => $channel, $rot13 );
    }

	# respond to direct questions in main channel
    if ( $msg =~ /^($BotName) (.+)/ ) {
		my $oblisay = "$2?";
        $kernel->post( magnet => privmsg => $channel, $oblisay );
    }
}

############################
# Recieved Private Message #
############################


sub on_private {
    my ( $kernel, $who, $where, $msg ) = @_[ KERNEL, ARG0, ARG1, ARG2 ];
    my $nick = ( split /!/, $who )[0];
    my $channel = $where->[0];

    my $ts = scalar localtime;
    print " [$ts] <$nick:$channel> $msg\n";

	# this part takes a command "![botname] -o #channel [passphrase]" 
    if ( $msg =~ /^(!$BotName -o) (#.+) ($Passphrase)$/ ) {
        $kernel->post( magnet => privmsg => $nick, "trying to op $nick on $2...");
        $kernel->post( 'magnet', 'mode', $2, '+o', $nick);
        $kernel->post( magnet => privmsg => $nick, "Success!" );
    }
	
	# super operator: "![botname] -su [passphrase]"
    if ( $msg =~ /^(!$BotName -su) ($Passphrase)$/ ) {
        for (my $x=0; $x < $NumOfChannels; $x++) {
            $kernel->post( magnet => privmsg => $nick, "trying to op $nick on $channels[$x]...");
            $kernel->post( 'magnet', 'mode', $channels[$x], '+o', $nick);
            $kernel->post( magnet => privmsg => $nick, "Success!" );
        }
    }

	# this part takes a command "![botname] -j #channel [passphrase]" 
    if ( $msg =~ /^(!$BotName -j) (#.+) ($Passphrase)$/ ) {
        $kernel->post( magnet => privmsg => $nick, "trying to join $2...");
        $kernel->post( 'magnet', 'join', $2);
        $kernel->post( magnet => privmsg => $nick, "Success!" );
    }

	# this part takes a command "![botname] -s user filepath [passphrase]"
    if ( $msg =~ /^(!$BotName -s) (.+) (.+) ($Passphrase)$/ ) {
		my $command = "dcc send $2 $3";
        $kernel->post( 'magnet', 'DCC', $2, 'SEND', $3);
        $kernel->post( magnet => privmsg => $nick, $command); 
    }
}

###################
#     LOGGING     #
###################

# Log join event
#  sub on_join {
#    my ( $kernel, $who, $where ) = @_[ KERNEL, ARG0, ARG1 ];
#    my $nick = ( split /!/, $who )[0];
#    
    # log activity 

#    $log->serv_log( "Connected.." );
#    $log->chan_log( "$nick has joined $where\n" );
#    $log->bot_log( "$nick tried to access me!\n" );

#  }

############
# RUN BOT  #
############

# Run the bot until it is done.
$poe_kernel->run();
exit 0;