]> git.donarmstrong.com Git - infobot.git/blob - src/Process.pl
warn on pmsg karma - raven24++
[infobot.git] / src / Process.pl
1 ###
2 ### Process.pl: Kevin Lenzo 1997-1999
3 ###
4
5 #
6 # process the incoming message
7 #
8
9 use strict;
10
11 use vars qw($who $msgType $addressed $message $ident $user $host $chan
12   $learnok $talkok $force_public_reply $noreply $addrchar
13   $literal $addressedother $userHandle $lobotomized);
14 use vars qw(%channels %users %param %cache %chanconf %mask %orig %lang);
15
16 sub process {
17     $learnok            = 0;    # Able to learn?
18     $talkok             = 0;    # Able to yap?
19     $force_public_reply = 0;
20     $literal            = 0;
21
22     return 'X' if $who eq $ident;    # self-message.
23     return 'addressedother set' if ($addressedother);
24
25     $talkok = ( $param{'addressing'} =~ /^OPTIONAL$/i or $addressed );
26     $learnok = 1 if ($addressed);
27     if ( $param{'learn'} =~ /^HUNGRY$/i ) {
28         $learnok  = 1;
29         #FIXME: why can we talk if we just want to learn?
30         #$addrchar = 1;
31         #$talkok   = 1;
32     }
33
34     &shmFlush();                     # hack.
35
36     # hack to support channel +o as '+o' in bot user file.
37     # requires +O in user file.
38     # is $who arg lowercase?
39     if ( exists $channels{$chan}{o}{ $orig{who} } && &IsFlag('O') eq 'O' ) {
40         &status("Gave $who/$chan +o (+O)\'ness");
41         $users{$userHandle}{FLAGS} .= 'o';
42     }
43
44     # check if we have our head intact.
45     if ($lobotomized) {
46         if ( $addressed and IsFlag('o') eq 'o' ) {
47             my $delta_time = time() - ( $cache{lobotomy}{$who} || 0 );
48             &msg( $who, 'give me an unlobotomy.' ) if ( $delta_time > 60 * 60 );
49             $cache{lobotomy}{$who} = time();
50         }
51         return 'LOBOTOMY' unless IsFlag('A');
52     }
53
54     # talkMethod.
55     if ( $param{'talkMethod'} =~ /^PRIVATE$/i ) {
56         if ( $msgType =~ /public/ and $addressed ) {
57             &msg( $who,
58                     "sorry. i'm in 'PRIVATE' talkMethod mode "
59                   . "while you sent a message to me ${msgType}ly." );
60
61             return 'TALKMETHOD';
62         }
63     }
64
65     # join, must be done before outsider checking.
66     if ( $message =~ /^join(\s+(.*))?\s*$/i ) {
67         return 'join: not addr' unless ($addressed);
68
69         $2 =~ /^($mask{chan})(\s+(\S+))?/;
70         my ( $joinchan, $key ) = ( lc $1, $3 );
71
72         if ( $joinchan eq '' ) {
73             &help('join');
74             return;
75         }
76
77         if ( $joinchan !~ /^$mask{chan}$/ ) {
78             &msg( $who, "$joinchan is not a valid channel name." );
79             return;
80         }
81
82         if ( &IsFlag('o') ne 'o' ) {
83             if ( !exists $chanconf{$joinchan} ) {
84                 &msg( $who, "I am not allowed to join $joinchan." );
85                 return;
86             }
87
88             if ( &validChan($joinchan) ) {
89                 &msg( $who,
90                     "warn: I'm already on $joinchan, joining anyway..." );
91             }
92         }
93         $cache{join}{$joinchan} = $who;    # used for on_join self.
94
95         &status("JOIN $joinchan $key <$who>");
96         &msg( $who, "joining $joinchan $key" );
97         &joinchan( $joinchan, $key );
98         &joinNextChan();                   # hack.
99
100         return;
101     }
102
103     # 'identify'
104     if ( $msgType =~ /private/ and $message =~ s/^identify//i ) {
105         $message =~ s/^\s+|\s+$//g;
106         my @array = split / /, $message;
107
108         if ( $who =~ /^_default$/i ) {
109             &performStrictReply('you are too eleet.');
110             return;
111         }
112
113         if ( !scalar @array or scalar @array > 2 ) {
114             &help('identify');
115             return;
116         }
117
118         my $do_nick = $array[1] || $who;
119
120         if ( !exists $users{$do_nick} ) {
121             &performStrictReply("nick $do_nick is not in user list.");
122             return;
123         }
124
125         my $crypt = $users{$do_nick}{PASS};
126         if ( !defined $crypt ) {
127             &performStrictReply("user $do_nick has no passwd set.");
128             return;
129         }
130
131         if ( !&ckpasswd( $array[0], $crypt ) ) {
132             &performStrictReply("invalid passwd for $do_nick.");
133             return;
134         }
135
136         my $mask = "$who!$user@" . &makeHostMask($host);
137         ### TODO: prevent adding multiple dupe masks?
138         ### TODO: make &addHostMask() CMD?
139         &performStrictReply("Added $mask for $do_nick...");
140         $users{$do_nick}{HOSTS}{$mask} = 1;
141
142         return;
143     }
144
145     # 'pass'
146     if ( $msgType =~ /private/ and $message =~ s/^pass//i ) {
147         $message =~ s/^\s+|\s+$//g;
148         my @array = split ' ', $message;
149
150         if ( $who =~ /^_default$/i ) {
151             &performStrictReply('you are too eleet.');
152             return;
153         }
154
155         if ( scalar @array != 1 ) {
156             &help('pass');
157             return;
158         }
159
160         # TODO: use &getUser()?
161         my $first = 1;
162         foreach ( keys %users ) {
163             if ( $users{$_}{FLAGS} =~ /n/ ) {
164                 $first = 0;
165                 last;
166             }
167         }
168
169         if ( !exists $users{$who} and !$first ) {
170             &performStrictReply("nick $who is not in user list.");
171             return;
172         }
173
174         if ($first) {
175             &performStrictReply('First time user... adding you as Master.');
176             $users{$who}{FLAGS} = 'aemnorst';
177         }
178
179         my $crypt = $users{$who}{PASS};
180         if ( defined $crypt ) {
181             &performStrictReply("user $who already has pass set.");
182             return;
183         }
184
185         if ( !defined $host ) {
186             &WARN('pass: host == NULL.');
187             return;
188         }
189
190         if ( !scalar keys %{ $users{$who}{HOSTS} } ) {
191             my $mask = "*!$user@" . &makeHostMask($host);
192             &performStrictReply("Added hostmask '\002$mask\002' to $who");
193             $users{$who}{HOSTS}{$mask} = 1;
194         }
195
196         $crypt = &mkcrypt( $array[0] );
197         $users{$who}{PASS} = $crypt;
198         &performStrictReply("new pass for $who, crypt $crypt.");
199
200         return;
201     }
202
203     # allowOutsiders.
204     if ( &IsParam('disallowOutsiders') and $msgType =~ /private/i and IsFlag('o') ne 'o' ) {
205         my $found = 0;
206
207         foreach ( keys %channels ) {
208
209             # don't test for $channel{_default} elsewhere !!!
210             next if ( /^\s*$/ || /^_?default$/ );
211             next unless ( &IsNickInChan( $who, $_ ) );
212
213             $found++;
214             last;
215         }
216
217         if ( !$found and scalar( keys %channels ) ) {
218             &status("OUTSIDER <$who> $message");
219             return 'OUTSIDER';
220         }
221     }
222
223     # override msgType.
224     if ( $msgType =~ /public/ and $message =~ s/^\+// ) {
225         &status("Process: '+' flag detected; changing reply to public");
226         $msgType = 'public';
227         $who     = $chan;      # major hack to fix &msg().
228         $force_public_reply++;
229
230         # notice is still NOTICE but to whole channel => good.
231     }
232
233     # User Processing, for all users.
234     if ($addressed) {
235         my $retval;
236         return 'SOMETHING parseCmdHook' if &parseCmdHook($message);
237
238         $retval = &userCommands();
239         return unless ( defined $retval );
240         return if ( $retval eq $noreply );
241     }
242
243     ###
244     # once useless messages have been parsed out, we match them.
245     ###
246
247     # confused? is this for infobot communications?
248     foreach ( keys %{ $lang{'confused'} } ) {
249         my $y = $_;
250
251         next unless ( $message =~ /^\Q$y\E\s*/ );
252         return 'CONFUSO';
253     }
254
255     # hello. [took me a while to fix this. -xk]
256     if ( $orig{message} =~
257 /^(\Q$ident\E\S?[:, ]\S?)?\s*(h(ello|i( there)?|owdy|ey|ola))( \Q$ident\E)?\s*$/i
258       )
259     {
260         return '' unless ($talkok);
261
262         # 'mynick: hi' or 'hi mynick' or 'hi'.
263         &status('somebody said hello');
264
265         # 50% chance of replying to a random greeting when not addressed
266         if ( !defined $5 and $addressed == 0 and rand() < 0.5 ) {
267             &status('not returning unaddressed greeting');
268             return;
269         }
270
271         # customized random message.
272         my $tmp = ( rand() < 0.5 ) ? ", $who" : '';
273         &performStrictReply( &getRandom( keys %{ $lang{'hello'} } ) . $tmp );
274         return;
275     }
276
277     # greetings.
278     if ( $message =~ /how (the hell )?are (ya|you)( doin\'?g?)?\?*$/ && $talkok ) {
279
280         &performReply( &getRandom( keys %{ $lang{'howareyou'} } ) );
281         return;
282     }
283
284     # praise.
285     if (   $message =~ /you (rock|rewl|rule|are so+ coo+l)/
286         || $message =~ /(good (bo(t|y)|g([ui]|r+)rl))|(bot( |\-)?snack)/i )
287     {
288         return 'praise: no addr' unless ($addressed);
289
290         &performReply( &getRandom( keys %{ $lang{'praise'} } ) );
291         return;
292     }
293
294     # thanks.
295     if ( $message =~ /^than(ks?|x)( you)?( \S+)?/i ) {
296         return 'thank: no addr' unless ( $message =~ /$ident/ or $talkok );
297
298         &performReply( &getRandom( keys %{ $lang{'welcome'} } ) );
299         return;
300     }
301
302     ###
303     ### bot commands...
304     ###
305
306     # karma. set...
307     if (   $message =~ /^(\S+)(--|\+\+)\s*$/
308         && $addressed
309         && &IsChanConfOrWarn('karma') )
310     {
311
312         # for factoids such as 'g++' or 'libstdc++', append '?' to query.
313         my ( $term, $inc ) = ( lc $1, $2 );
314
315         if( !( $msgType =~ /public/i ) ) {
316             &msg( $who, "please use karma in a channel only");
317             return;
318         }
319
320         if ( lc $term eq lc $who ) {
321             &msg( $who, "please don't karma yourself" );
322             return;
323         }
324
325         my $karma =
326           &sqlSelect( 'stats', 'counter', { nick => $term, type => 'karma' } )
327           || 0;
328         if ( $inc eq '++' ) {
329             $karma++;
330         }
331         else {
332             $karma--;
333         }
334
335         &sqlSet(
336             'stats',
337             { 'nick' => $term, type => 'karma', channel => 'PRIVATE' },
338             {
339                 'time'  => time(),
340                 counter => $karma,
341             }
342         );
343
344         return;
345     }
346
347     # here's where the external routines get called.
348     # if they return anything but null, that's the 'answer'.
349     if ($addressed) {
350         my $er = &Modules();
351         if ( !defined $er ) {
352             return 'SOMETHING 1';
353         }
354
355         # allow administration of bot via messages (default is DCC CHAT only)
356         if ( &IsFlag('A') ) {
357             # UserDCC.pl should autoload now from IRC/. Remove if desired
358             #&loadMyModule('UserDCC');
359             $er = &userDCC();
360             if ( !defined $er ) {
361                 return 'SOMETHING 2';
362             }
363         }
364
365         if ( 0 and $addrchar ) {
366             &msg( $who,
367 "I don't trust people to use the core commands while addressing me in a short-cut way."
368             );
369             return;
370         }
371     }
372
373     if (    &IsParam('factoids')
374         and $param{'DBType'} =~ /^(mysql|sqlite(2)?|pgsql)$/i )
375     {
376         &FactoidStuff();
377     }
378     elsif ( $param{'DBType'} =~ /^none$/i ) {
379         return 'NO FACTOIDS.';
380     }
381     else {
382         &ERROR("INVALID FACTOID SUPPORT? ($param{'DBType'})");
383         &shutdown();
384         exit 0;
385     }
386 }
387
388 1;
389
390 # vim:ts=4:sw=4:expandtab:tw=80