+# Command statistics.
+sub conninfo {
+ my $reply = 'conninfo:';
+ my $key;
+ foreach $key ( sort keys %::conns ) {
+ my $myconn = $::conns{$key};
+ $reply .= " $key/";
+ next if (!defined $myconn);
+ my $mynick = $myconn->nick();
+ $reply .= "$mynick";
+ }
+ &performStrictReply( "conninfo: $reply.");
+}
+
+# Factoid extension info. xk++
+sub factinfo {
+ my $faqtoid = lc shift(@_);
+ my $query = '';
+
+ if ( $faqtoid =~ /^\-(\S+)(\s+(.*))$/ ) {
+ &msg( $who,
+ 'error: individual factoid info queries not supported as yet.' );
+ &msg( $who,
+ "it's possible that the factoid mistakenly begins with '-'." );
+ return;
+
+ $query = lc $1;
+ $faqtoid = lc $3;
+ }
+
+ &CmdFactInfo( $faqtoid, $query );
+}
+
+sub factstats {
+ my $type = shift(@_);
+
+ &Forker(
+ 'Factoids',
+ sub {
+ &performStrictReply( &CmdFactStats($type) );
+ }
+ );
+}
+
+sub karma {
+ my $target = lc( shift || $who );
+ my $karma =
+ &sqlSelect( 'stats', 'counter', { nick => $target, type => 'karma' } )
+ || 0;
+
+ if ( $karma != 0 ) {
+ &performStrictReply("$target has karma of $karma");
+ }
+ else {
+ &performStrictReply("$target has neutral karma");
+ }
+}
+
+sub tell {
+ my $args = shift;
+ my ( $target, $tell_obj ) = ( '', '' );
+ my $dont_tell_me = 0;
+ my $reply;
+
+ ### is this fixed elsewhere?
+ $args =~ s/\s+/ /g; # fix up spaces.
+ $args =~ s/^\s+|\s+$//g; # again.
+
+ # this one catches most of them
+ if ( $args =~ /^(\S+) (-?)about (.*)$/i ) {
+ $target = $1;
+ $tell_obj = $3;
+ $dont_tell_me = ($2) ? 1 : 0;
+
+ $tell_obj = $who if ( $tell_obj =~ /^(me|myself)$/i );
+ $query = $tell_obj;
+ }
+ elsif ( $args =~ /^(\S+) where (\S+) can (\S+) (.*)$/i ) {
+
+ # i'm sure this could all be nicely collapsed
+ $target = $1;
+ $tell_obj = $4;
+ $query = $tell_obj;
+
+ }
+ elsif ( $args =~ /^(\S+) (what|where) (.*?) (is|are)[.?!]*$/i ) {
+ $target = $1;
+ $qWord = $2;
+ $tell_obj = $3;
+ $verb = $4;
+ $query = "$qWord $verb $tell_obj";
+
+ }
+ elsif ( $args =~ /^(.*?) to (\S+)$/i ) {
+ $target = $3;
+ $tell_obj = $2;
+ $query = $tell_obj;
+ }
+
+ # check target type. Deny channel targets.
+ if ( $target !~ /^$mask{nick}$/ or $target =~ /^$mask{chan}$/ ) {
+ &msg( $who, "No, $who, I won't. (target invalid?)" );
+ return;
+ }
+
+ $target = $talkchannel if ( $target =~ /^us$/i );
+ $target = $who if ( $target =~ /^(me|myself)$/i );
+
+ &status("tell: target = $target, query = $query");
+
+ # 'intrusive'.
+ # if ($target !~ /^$mask{chan}$/ and !&IsNickInAnyChan($target)) {
+ # &msg($who, "No, $target is not in any of my chans.");
+ # return;
+ # }
+
+ # self.
+ if ( $target =~ /^\Q$ident\E$/i ) {
+ &msg( $who, "Isn't that a bit silly?" );
+ return;
+ }
+
+ my $oldwho = $who;
+ my $oldmtype = $msgType;
+ $who = $target;
+ my $result = &doQuestion($tell_obj);
+
+ # ^ returns '0' if nothing was found.
+ $who = $oldwho;
+
+ # no such factoid.
+ if ( !defined $result || $result =~ /^0?$/ ) {
+ $who = $target;
+ $msgType = 'private';
+
+ # support command redirection.
+ # recursive cmdHooks aswell :)
+ my $done = 0;
+ $done++ if &parseCmdHook($tell_obj);
+ $message = $tell_obj;
+ $done++ unless ( &Modules() );
+
+ &VERB( 'tell: setting old values of who and msgType.', 2 );
+ $who = $oldwho;
+ $msgType = $oldmtype;
+
+ if ($done) {
+ &msg( $who, "told $target about CMD '$tell_obj'" );
+ }
+ else {
+ &msg( $who, "i dunno what is '$tell_obj'." );
+ }
+
+ return;
+ }
+
+ # success.
+ &status("tell: <$who> telling $target about $tell_obj.");
+ if ( $who ne $target ) {
+ if ($dont_tell_me) {
+ &msg( $who, "told $target about $tell_obj." );
+ }
+ else {
+ &msg( $who, "told $target about $tell_obj ($result)" );
+ }
+
+ $reply = "$who wants you to know: $result";
+ }
+ else {
+ $reply = "telling yourself: $result";