2 ### Process.pl: Kevin Lenzo 1997-1999
6 # process the incoming message
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);
17 $learnok = 0; # Able to learn?
18 $talkok = 0; # Able to yap?
19 $force_public_reply = 0;
22 return 'X' if $who eq $ident; # self-message.
23 return 'addressedother set' if ($addressedother);
25 $talkok = ( $param{'addressing'} =~ /^OPTIONAL$/i or $addressed );
26 $learnok = 1 if ($addressed);
27 if ( $param{'learn'} =~ /^HUNGRY$/i ) {
29 #FIXME: why can we talk if we just want to learn?
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';
44 # check if we have our head intact.
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();
51 return 'LOBOTOMY' unless IsFlag('A');
55 if ( $param{'talkMethod'} =~ /^PRIVATE$/i ) {
56 if ( $msgType =~ /public/ and $addressed ) {
58 "sorry. i'm in 'PRIVATE' talkMethod mode "
59 . "while you sent a message to me ${msgType}ly." );
65 # join, must be done before outsider checking.
66 if ( $message =~ /^join(\s+(.*))?\s*$/i ) {
67 return 'join: not addr' unless ($addressed);
69 $2 =~ /^($mask{chan})(\s+(\S+))?/;
70 my ( $joinchan, $key ) = ( lc $1, $3 );
72 if ( $joinchan eq '' ) {
77 if ( $joinchan !~ /^$mask{chan}$/ ) {
78 &msg( $who, "$joinchan is not a valid channel name." );
82 if ( &IsFlag('o') ne 'o' ) {
83 if ( !exists $chanconf{$joinchan} ) {
84 &msg( $who, "I am not allowed to join $joinchan." );
88 if ( &validChan($joinchan) ) {
90 "warn: I'm already on $joinchan, joining anyway..." );
93 $cache{join}{$joinchan} = $who; # used for on_join self.
95 &status("JOIN $joinchan $key <$who>");
96 &msg( $who, "joining $joinchan $key" );
97 &joinchan( $joinchan, $key );
98 &joinNextChan(); # hack.
104 if ( $msgType =~ /private/ and $message =~ s/^identify//i ) {
105 $message =~ s/^\s+|\s+$//g;
106 my @array = split / /, $message;
108 if ( $who =~ /^_default$/i ) {
109 &performStrictReply('you are too eleet.');
113 if ( !scalar @array or scalar @array > 2 ) {
118 my $do_nick = $array[1] || $who;
120 if ( !exists $users{$do_nick} ) {
121 &performStrictReply("nick $do_nick is not in user list.");
125 my $crypt = $users{$do_nick}{PASS};
126 if ( !defined $crypt ) {
127 &performStrictReply("user $do_nick has no passwd set.");
131 if ( !&ckpasswd( $array[0], $crypt ) ) {
132 &performStrictReply("invalid passwd for $do_nick.");
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;
146 if ( $msgType =~ /private/ and $message =~ s/^pass//i ) {
147 $message =~ s/^\s+|\s+$//g;
148 my @array = split ' ', $message;
150 if ( $who =~ /^_default$/i ) {
151 &performStrictReply('you are too eleet.');
155 if ( scalar @array != 1 ) {
160 # TODO: use &getUser()?
162 foreach ( keys %users ) {
163 if ( $users{$_}{FLAGS} =~ /n/ ) {
169 if ( !exists $users{$who} and !$first ) {
170 &performStrictReply("nick $who is not in user list.");
175 &performStrictReply('First time user... adding you as Master.');
176 $users{$who}{FLAGS} = 'aemnorst';
179 my $crypt = $users{$who}{PASS};
180 if ( defined $crypt ) {
181 &performStrictReply("user $who already has pass set.");
185 if ( !defined $host ) {
186 &WARN('pass: host == NULL.');
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;
196 $crypt = &mkcrypt( $array[0] );
197 $users{$who}{PASS} = $crypt;
198 &performStrictReply("new pass for $who, crypt $crypt.");
204 if ( &IsParam('disallowOutsiders') and $msgType =~ /private/i and IsFlag('o') ne 'o' ) {
207 foreach ( keys %channels ) {
209 # don't test for $channel{_default} elsewhere !!!
210 next if ( /^\s*$/ || /^_?default$/ );
211 next unless ( &IsNickInChan( $who, $_ ) );
217 if ( !$found and scalar( keys %channels ) ) {
218 &status("OUTSIDER <$who> $message");
224 if ( $msgType =~ /public/ and $message =~ s/^\+// ) {
225 &status("Process: '+' flag detected; changing reply to public");
227 $who = $chan; # major hack to fix &msg().
228 $force_public_reply++;
230 # notice is still NOTICE but to whole channel => good.
233 # User Processing, for all users.
236 return 'SOMETHING parseCmdHook' if &parseCmdHook($message);
238 $retval = &userCommands();
239 return unless ( defined $retval );
240 return if ( $retval eq $noreply );
244 # once useless messages have been parsed out, we match them.
247 # confused? is this for infobot communications?
248 foreach ( keys %{ $lang{'confused'} } ) {
251 next unless ( $message =~ /^\Q$y\E\s*/ );
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
260 return '' unless ($talkok);
262 # 'mynick: hi' or 'hi mynick' or 'hi'.
263 &status('somebody said hello');
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');
271 # customized random message.
272 my $tmp = ( rand() < 0.5 ) ? ", $who" : '';
273 &performStrictReply( &getRandom( keys %{ $lang{'hello'} } ) . $tmp );
278 if ( $message =~ /how (the he(ck|ll) )?are (ya|you)( doin\'?g?)?\?*$/ && $talkok ) {
280 &performReply( &getRandom( keys %{ $lang{'howareyou'} } ) );
285 if ( $message =~ /you (rock|rewl|rule|are so+ coo+l)/
286 || $message =~ /(good (bo(t|y)|g([ui]|r+)rl))|(bot( |\-)?snack)/i )
288 return 'praise: no addr' unless ($addressed);
290 &performReply( &getRandom( keys %{ $lang{'praise'} } ) );
295 if ( $message =~ /^than(ks?|x)( you)?( \S+)?/i ) {
296 return 'thank: no addr' unless ( $message =~ /$ident/ or $talkok );
298 &performReply( &getRandom( keys %{ $lang{'welcome'} } ) );
307 if ( $message =~ /^(\S+)(--|\+\+)\s*$/
309 && &IsChanConfOrWarn('karma') )
312 # for factoids such as 'g++' or 'libstdc++', append '?' to query.
313 my ( $term, $inc ) = ( lc $1, $2 );
315 if( !( $msgType =~ /public/i ) ) {
316 &msg( $who, "please use karma in a channel only");
320 if ( lc $term eq lc $who ) {
321 &msg( $who, "please don't karma yourself" );
326 &sqlSelect( 'stats', 'counter', { nick => $term, type => 'karma' } )
328 if ( $inc eq '++' ) {
337 { 'nick' => $term, type => 'karma', channel => 'PRIVATE' },
347 # here's where the external routines get called.
348 # if they return anything but null, that's the 'answer'.
351 if ( !defined $er ) {
352 return 'SOMETHING 1';
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');
360 if ( !defined $er ) {
361 return 'SOMETHING 2';
365 if ( 0 and $addrchar ) {
367 "I don't trust people to use the core commands while addressing me in a short-cut way."
373 if ( &IsParam('factoids')
374 and $param{'DBType'} =~ /^(mysql|sqlite(2)?|pgsql)$/i )
378 elsif ( $param{'DBType'} =~ /^none$/i ) {
379 return 'NO FACTOIDS.';
382 &ERROR("INVALID FACTOID SUPPORT? ($param{'DBType'})");
390 # vim:ts=4:sw=4:expandtab:tw=80