]> git.donarmstrong.com Git - infobot.git/blobdiff - src/CommandStubs.pl
- patch from Morten Brix Pedersen <morten@wtf.dk>. Thanks!
[infobot.git] / src / CommandStubs.pl
index 8ee0f27c8c625a8ba23a06e07cd973f26d22377a..1a55669aef5b19ad323f1480aa82a45997506e3f 100644 (file)
@@ -48,14 +48,15 @@ sub parseCmdHook {
        return 0;
     }
 
+    if (!defined $cmd) {
+       &WARN("cstubs: cmd == NULL.");
+       return 0;
+    }
+
     foreach (keys %{"hooks_$hashname"}) {
        # rename to something else! like $id or $label?
        my $ident = $_;
 
-       if (!defined $cmd or !defined $ident) {
-           &WARN("cstubs: cmd or ident == NULL. ($cmd, $ident)");
-           next;
-       }
        next unless ($cmd =~ /^$ident$/i);
 
        if ($done) {
@@ -72,7 +73,7 @@ sub parseCmdHook {
        }
 
        if ($hash{NoArgs} and $flatarg) {
-           &DEBUG("cmd $ident does not take args; skipping.");
+           &DEBUG("cmd $ident does not take args ('$flatarg'); skipping.");
            next;
        }
 
@@ -262,7 +263,7 @@ sub Modules {
     }
 
     # google searching. Simon++
-    if ($message =~ /^(?:search\s+)?(\S+)\s+for\s+['"]?(.*?)['"]?\s*\?*$/i) {
+    if ($message =~ /^(?:search\s+)?(\S+)\s+for\s+['"]?(.*?)["']?\s*\?*$/i) {
        return unless (&hasParam("wwwsearch"));
 
        &Forker("wwwsearch", sub { &W3Search::W3Search($1,$2); } );
@@ -271,32 +272,96 @@ sub Modules {
        return;
     }
 
-    # text counters.
-    if ($_ = &getChanConf("ircTextCounters")) {
-       s/([^\w\s])/\\$1/g;
-       my $z = join '|', split ' ';
+    # text counters. (eg: hehstats)
+    my $itc;
+    $itc = &getChanConf("ircTextCounters");
+    $itc = &findChanConf("ircTextCounters") unless ($itc);
+    if ($itc) {
+       $itc =~ s/([^\w\s])/\\$1/g;
+       my $z = join '|', split ' ', $itc;
+
+       if ($msgType eq "privmsg" and $message =~ / ($mask{chan})$/) {
+           &DEBUG("ircTC: privmsg detected; chan = $1");
+           $chan = $1;
+       }
+
+       if ($message =~ /^_stats(\s+(\S+))$/i) {
+           &textstats_main($2);
+           return;
+       }
 
        if ($message =~ /^($z)stats(\s+(\S+))?$/i) {
            my $type    = $1;
            my $arg     = $3;
 
+           # even more uglier with channel/time arguments.
+           my $c       = $chan;
+#          my $c       = $chan || "PRIVATE";
+           my $where   = "type=".&dbQuote($type);
+           $where      .= " AND channel=".&dbQuote($c) if (defined $c);
+           &DEBUG("not using chan arg") if (!defined $c);
+           my $sum = (&dbRawReturn("SELECT SUM(counter) FROM stats"
+                       ." WHERE ".$where ))[0];
+
            if (!defined $arg or $arg =~ /^\s*$/) {
-               my $x = (&dbRawReturn("SELECT SUM(counter) FROM stats WHERE type=".&dbQuote($type) ))[0];
+               # this is way fucking ugly.
+
+               my %hash = &dbGetCol("stats", "nick,counter",
+                       $where." ORDER BY counter DESC LIMIT 3", 1);
+               my $i;
+               my @top;
+
+               # unfortunately we have to sort it again!
+               # todo: make dbGetCol return hash and array? too much effort.
+               my $tp = 0;
+               foreach $i (sort { $b <=> $a } keys %hash) {
+                   foreach (keys %{ $hash{$i} }) {
+                       my $p   = sprintf("%.01f", 100*$i/$sum);
+                       $tp     += $p;
+                       push(@top, "\002$_\002 -- $i ($p%)");
+                   }
+               }
+               my $topstr = "";
+               &DEBUG("*stats: tp => $tp");
+               if (scalar @top) {
+                   $topstr = ".  Top ".scalar(@top).": ".join(', ', @top);
+               }
 
-               if (defined $x) {
-                   &pSReply("total count of '$type': $x");
+               if (defined $sum) {
+                   &pSReply("total count of \037$type\037 on \002$c\002: $sum$topstr");
                } else {
-                   &pSReply("zero counter for '$type'.");
+                   &pSReply("zero counter for \037$type\037.");
                }
            } else {
-               my $x = (&dbRawReturn("SELECT SUM(counter) FROM stats WHERE type=".
-                       &dbQuote($type)." AND nick=".&dbQuote($arg) ))[0];
+               my $x = (&dbRawReturn("SELECT SUM(counter) FROM stats".
+                       " WHERE $where AND nick=".&dbQuote($arg) ))[0];
 
-               if (defined $x) {       # defined.
-                   &pSReply("$arg has said $type $x times");
-               } else {                # !defined.
+               if (!defined $x) {      # !defined.
                    &pSReply("$arg has not said $type yet.");
+                   return;
+               }
+
+               # defined.
+               my @array = &dbGet("stats", "nick",
+                       $where." ORDER BY counter", 1);
+               my $good = 0;
+               my $i = 0;
+               for($i=0; $i<scalar @array; $i++) {
+                   next unless ($array[0] =~ /^\Q$who\E$/);
+                   $good++;
+                   last;
+               }
+               $i++;
+
+               my $total = scalar(@array);
+               my $xtra = "";
+               if ($total and $good) {
+                   my $pct = sprintf("%.01f", 100*(1+$total-$i)/$total);
+                   $xtra = ", ranked $i\002/\002$total (percentile: \002$pct\002 %)";
                }
+
+               my $pct1 = sprintf("%.01f", 100*$x/$sum);
+               &pSReply("\002$arg\002 has said \037$type\037 \002$x\002 times (\002$pct1\002 %)$xtra");
            }
 
            return;
@@ -405,7 +470,7 @@ sub Modules {
     }
 
     # Topic management. xk++
-    # may want to add a flag(??) for topic in the near future. -xk
+    # may want to add a userflags for topic. -xk
     if ($message =~ /^topic(\s+(.*))?$/i) {
        return unless (&hasParam("topic"));
 
@@ -504,7 +569,8 @@ sub uptime {
 
 # seen.
 sub seen {
-    my($person) = @_;
+    my($person) = lc shift;
+    $person =~ s/\?*$//;
 
     if (!defined $person or $person =~ /^$/) {
        &help("seen");
@@ -517,7 +583,6 @@ sub seen {
     }
 
     my @seen;
-    $person =~ s/\?*$//;
 
     &seenFlush();      # very evil hack. oh well, better safe than sorry.
 
@@ -526,7 +591,7 @@ sub seen {
     if ($person eq "random") {
        @seen = &randKey("seen", $select);
     } else {
-       @seen = &dbGet("seen", $select, "nick='$person'");
+       @seen = &dbGet("seen", $select, "nick=".&dbQuote($person) );
     }
 
     if (scalar @seen < 2) {
@@ -565,7 +630,7 @@ sub seen {
                 "saying\002:\002 '$seen[4]'.";
     }
 
-    &performStrictReply($reply);
+    &pSReply($reply);
     return;
 }
 
@@ -664,7 +729,7 @@ sub lart {
        }
     }
 
-    my $line = &getRandomLineFromFile($bot_misc_dir. "/blootbot.lart");
+    my $line = &getRandomLineFromFile($bot_data_dir. "/blootbot.lart");
     if (defined $line) {
        if ($target =~ /^(me|you|itself|\Q$ident\E)$/i) {
            $line =~ s/WHO/$who/g;
@@ -737,12 +802,24 @@ sub do_verstats {
        return;
     }
 
-    &msg($who, "Sending CTCP VERSION...");
+    &msg($who, "Sending CTCP VERSION to #$chan...");
     $conn->ctcp("VERSION", $chan);
     $cache{verstats}{chan}     = $chan;
     $cache{verstats}{who}      = $who;
     $cache{verstats}{msgType}  = $msgType;
 
+    $conn->schedule(30, sub {
+       my $c           = lc $cache{verstats}{chan};
+       @vernicktodo    = ();
+
+       foreach (keys %{ $channels{$c}{''} } ) {
+           next if (grep /^\Q$_\E$/i, @vernick);
+           push(@vernicktodo, $_);
+       }
+
+       &verstats_flush();
+    } );
+
     $conn->schedule(60, sub {
        my $vtotal      = 0;
        my $c           = lc $cache{verstats}{chan};
@@ -760,7 +837,7 @@ sub do_verstats {
        my $unknown     = $total - $vtotal;
        my $perc        = sprintf("%.1f", $unknown * 100 / $total);
        $perc           =~ s/.0$//;
-       $sorted{$perc}{"unknown/cloak"} = "$unknown ($perc%)";
+       $sorted{$perc}{"unknown/cloak"} = "$unknown ($perc%)" if ($unknown);
 
        foreach (keys %ver) {
            my $count   = scalar keys %{ $ver{$_} };
@@ -789,6 +866,101 @@ sub do_verstats {
     return;
 }
 
+sub verstats_flush {
+    for (1..5) {
+       last unless (scalar @vernicktodo);
+
+       my $n = shift(@vernicktodo);
+       $conn->ctcp("VERSION", $n);
+    }
+
+    return unless (scalar @vernicktodo);
+
+    $conn->schedule(3, \&verstats_flush() );
+}
+
+sub textstats_main {
+    my($arg) = @_;
+
+    # even more uglier with channel/time arguments.
+    my $c      = $chan;
+#    my $c     = $chan || "PRIVATE";
+    my $where  = "channel=".&dbQuote($c) if (defined $c);
+    &DEBUG("not using chan arg") if (!defined $c);
+    my $sum = (&dbRawReturn("SELECT SUM(counter) FROM stats"
+               ." WHERE ".$where ))[0];
+
+    if (!defined $arg or $arg =~ /^\s*$/) {
+       # this is way fucking ugly.
+       &DEBUG("_stats: !arg");
+
+       my %hash = &dbGetCol("stats", "nick,counter",
+               $where." ORDER BY counter DESC LIMIT 3", 1);
+       my $i;
+       my @top;
+
+       # unfortunately we have to sort it again!
+       # todo: make dbGetCol return hash and array? too much effort.
+       my $tp = 0;
+       foreach $i (sort { $b <=> $a } keys %hash) {
+           foreach (keys %{ $hash{$i} }) {
+               my $p   = sprintf("%.01f", 100*$i/$sum);
+               $tp     += $p;
+               push(@top, "\002$_\002 -- $i ($p%)");
+           }
+       }
+
+       my $topstr = "";
+       &DEBUG("*stats: tp => $tp");
+       if (scalar @top) {
+           $topstr = ".  Top ".scalar(@top).": ".join(', ', @top);
+       }
+
+       if (defined $sum) {
+           &pSReply("total count of \037$type\037 on \002$c\002: $sum$topstr");
+       } else {
+           &pSReply("zero counter for \037$type\037.");
+       }
+    } else {
+       my %hash = &dbGetCol("stats", "type,counter",
+               "$where AND nick=".&dbQuote($arg) );
+
+       foreach (keys %hash) {
+           &DEBUG("_stats: hash{$_} => $hash{$_}");
+           # ranking.
+           my @array = &dbGet("stats", "nick",
+               $where." ORDER BY counter", 1);
+           my $good = 0;
+           my $i = 0;
+           for($i=0; $i<scalar @array; $i++) {
+               next unless ($array[0] =~ /^\Q$who\E$/);
+               $good++;
+               last;
+           }
+           $i++;
+
+           my $total = scalar(@array);
+           &DEBUG("   i => $i, good => $good, total => $total");
+       }
+
+       return;
+
+       if (!defined $x) {      # !defined.
+           &pSReply("$arg has not said $type yet.");
+           return;
+       }
+
+       my $xtra = "";
+       if ($total and $good) {
+           my $pct = sprintf("%.01f", 100*(1+$total-$i)/$total);
+           $xtra = ", ranked $i\002/\002$total (percentile: \002$pct\002 %)";
+       }
+
+       my $pct1 = sprintf("%.01f", 100*$x/$sum);
+       &pSReply("\002$arg\002 has said \037$type\037 \002$x\002 times (\002$pct1\002 %)$xtra");
+    }
+}
+
 sub nullski { my ($arg) = @_; return unless (defined $arg);
        foreach (`$arg`) { &msg($who,$_); } }