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