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