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