]> git.donarmstrong.com Git - infobot.git/blob - src/Process.pl
A can unlobotomize
[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         $addressed      = 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+))?/;
69         my($thischan, $key) = (lc $1, $3);
70         my $chankey     = lc $thischan;
71         $chankey        .= " $key"      if (defined $key);
72
73         if ($thischan eq "") {
74             &help("join");
75             return;
76         }
77
78         if ($thischan !~ /^$mask{chan}$/) {
79             &msg($who, "$thischan is not a valid channel name.");
80             return;
81         }
82
83         if (&IsFlag("o") ne "o") {
84             if (!exists $chanconf{$thischan}) {
85                 &msg($who, "I am not allowed to join $thischan.");
86                 return;
87             }
88
89             if (&validChan($thischan)) {
90                 &msg($who,"warn: I'm already on $thischan, joining anyway...");
91             }
92         }
93         $cache{join}{$thischan} = $who; # used for on_join self.
94
95         &joinchan($chankey);
96         &status("JOIN $chankey <$who>");
97         &msg($who, "joining $chankey");
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             &pSReply("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             &pSReply("nick $do_nick is not in user list.");
122             return;
123         }
124
125         my $crypt = $users{$do_nick}{PASS};
126         if (!defined $crypt) {
127             &pSReply("user $do_nick has no passwd set.");
128             return;
129         }
130
131         if (!&ckpasswd($array[0], $crypt)) {
132             &pSReply("invalid passwd for $do_nick.");
133             return;
134         }
135
136         my $mask = "*!$user@".&makeHostMask($host);
137         ### TODO: prevent adding multiple dupe masks?
138         ### TODO: make &addHostMask() CMD?
139         &pSReply("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             &pSReply("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             &pSReply("nick $who is not in user list.");
171             return;
172         }
173
174         if ($first) {
175             &pSReply("First time user... adding you as Master.");
176             $users{$who}{FLAGS} = "mrsteon";
177         }
178
179         my $crypt = $users{$who}{PASS};
180         if (defined $crypt) {
181             &pSReply("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             &pSReply("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         &pSReply("new pass for $who, crypt $crypt.");
199
200         return;
201     }
202
203     # allowOutsiders.
204     if (&IsParam("disallowOutsiders") and $msgType =~ /private/i) {
205         my $found = 0;
206
207         foreach (keys %channels) {
208             # don't test for $channel{_default} elsewhere !!!
209             next if (/^\s*$/ || /^_?default$/);
210             next unless (&IsNickInChan($who,$_));
211
212             $found++;
213             last;
214         }
215
216         if (!$found and scalar(keys %channels)) {
217             &status("OUTSIDER <$who> $message");
218             return 'OUTSIDER';
219         }
220     }
221
222     # override msgType.
223     if ($msgType =~ /public/ and $message =~ s/^\+//) {
224         &status("Process: '+' flag detected; changing reply to public");
225         $msgType = 'public';
226         $who     = $chan;       # major hack to fix &msg().
227         $force_public_reply++;
228         # notice is still NOTICE but to whole channel => good.
229     }
230
231     # User Processing, for all users.
232     if ($addressed) {
233         my $retval;
234         return 'returned from pCH'   if &parseCmdHook("main",$message);
235
236         $retval = &userCommands();
237         return unless (defined $retval);
238         return if ($retval eq $noreply);
239     }
240
241     ###
242     # once useless messages have been parsed out, we match them.
243     ###
244
245     # confused? is this for infobot communications?
246     foreach (keys %{ $lang{'confused'} }) {
247         my $y = $_;
248
249         next unless ($message =~ /^\Q$y\E\s*/);
250         return 'CONFUSO';
251     }
252
253     # hello. [took me a while to fix this. -xk]
254     if ($orig{message} =~ /^(\Q$ident\E\S?[:, ]\S?)?\s*(h(ello|i( there)?|owdy|ey|ola))( \Q$ident\E)?\s*$/i) {
255         return '' unless ($talkok);
256
257         # 'mynick: hi' or 'hi mynick' or 'hi'.
258         &status("somebody said hello");
259
260         # 50% chance of replying to a random greeting when not addressed
261         if (!defined $5 and $addressed == 0 and rand() < 0.5) {
262             &status("not returning unaddressed greeting");
263             return;
264         }
265
266         # customized random message.
267         my $tmp = (rand() < 0.5) ? ", $who" : "";
268         &pSReply( &getRandom(keys %{ $lang{'hello'} }) . $tmp );
269         return;
270     }
271
272     # greetings.
273     if ($message =~ /how (the hell )?are (ya|you)( doin\'?g?)?\?*$/) {
274
275         &performReply(&getRandom(keys %{ $lang{'howareyou'} }));
276         return;
277     }
278
279     # praise.
280     if ($message =~ /you (rock|rewl|rule|are so+ coo+l)/ ||
281         $message =~ /(good (bo(t|y)|g([ui]|r+)rl))|(bot( |\-)?snack)/i)
282     {
283         return 'praise: no addr' unless ($addressed);
284
285         &performReply(&getRandom(keys %{ $lang{'praise'} }));
286         return;
287     }
288
289     # thanks.
290     if ($message =~ /^than(ks?|x)( you)?( \S+)?/i) {
291         return 'thank: no addr' unless ($message =~ /$ident/ or $talkok);
292
293         &performReply( &getRandom(keys %{ $lang{'welcome'} }) );
294         return;
295     }
296
297     ###
298     ### bot commands...
299     ###
300
301     # karma. set...
302     if ($msgType =~ /public/i && $message =~ /^(\S+)(--|\+\+)\s*$/ &&
303         $addressed && &hasParam("karma")
304     ) {
305         # to request factoids such as "g++" or "libstdc++", append "?" to the query.
306         my ($term,$inc) = (lc $1,$2);
307
308         if (lc $term eq lc $who) {
309             &msg($who, "please don't karma yourself");
310             return;
311         }
312
313         my $karma = &sqlSelect("stats", "counter",
314                 { nick => $term, type => "karma" }) || 0;
315         if ($inc eq '++') {
316             $karma++;
317         } else {
318             $karma--;
319         }
320
321         &sqlReplace("stats", {
322             nick        => $term,
323             type        => "karma",
324             'time'      => time(),
325             counter     => $karma,
326         } );
327
328         return;
329     }
330
331     # here's where the external routines get called.
332     # if they return anything but null, that's the "answer".
333     if ($addressed) {
334         if ( &parseCmdHook("extra",$message) ) {
335             return 'DID SOMETHING IN PCH.';
336         }
337
338         my $er = &Modules();
339         if (!defined $er) {
340             return 'SOMETHING 1';
341         }
342
343         # allow administration of bot via messages (default is DCC CHAT only)
344         if (&IsFlag("A")) {
345             &loadMyModule( $myModules{'ircdcc'} );
346             $er = &userDCC();
347             if (!defined $er) {
348                 return 'SOMETHING 2';
349             }
350         }
351
352         if (0 and $addrchar) {
353             &msg($who, "I don't trust people to use the core commands while addressing me in a short-cut way.");
354             return;
355         }
356     }
357
358     if (&IsParam("factoids") and $param{'DBType'} =~ /^(mysql|sqlite|pgsql)/i) {
359         &FactoidStuff();
360     } elsif ($param{'DBType'} =~ /^none$/i) {
361         return "NO FACTOIDS.";
362     } else {
363         &ERROR("INVALID FACTOID SUPPORT? ($param{'DBType'})");
364         &shutdown();
365         exit 0;
366     }
367 }
368
369 1;