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