2 ### Reply.pl: Kevin Lenzo (c) 1997
6 # x is y === $lhs $mhs $rhs
10 # rhs - factoid message.
14 use POSIX qw(strftime);
15 use Encode qw(encode_utf8 is_utf8);
17 use vars qw($msgType $uh $lastWho $ident);
18 use vars qw(%lang %lastWho);
22 my ( $lhs, $mhs, $rhs );
23 my ( $reply, $count, $fauthor, $result, $factoid, $search, @searches );
24 $orig{message} = $message;
26 if ( !defined $message or $message =~ /^\s*$/ ) {
27 &WARN("getR: message == NULL.");
31 $message =~ tr/A-Z/a-z/;
34 split( /\s+/, &getChanConfDefault( 'factoidSearch', '_default', $chan ) );
35 &::DEBUG( "factoidSearch: $chan is: " . join( ':', @searches ) );
37 # requesting the _default one, ignore factoidSearch
38 if ( $message =~ /^_default\s+/ ) {
39 @searches = ('_default');
40 $message =~ s/^_default\s+//;
43 # check for factoids with each prefix
44 foreach $search (@searches) {
45 if ( $search eq '$chan' ) {
46 $factoid = "$chan $message";
48 elsif ( $search eq '_default' ) {
52 $factoid = "$search $message";
54 ( $count, $fauthor, $result ) = &sqlSelect(
56 "requested_count,created_by,factoid_value",
57 { factoid_key => $factoid }
61 $result = encode_utf8($result) if is_utf8($result);
68 return "\"$factoid\" $mhs \"$rhs\"" if ($literal);
74 # if there was a head...
75 my (@poss) = split '\|\|', $result;
77 $poss[$#poss] =~ s/\s$//;
80 $result = &getRandom(@poss);
84 $result = &SARit($result);
87 if ( $result ne '' ) {
88 ### AT LAST, REPEAT PREVENTION CODE REMOVED IN FAVOUR OF GLOBAL
89 ### FLOOD REPETION AND PROTECTION. -20000124
92 ### FIXME: old mysql/sqlite doesn't support
93 ### "requested_count=requested_count+1".
97 { 'factoid_key' => $factoid },
100 requested_time => time(),
101 requested_count => $count
105 # TODO: rename $real to something else!
108 # my $author = &getFactInfo($lhs,'created_by') || '';
109 # $real++ if ($author =~ /^\Q$who\E\!/);
110 # $real++ if (&IsFlag('n'));
111 $real = 0 if ( $msgType =~ /public/ );
113 ### fix up the reply.
114 # only remove '<reply>'
115 if ( !$real and $reply =~ s/^\s*<reply>\s*//i ) {
118 if ( $reply =~ s/^are /$lhs are /i ) {
119 &VERB( "Reply.pl: el-cheapo 'are' fix executed.", 2 );
123 elsif ( !$real and $reply =~ s/^\s*<action>\s*(.*)/\cAACTION $1\cA/i ) {
125 # only remove '<action>' and make it an action.
127 else { # not a short reply
130 if ( exists $bots{$nuh} and $rhs !~ /^\s*$/ ) {
131 return "$lhs $mhs $rhs";
134 ### bot->person reply.
135 # result is random if separated by '||'.
136 # rhs is full factoid with '||'.
137 if ( $mhs eq 'is' ) {
138 $reply = &getRandom( keys %{ $lang{'factoid'} } );
139 $reply =~ s/##KEY/$lhs/;
140 $reply =~ s/##VALUE/$result/;
143 $reply = "$lhs $mhs $result";
146 if ( $reply =~ s/^\Q$who\E is/you are/i ) {
151 if ( $reply =~ /^you are / or $reply =~ / you are / ) {
152 return if ($addressed);
158 # remove excessive beginning and end whitespaces.
159 $reply =~ s/^\s+|\s+$//g;
161 if ( $reply =~ /^\s+$/ ) {
162 &DEBUG("Reply: Null factoid ($message)");
166 return $reply unless ( $reply =~ /\$/ );
172 # don't evaluate if it has factoid arguments.
173 # if ($message =~ /^cmd:/i) {
174 # &status("Reply: not doing substVars (eval dollar vars)");
176 $reply = &substVars( $reply, 1 );
185 my ( $l, $r ) = ( 0, 0 ); # l = left, r = right.
186 my ( $s, $t ) = ( 0, 0 ); # s = start, t = marker.
191 foreach ( split //, $string ) {
208 my $substr = substr( $old, $s, $i - $s + 1 );
209 push( @rand, substr( $old, $t + 1, $i - $t - 1 ) );
211 my $rand = $rand[ rand @rand ];
213 # &status("SARing '$substr' to '$rand'.");
214 $string =~ s/\Q$substr\E/$rand/;
219 if ( $_ eq "|" and $l + $r == 0 and $l == 1 ) {
220 push( @rand, substr( $old, $t + 1, $i - $t - 1 ) );
227 if ( $old eq $string ) {
228 &WARN("smart_replace: no subst made. (string => $string)");
239 while ( $txt =~ /\((.*?)\)\?/ ) {
241 if ( rand() > 0.5 ) { # fix.
242 &status("Factoid transform: keeping '$str'.");
243 $txt =~ s/\(\Q$str\E\)\?/$str/;
246 &status("Factoid transform: removing '$str'.");
247 $txt =~ s/\(\Q$str\E\)\?\s?//;
250 last if ( $done >= 10 ); # just in case.
254 # EG: (0-32768) => 6325
255 ### TODO: (1-10,20-30,40) => 24
256 while ( $txt =~ /\((\d+)-(\d+)\)/ ) {
257 my ( $lower, $upper ) = ( $1, $2 );
258 my $new = int( rand $upper - $lower ) + $lower;
260 &status("SARing '$&' to '$new' (2).");
263 last if ( $done >= 10 ); # just in case.
267 # EG: (blah1|blah2|blah3|) => blah1
268 while ( $txt =~ /.*\((.*\|.*?)\).*/ ) {
269 $txt = &smart_replace($txt);
272 last if ( $done >= 10 ); # just in case.
274 &status("Reply.pl: $done SARs done.") if ($done);
278 while ( $txt =~ /<URL>(.*)<\/URL>/ ) {
279 &status("we have to norm this <URL></URL> stuff, SARing");
281 if ( $foobar =~ m/(http:\/\/[^?]+)\?(.*)/ ) {
282 my ( $pig1, $pig2 ) = ( $1, $2 );
283 &status("SARing using URLencode");
284 $pig2 =~ s/([^\w])/sprintf("%%%02x",ord($1))/gie;
285 $foobar = $pig1 . "?" . $pig2;
287 $txt =~ s/<URL>(.*)<\/URL>/$foobar/;
293 my ( $reply, $flag ) = @_;
295 # $date, $time, $day.
296 # TODO: support localtime.
297 my $date = strftime( "%Y.%m.%d", gmtime() );
298 $reply =~ s/\$date/$date/gi;
299 my $time = strftime( "%k:%M:%S", gmtime() );
300 $reply =~ s/\$time/$time/gi;
301 my $day = strftime( "%A", gmtime() );
302 $reply =~ s/\$day/$day/gi;
304 # support $ident when I have multiple nicks
305 my $mynick = $conn->nick() if $conn;
309 $reply =~ s/\$nick/$who/g;
310 $reply =~ s/\$who/$who/g; # backward compat.
313 if ( $reply =~ /\$(user(name)?|host)/ ) {
314 my ( $username, $hostname ) = split /\@/, $uh;
315 $reply =~ s/\$user(name)?/$username/g;
316 $reply =~ s/\$host(name)?/$hostname/g;
318 $reply =~ s/\$chan(nel)?/$talkchannel/g;
319 if ( $msgType =~ /public/ ) {
320 $reply =~ s/\$lastspeaker/$lastWho{$talkchannel}/g;
323 $reply =~ s/\$lastspeaker/$lastWho/g;
326 if ( $reply =~ /\$rand/ ) {
330 if ( $reply =~ /\$randnick/ ) {
331 my @nicks = keys %{ $channels{$chan}{''} };
332 my $randnick = $nicks[ int( $rand * $#nicks ) ];
333 $reply =~ s/\$randnick/$randnick/g;
337 if ( $reply =~ /\$rand(\d+)(\.(\d+))?/ ) {
342 #&DEBUG("dot => $dot, max => $max, rand=>$rand");
343 $rand = sprintf( "%.*f", $dot, $rand * $max );
345 &DEBUG("swapping $orig to $rand");
346 $reply =~ s/\Q$orig\E/$rand/eg;
349 $reply =~ s/\$rand/$rand/g;
353 $reply =~ s/\$ident/$mynick/g;
355 if ( $reply =~ /\$startTime/ ) {
356 my $time = scalar( gmtime $^T );
357 $reply =~ s/\$startTime/$time/;
360 if ( $reply =~ /\$uptime/ ) {
361 my $uptime = &Time2String( time() - $^T );
362 $reply =~ s/\$uptime/$uptime/;
365 if ( $reply =~ /\$factoids/ ) {
366 my $factoids = &countKeys('factoids');
367 $reply =~ s/\$factoids/$factoids/;
370 if ( $reply =~ /\$Fupdate/ ) {
372 "\002$count{'Update'}\002 "
373 . &fixPlural( 'modification', $count{'Update'} );
374 $reply =~ s/\$Fupdate/$x/;
377 if ( $reply =~ /\$Fquestion/ ) {
379 "\002$count{'Question'}\002 "
380 . &fixPlural( 'question', $count{'Question'} );
381 $reply =~ s/\$Fquestion/$x/;
384 if ( $reply =~ /\$Fdunno/ ) {
386 "\002$count{'Dunno'}\002 " . &fixPlural( 'dunno', $count{'Dunno'} );
387 $reply =~ s/\$Fdunno/$x/;
390 $reply =~ s/\$memusage/$memusage/;
397 # vim:ts=4:sw=4:expandtab:tw=80