use Switch;
use Gaim;
use DBI;
use strict;


%::PLUGIN_INFO = (
perl_api_version => 2,
name => "IMBBS",
version => "0.1",
summary => "IM BBS for Gaim",
description => "",
author => "Charlie Brej <imbbs@brej.org>",
url => "http://brej.org/imbbs/",
load => "plugin_load",
unload => "plugin_unload"
);

sub plugin_init {
return %::PLUGIN_INFO;
}

my $plugin;
my $database;
my $usetimeout = 1;
my %functions = ("dict"     => ["dict",     \&sub_dict,    "dict [database] word"],
                 "spell"    => ["spell",    \&sub_spell,   "spell word" ],
#                 "slashdot" => ["slashdot", \&sub_slashdot,"slashdot" ],
                 "help" =>     ["help",     \&sub_help,    "help" ],
                 "news" =>     ["news",     \&sub_news,    "news" ],
                 "timeout" =>  ["timeout",  \&sub_timeout, "" ],
                 "soundex" =>  ["soundex",  \&sub_soundex, "soundex" ],
                 "leet" =>     ["leet",     \&sub_leet,    "leet" ],
                 );




sub got_msg {
my ($account, $who, $message, $flags) = @_;
print "\n:".$message.":\n";
while($message =~ s/<.*?>//) {}; #HTML si t3h sux0r!
my $key;
my $found=0;
foreach $key (keys %functions) {
        if ($message =~ /^$functions{$key}[0]/){
            my $func = $functions{$key}[1];
            $message = &$func($message, $who, $account);
            $found=1;
            last;
            }
        }
if(!$found) {$message = sub_unknown($message);}
send_msg($account, $who, $message);
}


sub send_msg
{
my ($account, $who, $message) = @_;
my $dummy;
my $conv = Gaim::Conversation::new($dummy, 1, $account, $who);
if ($conv) {
    $conv = Gaim::Conversation::get_im_data($conv);
    my @lines = split ("\n",$message);
    $message="";
    my $count=10;
    my $subcount=4;
    foreach (@lines){
        $subcount--;
        $message .= "\n".$_;
        if(!$subcount){
            if (!$count--) {last;}
            Gaim::Conversation::IM::send($conv,$message);
            $message="";
            $subcount = 4;
            }
        }
    Gaim::Conversation::IM::send($conv,$message);
    }
}




sub sub_spell
{
use Lingua::Ispell;
Lingua::Ispell::allow_compounds(1);
my $message = shift;
$message =~ s/^spell //;
my $temp = $message;
$message = "Spell Checker:\n";
for my $r ( Lingua::Ispell::spellcheck( $temp ) ) {
    if ( $r->{'type'} eq 'ok' ) {
        # as in the case of 'hello'
        $message .= "'<b>$r->{'term'}</b>' was found in the dictionary.\n";
        }
    elsif ( $r->{'type'} eq 'root' ) {
        # as in the case of 'hacking'
        $message .= "'<b>$r->{'term'}</b>' can be formed from root '$r->{'root'}'\n";
        }
    elsif ( $r->{'type'} eq 'miss' ) {
        # as in the case of 'perl'
        $message .= "'<b>$r->{'term'}</b>' was not found in the dictionary;\n";
        $message .= "Near misses: @{$r->{'misses'}}\n";
        }
    elsif ( $r->{'type'} eq 'guess' ) {
        # as in the case of 'salmoning'
        $message .= "'<b>$r->{'term'}</b>' was not found in the dictionary;\n";
        $message .= "Root/affix Guesses: @{$r->{'guesses'}}\n";
        }
    elsif ( $r->{'type'} eq 'compound' ) {
        # as in the case of 'fruithammer'
        $message .= "'<b>$r->{'term'}</b>' is a valid compound word.\n";
        }
    elsif ( $r->{'type'} eq 'none' ) {
        # as in the case of 'shrdlu'
        $message .= "No match for term '<b>$r->{'term'}</b>'\n";
        }
    # and numbers are skipped entirely, as in the case of 42.
    }
$message =~ s/\n*$//;
return $message;
}


sub sub_dict
{
my $message = shift;
$message =~ s/^dict\ +//;
my $database = 'gcide';
my @words = split(" ", $message);
$message = "";
foreach (@words){
    if ( $_ =~ /^\[.*\]$/) {
        $_ =~ s/^\[(.*)\]$/$1/;
        $database = $_;
        }
    else {
        $message .= "$_ ";
        }
    }
use Net::Dict;
    
$message =~ s/\ +$//;
my $dict = Net::Dict->new('dict.org');
my $h = $dict->define($message);
$message = "Dictionary lookup of <b>$message</b>:\n";
my $databases="";
foreach my $i (@{$h}) {
    my ($db, $def) = @{$i};
    $def =~ s/\[.*\]//g;
    while($def =~ s/\n\ *\n/\n/) {};
    $def = "<b>".$def;
    $def =~ s/([.\n])/$1<\/b\>\ /;
    if ($database eq "all" or $db eq $database){
        $message .= $def;
        }
    else{
        if (!($db eq '')) {$databases .= "$db:".$dict->dbTitle($db)."\n";}
        }
    }
$message .= "<b>Other databases:</b>\n$databases";
$message =~ s/[\n\ ]+$//;
        
    
return $message;
}



sub sub_slashdot
{
my $message;
use XML::RSS::Parser;
use FileHandle;

my $p = XML::RSS::Parser->new;
my $fh = FileHandle->new('/tmp/slashdot');
my $feed = $p->parse_file($fh);

# output some values 
my $feed_title = $feed->query('/channel/title');
#$message .= $feed_title->text_content;
my $count = $feed->item_count;
#$message .= " ($count)\n";
foreach my $i ( $feed->query('//item') ) { 
    $message .= '<b><a href="'.$i->query('link')->text_content.'">';
    $message .= $i->query('title')->text_content;
    $message .= "</a></b>\n";
    my $description = $i->query('description')->text_content;
    while($description =~ s/<.*?>//) {};
    $message .= $description;
    $message .= "\n"; 
}
    while($message =~ s/\n\n/\n/) {};

return $message;
}







sub sub_soundex
{
my ($message, $who, $account)  = @_;
$message =~ s/^soundex\ +//;

use Text::Soundex;

$message = Text::Soundex::soundex ($message);



return $message;
}


sub sub_leet
{
my ($message, $who, $account)  = @_;
$message =~ s/^leet\ +//;

$_ = $message;
tr /[:UPPER:]/[:LOWER:]/;

s/are/R/g;
s/you/U/g;
s/elite/leet/g;
s/the/da/g;
s/ks/x/g;
s/ck/x/g;
s/hacker/haxor/g;
s/own/pwn/g;



tr /ABCDEFGHIJKLMNOPQRSTUVWXYZ/4BCD3FGH1JK1MN0PQR57UVWXY2/;
tr /abcdefghijklmnopqrstuvwxyz/@bcd3fgh1jk1mn0pqr57uvwxy2/;
$message = $_;

return $message;
}


sub sub_string
{
my ($message, $who, $account)  = @_;
$message =~ s/^string\ +//;

$message = $_;



return $message;
}



sub sub_news
{
my ($message, $who, $account)  = @_;

$message =~ s/^news\ +//;
my $messagein = $message;
$message = "";

if ($messagein =~ /^subscribe\ /){
    $messagein =~ s/^subscribe\ +//;
    $messagein =~ s/\*/\%/g;    
    my $query = $database->prepare("SELECT `name` FROM `newsservices` WHERE name LIKE ?");
    print (":$messagein:");
    $query->execute($messagein);
    while (my @row = $query->fetchrow_array ) {
        $message .= "<font size=\"5\">Added: ".$row[0]."</font>\n";
        my $query = $database->prepare("REPLACE INTO `newssubscriptions` (`name`, `account`, `newsservice`) VALUES (?,?,?)");
        $query->execute($who, Gaim::Account::get_protocol_name($account), $row[0]);
        }
    
    
    
    }

if ($messagein =~ /^unsubscribe\ /){
    $messagein =~ s/^unsubscribe\ +//;
    $messagein =~ s/\*/\%/g;    
    my $query = $database->prepare("SELECT `name` FROM `newsservices` WHERE name LIKE ?");
    print (":$messagein:");
    $query->execute($messagein);
    while (my @row = $query->fetchrow_array ) {
        $message .= "<font size=\"5\">Deleted: ".$row[0]."</font>\n";
        my $query = $database->prepare("DELETE FROM `newssubscriptions` WHERE (`name`, `account`, `newsservice`) = (?,?,?)");
        $query->execute($who, Gaim::Account::get_protocol_name($account), $row[0]);
        }
    
    }

$message .= "<b>Subscribed news services:</b>\n";
restore_database();
my $query = $database->prepare("SELECT `newsservice` FROM `newssubscriptions` WHERE `name` = ? and `account` = ?");
$query->execute($who, Gaim::Account::get_protocol_name($account));
while (my @row = $query->fetchrow_array ) {
    $message .= $row[0]."\n";
    }

$message .= "<b>Available news services:</b>\n";
restore_database();
my $query = $database->prepare("SELECT `name` FROM `newsservices`");
$query->execute();
while (my @row = $query->fetchrow_array ) {
    $message .= $row[0]."\n";
    }






return $message;
}

sub sub_timeout
{
if ($usetimeout eq 1) {
    $usetimeout = 0;
    }
else {  
    $usetimeout = 1;
    timeout();
    }
return "Timeouts=$usetimeout";
}



sub timeout
{

restore_database();
my $addressquery = $database->prepare("SELECT address FROM newsnew");
$addressquery->execute();
while (my @addressrow = $addressquery->fetchrow_array ) {
    my $address = $addressrow[0];
    my $query = $database->prepare("SELECT DISTINCT  name, account, newssubscriptions.newsservice, title, description FROM newssubscriptions JOIN newsnew on newsnew.newsservice = newssubscriptions.newsservice WHERE address =  ?");
    $query->execute($address);
    while (my @row = $query->fetchrow_array ) {
        my $name = $row[0];
        my $account_name = $row[1];
        my $newsservice = $row[2];
        my $title = $row[3];
        my $description = $row[4];
        while($description =~ s/<.*?>//) {};
        my @accounts = Gaim::Accounts::get_all_active();
        my $account;
        foreach (@accounts){
            if (Gaim::Account::get_protocol_name($_) eq $account_name){
                $account = $_;
                last;
                }
            }
        my $message;
        if ($account_name eq 'AIM/ICQ') {$message = "News: $newsservice\n<b><a href=\"$address\">$title</a></b>\n$description";}
        if ($account_name eq 'Jabber')  {$message = "News: $newsservice\n<b><a href=\"$address\">$title</a></b>\n$description";}
        elsif ($account_name eq 'MSN')  {$message = "News: $newsservice\n$title\n$address\n$description";}
        elsif ($account_name eq 'Yahoo'){$message = "News: $newsservice\n<b>$title</b>\n$address\n$description";}
        else                            {$message = "News: $newsservice\n<b><a href=\"$address\">$title</a></b>\n$description";}
        send_msg($account, $name, $message);
        
        
        }
    my $query = $database->prepare("DELETE FROM `newsnew` WHERE `address`  = ?");
    $query->execute($address);

    }

print "timeout\n";
if ($usetimeout eq 1) {Gaim::timeout_add($plugin, 10, \&timeout);}
return "";
}



sub sub_unknown
{
my $message = shift;
$message = "Unknown function:".$message."\n";
$message .= "For Help type 'help'";
return $message;
}


sub sub_help
{
my $message = shift;
$message = "Available commands:\n";
foreach my $key (keys %functions) {
    $message .= $functions{$key}[2]."\n";
    }
return $message;
}












sub plugin_load {
$plugin = shift;
Gaim::signal_connect(Gaim::Conversation::gaim_conversations_get_handle, "received-im-msg", $plugin, \&got_msg, 0);


restore_database();
#Gaim::timeout_add($plugin, 10, \&timeout);


}

sub plugin_unload {
my $plugin = shift;
}


sub restore_database{

if (!$database or $database->ping){
    $database = DBI->connect("dbi:mysql:database=imbbs;host=localhost;port=3306", "root", "")
                or die "Couldn't connect to database: " . DBI->errstr;
    }


}
