]> git.donarmstrong.com Git - infobot.git/blob - src/Factoids/Update.pl
3eb70fb5855f9202018a76ac6db899d6515b9e66
[infobot.git] / src / Factoids / Update.pl
1 #
2 # Update.pl: Add or modify factoids in the db.
3 #    Author: Kevin Lenzo
4 #            dms
5 #   Version: 19991209
6 #   Created: 1997
7 #
8
9 # use strict;   # TODO
10
11 use Encode qw(decode_utf8 encode_utf8);
12
13 sub update {
14     my ( $lhs, $mhs, $rhs ) = @_;
15
16     my $lhs_utf8 = decode_utf8($lhs);
17     my $rhs_utf8 = decode_utf8($rhs_utf8);
18
19     $lhs_utf8 =~ s/^i (heard|think) //i;
20     $lhs_utf8 =~ s/^some(one|1|body) said //i;
21     $lhs_utf8 =~ s/\s+/ /g;
22
23     for my $temp ($lhs_utf8,$rhs_utf8 ) {
24         if ($temp =~ /([^[:print:]])/ or $temp =~ /(\N{U+FFFD})/) {
25             &status("statement: illegal character '$1' ".ord($1).".");
26             &performAddressedReply(
27                  "i'm not going to learn illegal characters");
28             return;
29         }
30     }
31     # update rhs and lhs
32     $rhs = encode_utf8($rhs_utf8);
33     $lhs = encode_utf8($lhs_utf8);
34
35     # locked.
36     return if ( &IsLocked($lhs) == 1 );
37
38     # profanity.
39     if ( &IsParam('profanityCheck') and &hasProfanity($rhs_utf8) ) {
40         &performReply("please, watch your language.");
41         return 1;
42     }
43
44     # teaching.
45     if ( &IsFlag('t') ne 't' && &IsFlag('o') ne 'o' ) {
46         &msg( $who, "permission denied." );
47         &status("alert: $who wanted to teach me.");
48         return 1;
49     }
50
51     # invalid verb.
52     if ( $mhs !~ /^(is|are)$/i ) {
53         &ERROR("UNKNOWN verb: $mhs.");
54         return;
55     }
56
57     # check if the arguments are too long to be stored in our table.
58     my $toolong = 0;
59     $toolong++ if ( length $lhs > $param{'maxKeySize'} );
60     $toolong++ if ( length $rhs > $param{'maxDataSize'} );
61     if ($toolong) {
62         &performAddressedReply("that's too long");
63         return 1;
64     }
65
66     # also checking.
67     my $also = ( $rhs_utf8 =~ s/^-?also //i );
68     my $also_or = ( $also and $rhs_utf8 =~ s/\s+(or|\|\|)\s+// );
69     # update rhs and lhs
70     $rhs = encode_utf8($rhs_utf8);
71     $lhs = encode_utf8($lhs_utf8);
72
73     if ( $also or $also_or ) {
74         my $author = &getFactInfo( $from, 'created_by' );
75         $author =~ /^(.*)!/;
76         my $created_by = $1;
77
78         # Can they even modify factoids?
79         if (    &IsFlag('m') ne 'm'
80             and &IsFlag('M') ne 'M'
81             and &IsFlag('o') ne 'o' )
82         {
83             &performReply("You do not have permission to modify factoids");
84             return 1;
85
86             # If they have +M but they didnt create the factoid
87         }
88         elsif ( &IsFlag('M') eq 'M'
89             and $who !~ /^\Q$created_by\E$/i
90             and &IsFlag('m') ne 'm'
91             and &IsFlag('o') ne 'o' )
92         {
93             &performReply("factoid '$lhs' is not yours to modify.");
94             return 1;
95         }
96     }
97
98     # factoid arguments handler.
99     # must start with a non-variable
100     if ( &IsChanConf('factoidArguments') > 0 and $lhs_utf8 =~ /^[^\$]+.*\$/ ) {
101         &status("Update: Factoid Arguments found.");
102         &status("Update: orig lhs => '$lhs'.");
103         &status("Update: orig rhs => '$rhs'.");
104
105         my @list;
106         my $count = 0;
107         $lhs_utf8 =~ s/^/cmd: /;
108         while ( $lhs_utf8 =~ s/\$(\S+)/(.*?)/ ) {
109             push( @list, "\$$1" );
110             $count++;
111             last if ( $count >= 10 );
112         }
113
114         if ( $count >= 10 ) {
115             &msg( $who, "error: could not SAR properly." );
116             &DEBUG("error: lhs => '$lhs' rhs => '$rhs'.");
117             return;
118         }
119
120         my $z = join( ',', @list );
121         $rhs_utf8 =~ s/^/($z): /;
122         # update rhs and lhs
123         $rhs = encode_utf8($rhs_utf8);
124         $lhs = encode_utf8($lhs_utf8);
125
126         &status("Update: new lhs => '$lhs' rhs => '$rhs'.");
127     }
128
129     # the fun begins.
130     my $exists = &getFactoid($lhs);
131     my $exists_utf8 = decode_utf8($exists);
132
133     if ( !$exists ) {
134
135         # nice 'are' hack (or work-around).
136         if ( $mhs =~ /^are$/i and $rhs_utf8 !~ /<\S+>/ ) {
137             &status("Update: 'are' hack detected.");
138             $mhs = 'is';
139             $rhs_utf8 = "<REPLY> are " . $rhs_utf8;
140         }
141         # update rhs and lhs
142         $rhs = encode_utf8($rhs_utf8);
143         $lhs = encode_utf8($lhs_utf8);
144
145         &status("enter: <$who> \'$lhs\' =$mhs=> \'$rhs\'");
146         $count{'Update'}++;
147
148         &performAddressedReply('okay');
149
150         &sqlInsert(
151             'factoids',
152             {
153                 created_by    => $nuh,
154                 created_time  => time(),    # modified time.
155                 factoid_key   => $lhs,
156                 factoid_value => $rhs,
157             }
158         );
159
160         if ( !defined $rhs or $rhs eq '' ) {
161             &ERROR("Update: rhs1 == NULL.");
162         }
163
164         return 1;
165     }
166
167     # factoid exists.
168     if ( $exists eq $rhs ) {
169
170         # this catches the following situation: (right or wrong?)
171         #    "test is test"
172         #    "test is also test"
173         &performAddressedReply("i already had it that way");
174         return 1;
175     }
176
177     if ($also) {    # 'is also'.
178         my $redircount = 5;
179         my $origlhs    = $lhs;
180         my $origlhs_utf8 = $lhs_utf8;
181         while ( $exists_utf8 =~ /^<REPLY> ?see (.*)/i ) {
182             $redircount--;
183             unless ($redircount) {
184                 &msg( $who, "$origlhs has too many levels of redirection." );
185                 return 1;
186             }
187
188             $lhs    = $1;
189             $exists = &getFactoid($lhs);
190             unless ($exists) {
191                 &msg( $who, "$1 is a dangling redirection." );
192                 return 1;
193             }
194             $exists_utf8 = decode_utf8($exists);
195         }
196
197         if ($also_or) {    # 'is also ||'.
198             $rhs_utf8 = $exists . ' || ' . $rhs_utf8;
199             $rhs = encode_utf8($rhs_utf8);
200             $lhs = encode_utf8($lhs_utf8);
201         }
202         else {
203
204             #       if ($exists =~ s/\,\s*$/,  /) {
205             if ( $exists_utf8 =~ /\,\s*$/ ) {
206                 &DEBUG("current has trailing comma, just append as is");
207                 &DEBUG("Up: exists => $exists");
208                 &DEBUG("Up: rhs    => $rhs");
209
210                 # $rhs =~ s/^\s+//;
211                 # $rhs = $exists." ".$rhs;      # keep comma.
212             }
213
214             if ( $exists_utf8 =~ /\.\s*$/ ) {
215                 &DEBUG(
216                     "current has trailing period, just append as is with 2 WS");
217                 &DEBUG("Up: exists => $exists");
218                 &DEBUG("Up: rhs    => $rhs");
219
220                 # $rhs =~ s/^\s+//;
221                 # use ucfirst();?
222                 # $rhs = $exists."  ".$rhs;     # keep comma.
223             }
224
225             if ( $rhs_utf8 =~ /^[A-Z]/ ) {
226                 if ( $rhs_utf8 =~ /\w+\s*$/ ) {
227                     &status("auto insert period to factoid.");
228                     $rhs_utf8 = $exists_utf8 . ". " . $rhs_utf8;
229                 }
230                 else {    # '?' or '.' assumed at end.
231                     &status(
232 "orig factoid already had trailing symbol; not adding period."
233                     );
234                     $rhs_utf8 = $exists_utf8 . " " . $rhs_utf8;
235                 }
236             }
237             elsif ( $exists =~ /[\,\.\-]\s*$/ ) {
238                 &VERB(
239 "U: current has trailing symbols; inserting whitespace + new.",
240                     2
241                 );
242                 $rhs_utf8 = $exists_utf8 . " " . $rhs_utf8;
243             }
244             elsif ( $rhs_utf8 =~ /^\./ ) {
245                 &VERB( "U: new text starts with period; appending directly", 2 );
246                 $rhs_utf8 = $exists_utf8 . $rhs_utf8;
247             }
248             else {
249                 $rhs_utf8 = $exists_utf8 . ', or ' . $rhs_utf8;
250             }
251             $rhs = encode_utf8($rhs_utf8);
252         }
253
254         # max length check again.
255         if ( length $rhs > $param{'maxDataSize'} ) {
256             if ( length $rhs_utf8 > length $exists_utf8 ) {
257                 &performAddressedReply("that's too long");
258                 return 1;
259             }
260             else {
261                 &status(
262 "Update: new length is still longer than maxDataSize but less than before, we'll let it go."
263                 );
264             }
265         }
266         $rhs = encode_utf8($rhs_utf8);
267         $lhs = encode_utf8($lhs_utf8);
268         $exists = encode_utf8($exists_utf8);
269
270         &performAddressedReply('okay');
271
272         $count{'Update'}++;
273         &status("update: <$who> \'$lhs\' =$mhs=> \'$rhs\'; was \'$exists\'");
274         &sqlSet(
275             'factoids',
276             { 'factoid_key' => $lhs },
277             {
278                 modified_by   => $nuh,
279                 modified_time => time(),
280                 factoid_value => $rhs,
281             }
282         );
283
284         if ( !defined $rhs or $rhs eq '' ) {
285             &ERROR("Update: rhs1 == NULL.");
286         }
287     }
288     else {    # not 'also'
289
290         if ( !$correction_plausible ) {    # "no, blah is ..."
291             if ($addressed) {
292                 &performStrictReply(
293                     "...but \002$lhs\002 is already something else...");
294                 &status("FAILED update: <$who> \'$lhs\' =$mhs=> \'$rhs\'");
295             }
296             return 1;
297         }
298
299         my $author = &getFactInfo( $lhs, 'created_by' ) || '';
300
301         if (   IsFlag('m') ne 'm'
302             && IsFlag('o') ne 'o'
303             && $author !~ /^\Q$who\E\!/i )
304         {
305             &msg( $who, "you can't change that factoid." );
306             return 1;
307         }
308
309         &performAddressedReply('okay');
310
311         $count{'Update'}++;
312         &status("update: <$who> \'$lhs\' =$mhs=> \'$rhs\'; was \'$exists\'");
313
314         &sqlSet(
315             'factoids',
316             { 'factoid_key' => $lhs },
317             {
318                 modified_by   => $nuh,
319                 modified_time => time(),
320                 factoid_value => $rhs,
321             }
322         );
323
324         if ( !defined $rhs or $rhs eq '' ) {
325             &ERROR("Update: rhs1 == NULL.");
326         }
327     }
328
329     return 1;
330 }
331
332 1;
333
334 # vim:ts=4:sw=4:expandtab:tw=80