From: dms <dms@c11ca15a-4712-0410-83d8-924469b57eb5>
Date: Mon, 6 Aug 2001 14:55:24 +0000 (+0000)
Subject: - irctextcounters: add percentile/ranking.
X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=92c3870d1fd6aa5f063a57cfb690aea12ec77df7;p=infobot.git

- irctextcounters: add percentile/ranking.
- irctextcounters: added channel support.
- added command stats counter to be logged to sql table.
- added findChanConf() - hack to get any conf value.
- update stats when requesting factoid args factoid.
- added irc hooks for whoischannels,useronchannel,whois,422.


git-svn-id: https://svn.code.sf.net/p/infobot/code/trunk/blootbot@512 c11ca15a-4712-0410-83d8-924469b57eb5
---

diff --git a/src/CommandStubs.pl b/src/CommandStubs.pl
index eba7a50..91dfc72 100644
--- a/src/CommandStubs.pl
+++ b/src/CommandStubs.pl
@@ -272,21 +272,33 @@ sub Modules {
 	return;
     }
 
-    # text counters.
-    # warn: lets process it anyway.
-    if (1 and $_ = &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 ($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];
+	    &DEBUG("type => $type, arg => $arg");
+
 	    if (!defined $arg or $arg =~ /^\s*$/) {
 		# this is way fucking ugly.
-		my $x = (&dbRawReturn("SELECT SUM(counter) FROM stats WHERE type=".&dbQuote($type) ))[0];
-		my %hash = &dbGetCol("stats", "nick,counter", "type=".&dbQuote($type).
-			" ORDER BY counter DESC LIMIT 3", 1);
+
+		my %hash = &dbGetCol("stats", "nick,counter",
+			$where." ORDER BY counter DESC LIMIT 3", 1);
 		my $i;
 		my @top;
 
@@ -295,7 +307,7 @@ sub Modules {
 		my $tp = 0;
 		foreach $i (sort { $b <=> $a } keys %hash) {
 		    foreach (keys %{ $hash{$i} }) {
-			my $p	= sprintf("%.01f", 100*$i/$x);
+			my $p	= sprintf("%.01f", 100*$i/$sum);
 			$tp	+= $p;
 			push(@top, "\002$_\002 -- $i ($p%)");
 		    }
@@ -306,20 +318,41 @@ sub Modules {
 		    $topstr = ".  Top ".scalar(@top).": ".join(', ', @top);
 		}
 
-		if (defined $x) {
-		    &pSReply("total count of '$type': $x$topstr");
+		if (defined $sum) {
+		    &pSReply("total count of '$type' on $c: $sum$topstr");
 		} else {
 		    &pSReply("zero counter for '$type'.");
 		}
 	    } 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/$total (percentile: $pct %)";
+		}
+
+		my $pct1 = sprintf("%.01f", 100*$x/$sum);
+		&pSReply("$arg has said $type $x times ($pct1 %)$xtra");
 	    }
 
 	    return;
diff --git a/src/Factoids/Question.pl b/src/Factoids/Question.pl
index e61b30f..93725e5 100644
--- a/src/Factoids/Question.pl
+++ b/src/Factoids/Question.pl
@@ -87,6 +87,7 @@ sub doQuestion {
 
     if (&IsChanConf("factoidArguments")) {
 	$result = &factoidArgs($query[0]);
+
 	return $result if (defined $result);
     }
 
@@ -186,6 +187,9 @@ sub factoidArgs {
 	my @vals;
 	my $arg = $_;
 
+	# todo: <greycat> ~punish apt for (Eating) (Parentheses)
+	# how the hell do I fix the above?
+
 	# todo: make eval work with $$i's :(
 	# fuck this is an ugly hack. it works though.
 	eval {
@@ -216,12 +220,21 @@ sub factoidArgs {
 	&status("Question: factoid Arguments for '$str'");
 	# todo: use getReply() - need to modify it :(
 	my $i	= 0;
-	my $r	= &getFactoid("CMD: $_");
+	my $q	= "CMD: $_";
+	my $r	= &getFactoid($q);
 	if (!defined $r) {
 	    &DEBUG("question: !result... should this happen?");
 	    return;
 	}
 
+	# update stats.
+	my $count = &getFactInfo($q, "requested_count") || 0;
+	$count++;   
+	&setFactInfo($q, "requested_by", $nuh);
+	&setFactInfo($q, "requested_time", time());
+	&setFactInfo($q, "requested_count", $count);
+	# end of update stats.
+
 	$result	= $r;
 	$result	=~ s/^\((.*?)\): //;
 
@@ -237,9 +250,9 @@ sub factoidArgs {
 	    my $done = 0;
 	    my $old = $result;
 	    while (1) {
-#		&DEBUG("Q: result => $result (1)");
+#		&DEBUG("Q: result => $result (1before)");
 		$result = &substVars($result);
-#		&DEBUG("Q: result => $result (1)");
+#		&DEBUG("Q: result => $result (1after)");
 
 		last if ($old eq $result);
 		$old = $result;
diff --git a/src/IRC/Irc.pl b/src/IRC/Irc.pl
index a5c0ca4..d6f81b6 100644
--- a/src/IRC/Irc.pl
+++ b/src/IRC/Irc.pl
@@ -135,12 +135,15 @@ sub irc {
 	$conn->add_handler('nick',	\&on_nick);
 	$conn->add_handler('quit',	\&on_quit);
 	$conn->add_handler('notice',	\&on_notice);
-	$conn->add_handler('whoisuser',	\&on_whoisuser);
+	$conn->add_handler('whoischannels', \&on_whoischannels);
+	$conn->add_handler('useronchannel', \&on_useronchannel);
+	$conn->add_handler('whois',	\&on_whois);
 	$conn->add_handler('other',	\&on_other);
 	$conn->add_global_handler('disconnect', \&on_disconnect);
 	$conn->add_global_handler([251,252,253,254,255], \&on_init);
 ###	$conn->add_global_handler([251,252,253,254,255,302], \&on_init);
 	$conn->add_global_handler(315, \&on_endofwho);
+	$conn->add_global_handler(422, \&on_endofwho); # nomotd.
 	$conn->add_global_handler(324, \&on_modeis);
 	$conn->add_global_handler(333, \&on_topicinfo);
 	$conn->add_global_handler(352, \&on_who);
@@ -430,11 +433,11 @@ sub joinchan {
 	$chan = lc $1;
     }
 
-    &status("joining $b_blue$chan$ob");
-
+    # hopefully validChan is right.
     if (&validChan($chan)) {
 	&status("join: already on $chan");
     } else {
+	&status("joining $b_blue$chan$ob");
 	if (!$conn->join($chan)) {
 	    &DEBUG("joinchan: join failed. trying connect!");
 	    $conn->connect();
@@ -449,6 +452,11 @@ sub part {
 	next if ($chan eq "");
 	$chan =~ tr/A-Z/a-z/;	# lowercase.
 
+	if ($chan !~ /^$mask{chan}$/) {
+	    &WARN("part: chan is invalid ($chan)");
+	    next;
+	}
+
 	&status("parting $chan");
 	if (!&validChan($chan)) {
 	    &WARN("part: not on $chan; doing anyway");
@@ -845,10 +853,15 @@ sub joinfloodCheck {
 
     ### Clean it up.
     my $delete = 0;
+    my $time = time();
     foreach $chan (keys %floodjoin) {
 	foreach $who (keys %{ $floodjoin{$chan} }) {
-	    my $time = time() - $floodjoin{$chan}{$who}{Time};
-	    next unless ($time > 10);
+	    my $t	= $floodjoin{$chan}{$who}{Time};
+	    next unless (defined $t);
+
+	    my $delta	= $time - $t;
+	    next unless ($delta > 10);
+
 	    delete $floodjoin{$chan}{$who};
 	    $delete++;
 	}
diff --git a/src/IRC/IrcHooks.pl b/src/IRC/IrcHooks.pl
index b181714..7f2e7f8 100644
--- a/src/IRC/IrcHooks.pl
+++ b/src/IRC/IrcHooks.pl
@@ -374,7 +374,7 @@ sub on_endofnames {
     # sync time should be done in on_endofwho like in BitchX
     if (exists $cache{jointime}{$chan}) {
 	my $delta_time = sprintf("%.03f", &timedelta($cache{jointime}{$chan}) );
-	$delta_time    = 0	if ($delta_time < 0);
+	$delta_time    = 0	if ($delta_time <= 0);
 	if ($delta_time > 100) {
 	    &WARN("endofnames: delta_time > 100 ($delta_time)");
 	}
@@ -382,7 +382,7 @@ sub on_endofnames {
 	&status("$b_blue$chan$ob: sync in ${delta_time}s.");
     }
 
-    rawout("MODE $chan");
+    &rawout("MODE $chan");
 
     my $txt;
     my @array;
@@ -756,6 +756,11 @@ sub on_part {
     $who	= $nick;
     $msgType	= "public";
 
+    if (0 and !exists $channels{$chan}) {
+	&DEBUG("on_part: found out we're on $chan!");
+	$channels{$chan} = 1;
+    }
+
     if (exists $floodjoin{$chan}{$nick}{Time}) {
 	delete $floodjoin{$chan}{$nick};
     }
@@ -818,17 +823,40 @@ sub on_public {
 
     # would this slow things down?
     if ($_ = &getChanConf("ircTextCounters")) {
+	my $time = time();
+
 	foreach (split /[\s]+/) {
-	    next unless ($msg =~ /^\Q$_\E$/i);
-	    &VERB("textcounters: $_ matched for $who",2);
+	    my $x = $_;
+
+	    # either full word or ends with a space, etc...
+	    next unless ($msg =~ /^\Q$x\E[\$\s!.]/i);
+
+	    &VERB("textcounters: $x matched for $who",2);
+	    my $c = $chan || "PRIVATE";
 
-	    my $v = &dbGet("stats", "counter", "nick=".&dbQuote($who).
-			" AND type='$msg'");
+	    my ($v,$t) = &dbGet("stats", "counter,time",
+			"nick=". &dbQuote($who)
+			." AND type=".&dbQuote($x)
+			." AND channel=".&dbQuote($c)
+	    );
 	    $v++;
 
-	    &dbReplace("stats", (nick => $who, type => $_, counter => $v) );
+	    # don't allow ppl to cheat the stats :-)
+	    next unless ($time - $t > 10);
+
+	    my %hash = (
+		nick	=> $who,
+		type	=> $x,
+		channel => $c,
+
+		time	=> $time,
+		counter => $v,
+	    );
+		
+
+	    &dbReplace("stats", %hash);
 	    # does not work, atleast with old mysql!!! :(
-#	    &dbReplace("stats", (nick => $who, type => $_, -counter => "counter+1") );
+#	    &dbReplace("stats", (nick => $who, type => $x, -counter => "counter+1") );
 	}
     }
 
@@ -1076,15 +1104,28 @@ sub on_who {
     $nuh{lc $args[5]} = $args[5]."!".$args[2]."\@".$args[3];
 }
 
-sub on_whoisuser {
+sub on_whois {
     my ($self, $event) = @_;
     my @args	= $event->args;
 
-    &DEBUG("on_whoisuser: @args");
-
     $nuh{lc $args[1]} = $args[1]."!".$args[2]."\@".$args[3];
 }
 
+sub on_whoischannels {
+    my ($self, $event) = @_;
+    my @args	= $event->args;
+
+    &DEBUG("on_whoischannels: @args");
+}
+
+sub on_useronchannel {
+    my ($self, $event) = @_;
+    my @args	= $event->args;
+
+    &DEBUG("on_useronchannel: @args");
+    &joinNextChan();
+}
+
 ###
 ### since joinnextchan is hooked onto on_endofnames, these are needed.
 ###
diff --git a/src/IRC/Schedulers.pl b/src/IRC/Schedulers.pl
index fd19da2..a7d38c4 100644
--- a/src/IRC/Schedulers.pl
+++ b/src/IRC/Schedulers.pl
@@ -29,7 +29,8 @@ sub setupSchedulers {
     &leakCheck(2);	# mandatory
     &ignoreCheck(1);	# mandatory
     &seenFlushOld(2);
-    &ircCheck(2);	# mandatory
+#    &ircCheck(2);	# mandatory
+    &ircCheck(1);	# mandatory
     &miscCheck(1);	# mandatory
     &miscCheck2(2);	# mandatory
     &shmFlush(1);	# mandatory
diff --git a/src/Misc.pl b/src/Misc.pl
index ffc6fb6..a598234 100644
--- a/src/Misc.pl
+++ b/src/Misc.pl
@@ -212,6 +212,11 @@ sub fixFileList {
 	my @keys = sort keys %{ $files{$file} };
 	my $i	 = scalar(@keys);
 
+	if (scalar @keys > 3) {
+	    pop @keys while (scalar @keys > 3);
+	    push(@keys, "...");
+	}
+
 	if ($i > 1) {
 	    $file .= "\002{\002". join("\002|\002", @keys) ."\002}\002";
 	} else {
@@ -572,7 +577,8 @@ sub validFactoid {
 	# symbols.
 	/(\"\*)/ and last;
 	/, / and last;
-	/^\'/ and last;
+	(/^'/ and /'$/) and last;
+	(/^"/ and /"$/) and last;
 
 	# delimiters.
 	/\=\>/ and last;		# '=>'.
@@ -587,11 +593,13 @@ sub validFactoid {
 	/ also$/ and last;
 	/ and$/ and last;
 	/^because / and last;
+	/^but / and last;
 	/^gives / and last;
 	/^h(is|er) / and last;
 	/^if / and last;
 	/ is,/ and last;
 	/ it$/ and last;
+	/^or / and last;
 	/ says$/ and last;
 	/^should / and last;
 	/^so / and last;
@@ -704,13 +712,21 @@ sub closeStats {
 
     foreach (keys %cmdstats) {
 	my $type	= $_;
-	my $i = &dbGet("stats", "counter", "nick=".&dbQuote($type).
+	my $i	= &dbGet("stats", "counter", "nick=".&dbQuote($type).
 			" AND type='cmdstats'");
+	my $z	= 0;
+	$z++ unless ($i);
+
 	$i	+= $cmdstats{$type};
 
-	&dbReplace("stats",
-		(nick => $type, type => "cmdstats", counter => $i)
-	);
+	my %hash = (
+		nick => $type,
+		type => "cmdstats",
+		counter => $i
+	);		
+	$hash{time} = time() if ($z);
+
+	&dbReplace("stats", %hash);
     }
 }
 
diff --git a/src/Modules/News.pl b/src/Modules/News.pl
index 58d33d5..bb2e6f2 100644
--- a/src/Modules/News.pl
+++ b/src/Modules/News.pl
@@ -396,7 +396,7 @@ sub list {
     &::msg($::who, "|= Last updated $timestr ago.");
     &::msg($::who, " \037Num\037  \037Item ".(" "x40)." \037");
 
-    &::DEBUG("list: expire = $expire");
+    &DEBUG("list: expire = $expire");
     &::DEBUG("list: eno    = $eno");
 
     my $i = 1;
@@ -983,4 +983,6 @@ sub stats {
     $i = $j = 0;
 }
 
+sub AUTOLOAD { &::AUTOLOAD(@_); }
+
 1;
diff --git a/src/Modules/UserDCC.pl b/src/Modules/UserDCC.pl
index 195fdf8..b5b64a6 100644
--- a/src/Modules/UserDCC.pl
+++ b/src/Modules/UserDCC.pl
@@ -444,10 +444,9 @@ sub userDCC {
 	&msg($who,"resetting...");
 	my @done;
 	foreach ( keys %channels, keys %chanconf ) {
-	    &DEBUG("reset: c => $c");
-	    next if (grep /^\Q$_\E$/i, @done);
+	    my $c = $_;
+	    next if (grep /^\Q$c\E$/i, @done);
 
-	    &DEBUG("reset: should part... c => $c");
 	    &part($_);
 
 	    push(@done, $_);
diff --git a/src/Process.pl b/src/Process.pl
index 8133d7a..255730f 100644
--- a/src/Process.pl
+++ b/src/Process.pl
@@ -72,6 +72,7 @@ sub process {
 	&joinchan($chankey);
 	&status("JOIN $chankey <$who>");
 	&msg($who, "joining $chankey");
+	&joinNextChan();	# hack.
 
 	return;
     }
diff --git a/src/core.pl b/src/core.pl
index 63c8406..4bda802 100644
--- a/src/core.pl
+++ b/src/core.pl
@@ -299,6 +299,31 @@ sub getChanConf {
     return $chanconf{"_default"}{$param};
 }
 
+#####
+#  Usage: &findChanConf($param);
+#  About: Retrieve value for 'param' value from any chan.
+# Return: scalar for success, undef for failure.
+sub findChanConf {
+    my($param)	= @_;
+
+    if (!defined $param) {
+	&WARN("param == NULL.");
+	return 0;
+    }
+
+    my $c;
+    foreach $c (keys %chanconf) {
+	foreach (keys %{ $chanconf{$c} }) {
+	    next unless (/^$param$/);
+
+	    &DEBUG("chanconf{$c}{$_} ...");
+	    return $chanconf{$c}{$_};
+	}
+    }
+
+    return;
+}
+
 sub showProc {
     my ($prefix) = $_[0] || "";
 
diff --git a/src/db_mysql.pl b/src/db_mysql.pl
index 185a5bf..357f4a8 100644
--- a/src/db_mysql.pl
+++ b/src/db_mysql.pl
@@ -88,13 +88,10 @@ sub dbGetCol {
     $query	.= " WHERE ".$where if ($where);
     my %retval;
 
-    &DEBUG("dbGetCol: query => '$query'.");
-
     my $sth = $dbh->prepare($query);
     &SQLDebug($query);
     if (!$sth->execute) {
 	&ERROR("GetCol: execute: '$query'");
-#	&ERROR("GetCol => $DBI::errstr");
 	$sth->finish;
 	return;
     }