]> git.donarmstrong.com Git - infobot.git/blob - src/Factoids/Reply.pl
fix rand, factoids, convert to gmtime
[infobot.git] / src / Factoids / Reply.pl
1 ###
2 ### Reply.pl: Kevin Lenzo   (c) 1997
3 ###
4
5 ##
6 # x is y === $lhs $mhs $rhs
7 #
8 #   lhs - factoid.
9 #   mhs - verb.
10 #   rhs - factoid message.
11 ##
12
13 if (&IsParam("useStrict")) { use strict; }
14
15 use vars qw($msgType $uh $lastWho $ident);
16 use vars qw(%lang %lastWho);
17
18 sub getReply {
19     my($message) = @_;
20     my($lhs,$mhs,$rhs);
21     my($reply);
22     $orig{message} = $message;
23
24     if (!defined $message or $message =~ /^\s*$/) {
25         &WARN("getR: message == NULL.");
26         return '';
27     }
28
29     $message =~ tr/A-Z/a-z/;
30
31     my ($result, $fauthor, $count) = &dbGet("factoids", 
32         "factoid_value,created_by,requested_count", "factoid_key=".&dbQuote($message) );
33     if ($result) {
34         $lhs = $message;
35         $mhs = "is";
36         $rhs = $result;
37
38         return "$lhs $mhs $rhs" if ($literal);
39     } else {
40         return '';
41     }
42
43     # if there was a head...
44     my(@poss) = split '\|\|', $result;
45     $poss[0] =~ s/^\s//;
46     $poss[$#poss] =~ s/\s$//;
47
48     if (@poss > 1) {
49         $result = &getRandom(@poss);
50         $result =~ s/^\s*//;
51     }
52
53     $result     = &SARit($result);
54
55     $reply      = $result;
56     if ($result ne "") {
57         ### AT LAST, REPEAT PREVENTION CODE REMOVED IN FAVOUR OF GLOBAL
58         ### FLOOD REPETION AND PROTECTION. -20000124
59
60         # stats code.
61         ### FIXME: old mysql doesn't support
62         ### "requested_count=requested_count+1".
63         $count++;
64         ### BROKEN!!! - Tim Riker <Tim@Rikers.org> says it's fixed now
65         if (0) {        # old code.
66             &setFactInfo($lhs,"requested_by", $nuh);
67             &setFactInfo($lhs,"requested_time", time());
68             &setFactInfo($lhs,"requested_count", $count);
69         } else {
70             &dbSet("factoids", {'factoid_key' => $lhs}, {
71                 requested_by    => $nuh,
72                 requested_time  => time(),
73                 requested_count => $count
74             } );
75         }
76
77         # todo: rename $real to something else!
78         my $real   = 0;
79 #       my $author = &getFactInfo($lhs,"created_by") || '';
80 #       $real++ if ($author =~ /^\Q$who\E\!/);
81 #       $real++ if (&IsFlag("n"));
82         $real = 0 if ($msgType =~ /public/);
83
84         ### fix up the reply.
85         # only remove '<reply>'
86         if (!$real and $reply =~ s/^\s*<reply>\s*//i) {
87             # 'are' fix.
88             if ($reply =~ s/^are /$lhs are /i) {
89                 &VERB("Reply.pl: el-cheapo 'are' fix executed.",2);
90             }
91
92         } elsif (!$real and $reply =~ s/^\s*<action>\s*(.*)/\cAACTION $1\cA/i) {
93             # only remove '<action>' and make it an action.
94         } else {                # not a short reply
95
96             ### bot->bot reply.
97             if (exists $bots{$nuh} and $rhs !~ /^\s*$/) {
98                 return "$lhs $mhs $rhs";
99             }
100
101             ### bot->person reply.
102             # result is random if separated by '||'.
103             # rhs is full factoid with '||'.
104             if ($mhs eq "is") {
105                 $reply = &getRandom(keys %{ $lang{'factoid'} });
106                 $reply =~ s/##KEY/$lhs/;
107                 $reply =~ s/##VALUE/$result/;
108             } else {
109                 $reply = "$lhs $mhs $result";
110             }
111
112             if ($reply =~ s/^\Q$who\E is/you are/i) {
113                 # fix the person.
114             } else {
115                 if ($reply =~ /^you are / or $reply =~ / you are /) {
116                     return if ($addressed);
117                 }
118             }
119         }
120     }
121
122     return $reply if ($literal);
123
124     # remove excessive beginning and end whitespaces.
125     $reply      =~ s/^\s+|\s+$//g;
126
127     if ($reply =~ /^\s+$/) {
128         &DEBUG("Reply: Null factoid ($message)");
129         return '';
130     }
131
132     return $reply unless ($reply =~ /\$/);
133
134     ###
135     ### $ SUBSTITUTION.
136     ###
137
138     # don't evaluate if it has factoid arguments.
139     if ($message =~ /^CMD:/i) {
140         &status("Reply: not doing substVars (eval dollar vars)");
141     } else {
142         $reply = &substVars($reply,1);
143     }
144
145     $reply;
146 }
147
148 sub smart_replace {
149     my ($string) = @_;
150     my ($l,$r)  = (0,0);        # l = left,  r = right.
151     my ($s,$t)  = (0,0);        # s = start, t = marker.
152     my $i       = 0;
153     my $old     = $string;
154     my @rand;
155
156     foreach (split //, $string) {
157
158         if ($_ eq "(") {
159 ###         print "( l=>$l, r=>$r\n";
160
161             if (!$l and !$r) {
162 #               print "STARTING at $i\n";
163                 $s = $i;
164                 $t = $i;
165             }
166
167             $l++;
168             $r--;
169         }
170
171         if ($_ eq ")") {
172 ###         print ") l=>$l, r=>$r\n";
173
174             $r++;
175             $l--;
176
177             if (!$l and !$r) {
178                 my $substr = substr($old,$s,$i-$s+1);
179 #               print "STOP at $i $substr\n";
180                 push(@rand, substr($old,$t+1,$i-$t-1) );
181
182                 my $rand = $rand[rand @rand];
183                 &status("SARing '$substr' to '$rand'.");
184                 $string =~ s/\Q$substr\E/$rand/;
185                 undef @rand;
186             }
187         }
188
189         if ($_ eq "|" and $l+$r== 0 and $l==1) {
190 #           print "| at $i (l=>$l,r=>$r)\n";
191             push(@rand, substr($old,$t+1,$i-$t-1) );
192             $t = $i;
193         }
194
195         $i++;
196     }
197
198     if ($old eq $string) {
199         &WARN("smart_replace: no subst made. (string => $string)");
200     }
201
202     return $string;
203 }
204
205 sub SARit {
206     my($txt) = @_;
207     my $done = 0;
208
209     # (blah1|blah2)?
210     while ($txt =~ /\((.*?)\)\?/) {
211         my $str = $1;
212         if (rand() > 0.5) {             # fix.
213             &status("Factoid transform: keeping '$str'.");
214             $txt =~ s/\(\Q$str\E\)\?/$str/;
215         } else {                        # remove
216             &status("Factoid transform: removing '$str'.");
217             $txt =~ s/\(\Q$str\E\)\?\s?//;
218         }
219         $done++;
220         last if ($done >= 10);  # just in case.
221     }
222     $done = 0;
223
224     # EG: (0-32768) => 6325
225     ### TODO: (1-10,20-30,40) => 24
226     while ($txt =~ /\((\d+)-(\d+)\)/) {
227         my ($lower,$upper) = ($1,$2);
228         my $new = int(rand $upper-$lower) + $lower;
229
230         &status("SARing '$&' to '$new' (2).");
231         $txt =~ s/$&/$new/;
232         $done++;
233         last if ($done >= 10);  # just in case.
234     }
235     $done = 0;
236
237     # EG: (blah1|blah2|blah3|) => blah1
238     while ($txt =~ /.*\((.*\|.*?)\).*/) {
239         $txt = &smart_replace($txt);
240
241         $done++;
242         last if ($done >= 10);  # just in case.
243     }
244     &status("Reply.pl: $done SARs done.") if ($done);
245
246     return $txt;
247 }
248
249 sub substVars {
250     my($reply,$flag) = @_;
251
252     # $date, $time.
253     # todo: support localtime.
254     my $date    =  scalar(gmtime());
255     $date       =~ s/\:\d+(\s+\w+)\s+\d+$/$1/;
256     $reply      =~ s/\$date/$date/gi;
257     $date       =~ s/\w+\s+\w+\s+\d+\s+//;
258     $reply      =~ s/\$time/$date/gi;
259
260     # dollar variables.
261     if ($flag) {
262         $reply  =~ s/\$nick/$who/g;
263         $reply  =~ s/\$who/$who/g;      # backward compat.
264     }
265
266     if ($reply =~ /\$(user(name)?|host)/) {
267         my ($username, $hostname) = split /\@/, $uh;
268         $reply  =~ s/\$user(name)?/$username/g;
269         $reply  =~ s/\$host(name)?/$hostname/g;
270     }
271     $reply      =~ s/\$chan(nel)?/$talkchannel/g;
272     if ($msgType =~ /public/) {
273         $reply  =~ s/\$lastspeaker/$lastWho{$talkchannel}/g;
274     } else {
275         $reply  =~ s/\$lastspeaker/$lastWho/g;
276     }
277
278     if ($reply =~ /\$rand/) {
279         my $rand  = rand();
280
281         # $randnick.
282         if ($reply =~ /\$randnick/) {
283             my @nicks = keys %{ $channels{$chan}{''} };
284             my $randnick = $nicks[ int($rand*$#nicks) ];
285             $reply =~ s/\$randnick/$randnick/g;
286         }
287
288         # eg: $rand100.3
289         if ($reply =~ /\$rand(\d+)(\.(\d+))?/) {
290             my $max = $1;
291             my $dot = $3 || 0;
292             my $orig = $&;
293             #&DEBUG("dot => $dot, max => $max, rand=>$rand");
294             $rand = sprintf("%.*f", $dot, $rand*$max);
295
296             &DEBUG("swapping $orig to $rand");
297             $reply =~ s/\Q$orig\E/$rand/eg;
298         } else {
299             $reply =~ s/\$rand/$rand/g;
300         }
301     }
302
303     $reply      =~ s/\$ident/$ident/g;
304
305     if ($reply =~ /\$startTime/) {
306         my $time = scalar(gmtime $^T);
307         $reply =~ s/\$startTime/$time/;
308     }
309
310     if ($reply =~ /\$uptime/) {
311         my $uptime = &Time2String(time() - $^T);
312         $reply =~ s/\$uptime/$uptime/;
313     }
314
315     if ($reply =~ /\$factoids/) {
316         my $factoids = &countKeys("factoids");
317         $reply =~ s/\$factoids/$factoids/;
318     }
319
320     if ($reply =~ /\$Fupdate/) {
321         my $x = "\002$count{'Update'}\002 ".
322                 &fixPlural("modification", $count{'Update'});
323         $reply =~ s/\$Fupdate/$x/;
324     }
325
326     if ($reply =~ /\$Fquestion/) {
327         my $x = "\002$count{'Question'}\002 ".
328                 &fixPlural("question", $count{'Question'});
329         $reply =~ s/\$Fquestion/$x/;
330     }
331
332     if ($reply =~ /\$Fdunno/) {
333         my $x = "\002$count{'Dunno'}\002 ".
334                 &fixPlural("dunno", $count{'Dunno'});
335         $reply =~ s/\$Fdunno/$x/;
336     }
337
338     $reply      =~ s/\$memusage/$memusage/;
339
340     return $reply;
341 }
342
343 1;