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