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