2 # UserDCC.pl: User Commands, DCC CHAT.
4 # Version: v0.2 (20010119)
5 # Created: 20000707 (from UserExtra.pl)
10 use vars qw(%users %ignore %sched %bans %mask %cache %channels %param
12 use vars qw($who $chan $message $msgType $user $chnick $conn $ident
13 $verifyUser $ucount_userfile $utime_userfile $lobotomized
14 $utime_chanfile $ucount_chanfile);
15 use vars qw(@backlog);
24 if ( $message =~ /^(exit|quit)$/i ) {
26 # do ircII clients support remote close? if so, cool!
27 &FIXME("userDCC: quit called.");
29 &status("userDCC: after dcc_close!");
35 if ( $message =~ /^who$/ ) {
36 my $count = scalar( keys %{ $dcc{'CHAT'} } );
37 my $dccCHAT = $message;
39 &performStrictReply("Start of who ($count users).");
40 foreach ( keys %{ $dcc{'CHAT'} } ) {
41 &performStrictReply("=> $_");
43 &performStrictReply("End of who.");
48 ### for those users with enough flags.
50 if ( $message =~ /^tellme(\s+(.*))?$/i ) {
52 if ( $args =~ /^\s*$/ ) {
57 my $result = &doQuestion($args);
58 &performStrictReply($result);
64 if ( $message =~ /^4op(\s+($mask{chan}))?$/i ) {
65 return unless ( &hasFlag('o') );
74 if ( !$channels{$chan}{'o'}{$ident} ) {
75 &msg( $who, "i don't have ops on $chan to do that." );
79 # on non-4mode(<4) servers, this may be exploited.
80 if ( $channels{$chan}{'o'}{$who} ) {
81 rawout( "MODE $chan -o+o-o+o" . ( " $who" x 4 ) );
84 rawout( "MODE $chan +o-o+o-o" . ( " $who" x 4 ) );
91 if ( $message =~ /^opme(\s+($mask{chan}))?$/i ) {
92 return unless ( &hasFlag('o') );
93 return unless ( &hasFlag('A') );
102 # can this be exploited?
103 rawout("MODE $chan +o $who");
109 if ( $message =~ /^backlog(\s+(.*))?$/i ) {
110 return unless ( &hasFlag('o') );
111 return unless ( &IsParam('backlog') );
113 my $max = $param{'backlog'};
115 if ( !defined $num ) {
119 elsif ( $num !~ /^\d+/ ) {
120 &msg( $who, "error: argument is not positive integer." );
123 elsif ( $num > $max or $num < 0 ) {
124 &msg( $who, "error: argument is out of range (max $max)." );
128 &msg( $who, "Start of backlog..." );
129 for ( 0 .. $num - 1 ) {
130 sleep 1 if ( $_ % 4 == 0 and $_ != 0 );
131 $conn->privmsg( $who,
132 "[" . ( $_ + 1 ) . "]: $backlog[$max-$num+$_]" );
134 &msg( $who, "End of backlog." );
140 if ( $message =~ /^dumpvars$/i ) {
141 return unless ( &hasFlag('o') );
142 return unless ( &IsParam('DumpVars') );
144 &status("Dumping all variables...");
151 if ( $message =~ /^symdump$/i ) {
152 return unless ( &hasFlag('o') );
153 return unless ( &IsParam('DumpVars2') );
155 &status("Dumping all variables...");
162 if ( $message =~ /^kick(\s+(.*?))$/ ) {
163 return unless ( &hasFlag('o') );
171 my @args = split( /\s+/, $arg );
172 my ( $nick, $chan, $reason ) = @args;
174 if ( &validChan($chan) == 0 ) {
175 &msg( $who, "error: invalid channel \002$chan\002" );
179 if ( &IsNickInChan( $nick, $chan ) == 0 ) {
180 &msg( $who, "$nick is not in $chan." );
184 &kick( $nick, $chan, $reason );
190 if ( $message =~ /^mode(\s+(.*))?$/ ) {
191 return unless ( &hasFlag('n') );
192 my ( $chan, $mode ) = split /\s+/, $2, 2;
199 if ( &validChan($chan) == 0 ) {
200 &msg( $who, "error: invalid channel \002$chan\002" );
204 if ( !$channels{$chan}{o}{$ident} ) {
205 &msg( $who, "error: don't have ops on \002$chan\002" );
209 &mode( $chan, $mode );
215 if ( $message =~ /^part(\s+(\S+))?$/i ) {
216 return unless ( &hasFlag('o') );
219 if ( $jchan !~ /^$mask{chan}$/ ) {
220 &msg( $who, "error, invalid chan." );
225 if ( !&validChan($jchan) ) {
226 &msg( $who, "error, I'm not on that chan." );
230 &msg( $jchan, "Leaving. (courtesy of $who)." );
235 # lobotomy. sometimes we want the bot to be _QUIET_.
236 if ( $message =~ /^(lobotomy|bequiet)$/i ) {
237 return unless ( &hasFlag('o') );
240 &performReply("i'm already lobotomized");
243 &performReply('i have been lobotomized');
251 if ( $message =~ /^(unlobotomy|benoisy)$/i ) {
252 return unless ( &hasFlag('o') );
255 &performReply('i have been unlobotomized, woohoo');
257 delete $cache{lobotomy};
259 # undef $cache{lobotomy}; # ??
262 &performReply("i'm not lobotomized");
269 if ( $message =~ /^op(\s+(.*))?$/i ) {
270 return unless ( &hasFlag('o') );
274 if ( $opee =~ / / ) {
275 if ( $opee =~ /^(\S+)\s+(\S+)$/ ) {
278 if ( !&validChan($2) ) {
279 &msg( $who, "error: invalid chan ($2)." );
284 &msg( $who, "error: invalid params." );
289 @chans = keys %channels;
295 next unless ( &IsNickInChan( $opee, $_ ) );
297 if ( $channels{$_}{'o'}{$opee} ) {
298 &performStrictReply("op: $opee already has ops on $_");
303 &performStrictReply("opping $opee on $_");
307 if ( $found != $op ) {
308 &performStrictReply("op: opped on all possible channels.");
311 &DEBUG("op: found => '$found'.");
312 &DEBUG("op: op => '$op'.");
319 if ( $message =~ /^deop(\s+(.*))?$/i ) {
320 return unless ( &hasFlag('o') );
324 if ( $opee =~ / / ) {
325 if ( $opee =~ /^(\S+)\s+(\S+)$/ ) {
328 if ( !&validChan($2) ) {
329 &msg( $who, "error: invalid chan ($2)." );
334 &msg( $who, "error: invalid params." );
339 @chans = keys %channels;
345 next unless ( &IsNickInChan( $opee, $_ ) );
347 if ( !exists $channels{$_}{'o'}{$opee} ) {
348 &status("deop: $opee already has no ops on $_");
353 &status("deopping $opee on $_ at ${who}'s request");
357 if ( $found != $op ) {
358 &status("deop: deopped on all possible channels.");
361 &DEBUG("deop: found => '$found'.");
362 &DEBUG("deop: op => '$op'.");
369 if ( $message =~ s/^say\s+(\S+)\s+(.*)// ) {
370 return unless ( &hasFlag('o') );
371 my ( $chan, $msg ) = ( lc $1, $2 );
373 &DEBUG("chan => '$1', msg => '$msg'.");
381 if ( $message =~ s/^do\s+(\S+)\s+(.*)// ) {
382 return unless ( &hasFlag('o') );
383 my ( $chan, $msg ) = ( lc $1, $2 );
385 &DEBUG("chan => '$1', msg => '$msg'.");
387 &action( $chan, $msg );
393 if ( $message =~ /^die$/ ) {
394 return unless ( &hasFlag('n') );
398 &status("Dying by $who\'s request");
402 # global factoid substitution.
403 if ( $message =~ m|^\* =~ s([/,#])(.+?)\1(.*?)\1;?\s*$| ) {
404 my ( $delim, $op, $np ) = ( $1, $2, $3 );
405 return unless ( &hasFlag('n') );
406 ### TODO: support flags to do full-on global.
409 if ( $np =~ /$delim/ ) {
411 "looks like you used the delimiter too many times. You may want to use a different delimiter, like ':' or '#'."
416 ### TODO: fix up $op to support mysql/sqlite/pgsql
417 ### TODO: => add db/sql specific function to fix this.
419 &searchTable( 'factoids', 'factoid_key', 'factoid_value', $op );
421 if ( !scalar @list ) {
422 &performReply("Expression didn't match anything.");
426 if ( scalar @list > 100 ) {
427 &performReply("regex found more than 100 matches... not doing.");
431 &status( "gsubst: going to alter " . scalar(@list) . " factoids." );
432 &performReply( 'going to alter ' . scalar(@list) . " factoids." );
438 next if ( &IsLocked($faqtoid) == 1 );
439 my $result = &getFactoid($faqtoid);
441 &DEBUG("was($faqtoid) => '$was'.");
444 # we could support global local (once off).
445 if ( $result =~ s/\Q$op/$np/gi ) {
446 if ( length $result > $param{'maxDataSize'} ) {
447 &performReply("that's too long (or was long)");
450 &setFactInfo( $faqtoid, 'factoid_value', $result );
451 &status("update: '$faqtoid' =is=> '$result'; was '$was'");
455 "subst: that's weird... thought we found the string ($op) in '$faqtoid'."
462 &ERROR("Some warnings/errors?");
465 &performReply( "Ok... did s/$op/$np/ for "
466 . ( scalar(@list) - $error )
473 if ( $message =~ /^jump(\s+(\S+))?$/i ) {
474 return unless ( &hasFlag('n') );
481 my ( $server, $port );
482 if ( $2 =~ /^(\S+)(:(\d+))?$/ ) {
487 &msg( $who, "invalid format." );
491 &status("jumping servers... $server...");
492 $conn->quit("jumping to $server");
494 if ( &irc( $server, $port ) == 0 ) {
500 if ( $message =~ /^reload$/i ) {
501 return unless ( &hasFlag('n') );
503 &status("USER reload $who");
504 &performStrictReply("reloading...");
508 &performStrictReply("reloaded.");
514 if ( $message =~ /^reset$/i ) {
515 return unless ( &hasFlag('n') );
517 &msg( $who, "resetting..." );
519 foreach ( keys %channels, keys %chanconf ) {
521 next if ( grep /^\Q$c\E$/i, @done );
528 &DEBUG('before clearircvars');
530 &DEBUG('before joinnextchan');
532 &DEBUG('after joinnextchan');
534 &status("USER reset $who");
535 &msg( $who, 'reset complete' );
541 if ( $message =~ /^rehash$/ ) {
542 return unless ( &hasFlag('n') );
544 &msg( $who, "rehashing..." );
546 &status("USER rehash $who");
547 &msg( $who, 'rehashed' );
553 ##### USER//CHAN SPECIFIC CONFIGURATION COMMANDS
556 if ( $message =~ /^chaninfo(\s+(.*))?$/ ) {
557 my @args = split /[\s\t]+/, $2; # hrm.
559 if ( scalar @args != 1 ) {
564 if ( !exists $chanconf{ $args[0] } ) {
565 &performStrictReply("no such channel $args[0]");
569 &performStrictReply("showing channel conf.");
570 foreach ( sort keys %{ $chanconf{ $args[0] } } ) {
571 &performStrictReply("$chan: $_ => $chanconf{$args[0]}{$_}");
573 &performStrictReply("End of chaninfo.");
579 if ( $message =~ /^(chanset|chanadd)(\s+(.*?))?$/ ) {
584 if ( !defined $args ) {
590 while ( $args =~ s/^($mask{chan})\s*// ) {
591 push( @chans, lc($1) );
594 if ( !scalar @chans ) {
595 push( @chans, '_default' );
599 my ( $what, $val ) = split /[\s\t]+/, $args, 2;
601 ### TODO: "cannot set values without +m".
602 return unless ( &hasFlag('n') );
605 if ( defined $what and $what !~ /^[-+]/ and !defined $val and $no_chan )
607 &performStrictReply("Showing $what values on all channels...");
610 foreach ( keys %chanconf ) {
612 if ( defined $chanconf{$_}{$what} ) {
613 $val = $chanconf{$_}{$what};
621 foreach ( keys %vals ) {
622 &performStrictReply( " $what = $_("
623 . scalar( keys %{ $vals{$_} } ) . "): "
624 . join( ' ', sort keys %{ $vals{$_} } ) );
627 &performStrictReply("End of list.");
632 ### TODO: move to UserDCC again.
633 if ( $cmd eq 'chanset' and !defined $what ) {
634 &DEBUG("showing channel conf.");
636 foreach $chan (@chans) {
637 if ( $chan eq '_default' ) {
638 &performStrictReply('Default channel settings');
641 &performStrictReply("chan: $chan (see _default also)");
645 foreach ( sort keys %{ $chanconf{$chan} } ) {
646 my $newstr = join( ', ', @items );
647 ### TODO: make length use channel line limit?
648 if ( length $newstr > 370 ) {
649 &performStrictReply(" $str");
653 push( @items, "$_ => $chanconf{$chan}{$_}" );
656 my $str = join( ', ', @items );
657 &performStrictReply(" $str");
663 $cache{confvars}{$what} = $val;
667 &chanSet( $cmd, $_, $what, $val );
673 if ( $message =~ /^(chanunset|chandel)(\s+(.*))?$/ ) {
674 return unless ( &hasFlag('n') );
679 if ( !defined $args ) {
686 if ( $args =~ s/^(\-)?($mask{chan})\s*// ) {
688 $delete = ($1) ? 1 : 0;
691 &VERB( "no chan arg; setting to default.", 2 );
696 if ( !exists $chanconf{$chan} ) {
697 &performStrictReply("no such channel $chan");
703 if ( !&getChanConf( $args, $chan ) ) {
704 &performStrictReply("$args does not exist for $chan");
708 my @chans = &ChanConfList($args);
709 &DEBUG( "scalar chans => " . scalar(@chans) );
710 if ( scalar @chans == 1 and $chans[0] eq '_default' and !$no_chan )
713 "ok, $args was set only for _default; unsetting for _defaul but setting for other chans."
716 my $val = $chanconf{$_}{_default};
717 foreach ( keys %chanconf ) {
718 $chanconf{$_}{$args} = $val;
720 delete $chanconf{_default}{$args};
721 $cache{confvars}{$args} = 0;
727 if ( $no_chan and !exists( $chanconf{_default}{$args} ) ) {
729 "ok, $args for _default does not exist, removing from all chans."
732 foreach ( keys %chanconf ) {
733 next unless ( exists $chanconf{$_}{$args} );
734 &DEBUG("delete chanconf{$_}{$args};");
735 delete $chanconf{$_}{$args};
737 $cache{confvars}{$args} = 0;
744 "Unsetting channel ($chan) option $args. (was $chanconf{$chan}{$args})"
746 delete $chanconf{$chan}{$args};
752 &performStrictReply("Deleting channel $chan for sure!");
753 $utime_chanfile = time();
757 &performStrictReply("Leaving $chan...");
759 delete $chanconf{$chan};
762 &performStrictReply("Prefix channel with '-' to delete for sure.");
768 if ( $message =~ /^newpass(\s+(.*))?$/ ) {
769 my (@args) = split /[\s\t]+/, $2 || '';
771 if ( scalar @args != 1 ) {
776 my $u = &getUser($who);
777 my $crypt = &mkcrypt( $args[0] );
779 &performStrictReply("Set your passwd to '$crypt'");
780 $users{$u}{PASS} = $crypt;
782 $utime_userfile = time();
788 if ( $message =~ /^chpass(\s+(.*))?$/ ) {
789 my (@args) = split /[\s\t]+/, $2 || '';
791 if ( !scalar @args ) {
796 if ( !&IsUser( $args[0] ) ) {
797 &performStrictReply("user $args[0] is not valid.");
801 my $u = &getUser( $args[0] );
803 &performStrictReply("Internal error, u = NULL.");
807 if ( scalar @args == 1 ) {
810 if ( !&IsFlag('n') and $who !~ /^\Q$verifyUser\E$/i ) {
811 &performStrictReply("cannot remove passwd of others.");
815 if ( !exists $users{$u}{PASS} ) {
816 &performStrictReply("$u does not have pass set anyway.");
820 &performStrictReply("Deleted pass from $u.");
822 $utime_userfile = time();
825 delete $users{$u}{PASS};
830 my $crypt = &mkcrypt( $args[1] );
831 &performStrictReply("Set $u's passwd to '$crypt'");
832 $users{$u}{PASS} = $crypt;
834 $utime_userfile = time();
840 if ( $message =~ /^chattr(\s+(.*))?$/ ) {
841 my (@args) = split /[\s\t]+/, $2 || '';
843 if ( !scalar @args ) {
850 if ( $args[0] =~ /^$mask{nick}$/i ) {
853 $user = &getUser( $args[0] );
859 $user = &getUser($who);
860 &DEBUG("user $who... nope.") unless ( defined $user );
861 $user = &getUser($verifyUser);
865 if ( !defined $user ) {
866 &performStrictReply("user does not exist.");
870 my $flags = $users{$user}{FLAGS};
871 if ( !defined $chflag ) {
872 &performStrictReply("Flags for $user: $flags");
876 &DEBUG("who => $who");
877 &DEBUG("verifyUser => $verifyUser");
878 if ( !&IsFlag('n') and $who !~ /^\Q$verifyUser\E$/i ) {
879 &performStrictReply("cannto change attributes of others.");
885 foreach ( split //, $chflag ) {
886 if ( $_ eq "+" ) { $state = 1; next; }
887 if ( $_ eq "-" ) { $state = 0; next; }
889 if ( !defined $state ) {
890 &performStrictReply("no initial + or - was found in attr.");
895 next if ( $flags =~ /\Q$_\E/ );
899 if ( &IsParam('owner')
900 and $param{owner} =~ /^\Q$user\E$/i
901 and $flags =~ /[nmo]/ )
903 &performStrictReply("not removing flag $_ for $user.");
906 next unless ( $flags =~ s/\Q$_\E// );
913 $utime_userfile = time();
917 $flags = join( '', sort split( '', $flags ) );
918 &performStrictReply("Current flags: $flags");
919 $users{$user}{FLAGS} = $flags;
922 &performStrictReply("No flags changed: $flags");
928 if ( $message =~ /^chnick(\s+(.*))?$/ ) {
929 my (@args) = split /[\s\t]+/, $2 || '';
931 if ( $who eq '_default' ) {
932 &WARN("$who or verifyuser tried to run chnick.");
936 if ( !scalar @args or scalar @args > 2 ) {
941 if ( scalar @args == 1 ) { # 1
942 $user = &getUser($who);
943 &DEBUG("nope, not $who.") unless ( defined $user );
944 $user ||= &getUser($verifyUser);
948 $user = &getUser( $args[0] );
952 if ( !defined $user ) {
953 &performStrictReply("user $who or $args[0] does not exist.");
957 if ( $user =~ /^\Q$chnick\E$/i ) {
958 &performStrictReply("user == chnick. why should I do that?");
962 if ( &getUser($chnick) ) {
963 &performStrictReply("user $chnick is already used!");
967 if ( !&IsFlag('n') and $who !~ /^\Q$verifyUser\E$/i ) {
968 &performStrictReply("cannto change nick of others.");
969 return 'REPLY' if ( $who eq '_default' );
973 foreach ( keys %{ $users{$user} } ) {
974 $users{$chnick}{$_} = $users{$user}{$_};
975 delete $users{$user}{$_};
977 undef $users{$user}; # ???
979 $utime_userfile = time();
982 &performStrictReply("Changed '$user' to '$chnick' successfully.");
987 if ( $message =~ /^(hostadd|hostdel)(\s+(.*))?$/ ) {
989 my (@args) = split /[\s\t]+/, $3 || '';
990 my $state = ( $1 eq "hostadd" ) ? 1 : 0;
992 if ( !scalar @args ) {
997 if ( $who eq '_default' ) {
998 &WARN("$who or verifyuser tried to run $cmd.");
1002 my ( $user, $mask );
1003 if ( $args[0] =~ /^$mask{nick}$/i ) { # <nick>
1004 return unless ( &hasFlag('n') );
1005 $user = &getUser( $args[0] );
1009 # FIXME: who or verifyUser. (don't remember why)
1010 $user = &getUser($who);
1014 if ( !defined $user ) {
1015 &performStrictReply("user $user does not exist.");
1019 if ( !defined $mask ) {
1020 &performStrictReply( "Hostmasks for $user: "
1021 . join( ' ', keys %{ $users{$user}{HOSTS} } ) );
1025 if ( !&IsFlag('n') and $who !~ /^\Q$verifyUser\E$/i ) {
1026 &performStrictReply("cannto change masks of others.");
1030 my $count = scalar keys %{ $users{$user}{HOSTS} };
1032 if ($state) { # add.
1033 if ( $mask !~ /^$mask{nuh}$/ ) {
1034 &performStrictReply(
1035 "error: mask ($mask) is not a real hostmask.");
1039 if ( exists $users{$user}{HOSTS}{$mask} ) {
1040 &performStrictReply("mask $mask already exists.");
1044 ### TODO: override support.
1045 $users{$user}{HOSTS}{$mask} = 1;
1047 &performStrictReply("Added $mask to list of masks.");
1052 if ( !exists $users{$user}{HOSTS}{$mask} ) {
1053 &performStrictReply("mask $mask does not exist.");
1057 ### TODO: wildcard support. ?
1058 delete $users{$user}{HOSTS}{$mask};
1060 if ( scalar keys %{ $users{$user}{HOSTS} } != $count ) {
1061 &performStrictReply("Removed $mask from list of masks.");
1064 &performStrictReply(
1065 "error: could not find $mask in list of masks.");
1070 $utime_userfile = time();
1076 if ( $message =~ /^(banadd|bandel)(\s+(.*))?$/ ) {
1079 my (@args) = split /[\s\t]+/, $3 || '';
1080 my $state = ( $1 eq "banadd" ) ? 1 : 0;
1082 if ( !scalar @args ) {
1087 my ( $mask, $chan, $time, $reason );
1089 if ( $flatarg =~ s/^($mask{nuh})\s*// ) {
1093 &DEBUG("arg does not contain nuh mask?");
1096 if ( $flatarg =~ s/^($mask{chan})\s*// ) {
1100 $chan = '*'; # _default instead?
1103 if ( $state == 0 ) { # delete.
1104 my @c = &banDel($mask);
1107 &unban( $mask, $_ );
1111 &performStrictReply("Removed $mask from chans: @c");
1114 &performStrictReply("$mask was not found in ban list.");
1125 if ( $flatarg =~ s/^(\d+)\s*// ) {
1127 &DEBUG("time = $time.");
1129 &performStrictReply("error: time cannot be negatime?");
1137 if ( $flatarg =~ s/^(.*)$// ) { # need length?
1141 if ( !&IsFlag('n') and $who !~ /^\Q$verifyUser\E$/i ) {
1142 &performStrictReply("cannto change masks of others.");
1146 if ( $mask !~ /^$mask{nuh}$/ ) {
1147 &performStrictReply("error: mask ($mask) is not a real hostmask.");
1151 if ( &banAdd( $mask, $chan, $time, $reason ) == 2 ) {
1152 &performStrictReply("ban already exists; overwriting.");
1154 &performStrictReply(
1155 "Added $mask for $chan (time => $time, reason => $reason)");
1160 if ( $message =~ /^whois(\s+(.*))?$/ ) {
1163 if ( !defined $arg ) {
1168 my $user = &getUser($arg);
1169 if ( !defined $user ) {
1170 &performStrictReply("whois: user '$arg' does not exist.");
1174 ### TODO: better (eggdrop-like) output.
1175 &performStrictReply("user: $user");
1176 foreach ( keys %{ $users{$user} } ) {
1177 my $ref = ref $users{$user}{$_};
1179 if ( $ref eq 'HASH' ) {
1181 ### DOES NOT WORK???
1182 foreach ( keys %{ $users{$user}{$type} } ) {
1183 &performStrictReply(" $type => $_");
1188 &performStrictReply(" $_ => $users{$user}{$_}");
1190 &performStrictReply("End of USER whois.");
1195 if ( $message =~ /^bans(\s+(.*))?$/ ) {
1198 if ( defined $arg ) {
1199 if ( $arg ne '_default' and !&validChan($arg) ) {
1200 &performStrictReply("error: chan $chan is invalid.");
1205 if ( !scalar keys %bans ) {
1206 &performStrictReply("Ban list is empty.");
1211 &performStrictReply(
1212 " mask: expire, time-added, count, who-by, reason");
1213 foreach $c ( keys %bans ) {
1214 next unless ( !defined $arg or $arg =~ /^\Q$c\E$/i );
1215 &performStrictReply(" $c:");
1217 foreach ( keys %{ $bans{$c} } ) {
1218 my $val = $bans{$c}{$_};
1220 if ( ref $val eq 'ARRAY' ) {
1221 my @array = @{$val};
1222 &performStrictReply(" $_: @array");
1225 &DEBUG("unknown ban: $val");
1229 &performStrictReply("END of bans.");
1234 if ( $message =~ /^banlist(\s+(.*))?$/ ) {
1237 if ( defined $arg and $arg !~ /^$mask{chan}$/ ) {
1238 &performStrictReply("error: chan $chan is invalid.");
1242 &DEBUG("bans for global or arg => $arg.");
1243 foreach ( keys %bans ) { #CHANGE!!!
1244 &DEBUG(" $_ => $bans{$_}.");
1247 &DEBUG("End of bans.");
1248 &performStrictReply("END of bans.");
1253 if ( $message =~ /^save$/ ) {
1254 return unless ( &hasFlag('o') );
1258 &performStrictReply('saved user and chan files');
1264 $message =~ s/^addignore/+ignore/;
1265 $message =~ s/^(del|un)ignore/-ignore/;
1268 if ( $message =~ /^(\+|\-)ignore(\s+(.*))?$/i ) {
1269 return unless ( &hasFlag('o') );
1270 my $state = ( $1 eq "+" ) ? 1 : 0;
1271 my $str = $1 . 'ignore';
1279 my ( $mask, $chan, $time, $comment );
1282 if ( $args =~ s/^($mask{nuh})\s*// ) {
1286 &ERROR("no NUH mask?");
1290 if ( !$state ) { # delignore.
1291 if ( &ignoreDel($mask) ) {
1292 &performStrictReply("ok, deleted ignores for $mask.");
1295 &performStrictReply("could not find $mask in ignore list.");
1305 if ( $args =~ s/^($mask{chan}|\*)\s*// ) {
1313 if ( $args =~ s/^(\d+)\s*// ) {
1314 $time = $1; # time is in minutes
1325 $comment = "added by $who";
1328 if ( &ignoreAdd( $mask, $chan, $time, $comment ) > 1 ) {
1329 &performStrictReply(
1330 "FIXME: $mask already in ignore list; written over anyway.");
1333 &performStrictReply("added $mask to ignore list.");
1339 if ( $message =~ /^ignore(\s+(.*))?$/ ) {
1342 if ( defined $arg ) {
1343 if ( $arg !~ /^$mask{chan}$/ ) {
1344 &performStrictReply("error: chan $chan is invalid.");
1348 if ( !&validChan($arg) ) {
1349 &performStrictReply("error: chan $arg is invalid.");
1353 &performStrictReply("Showing bans for $arg only.");
1356 if ( !scalar keys %ignore ) {
1357 &performStrictReply("Ignore list is empty.");
1361 ### TODO: proper (eggdrop-like) formatting.
1363 &performStrictReply(" mask: expire, time-added, who, comment");
1364 foreach $c ( keys %ignore ) {
1365 next unless ( !defined $arg or $arg =~ /^\Q$c\E$/i );
1366 &performStrictReply(" $c:");
1368 foreach ( keys %{ $ignore{$c} } ) {
1369 my $ref = ref $ignore{$c}{$_};
1370 if ( $ref eq 'ARRAY' ) {
1371 my @array = @{ $ignore{$c}{$_} };
1372 &performStrictReply(" $_: @array");
1375 &DEBUG("unknown ignore line?");
1379 &performStrictReply("END of ignore.");
1385 if ( $message =~ /^(useradd|userdel)(\s+(.*))?$/i ) {
1387 my @args = split /\s+/, $3 || '';
1389 my $state = ( $cmd eq "useradd" ) ? 1 : 0;
1391 if ( !scalar @args ) {
1396 if ( $cmd eq 'useradd' ) {
1397 if ( scalar @args != 2 ) {
1398 &performStrictReply('useradd requires hostmask argument.');
1402 elsif ( scalar @args != 1 ) {
1403 &performStrictReply('too many arguments.');
1410 if ( scalar @args == 1 ) {
1411 $args[1] = &getHostMask( $args[0] );
1412 &performStrictReply(
1413 "Attemping to guess $args[0]'s hostmask...");
1415 # crude hack... crappy Net::IRC
1420 # hopefully this is right.
1421 my $nick = ( keys %{ $cache{nuhInfo} } )[0];
1422 if ( !defined $nick ) {
1423 &performStrictReply(
1424 "couldn't get nuhinfo... adding user without a hostmask."
1429 my $mask = &makeHostMask( $cache{nuhInfo}{$nick}{NUH} );
1431 if ( &userAdd( $nick, $mask ) ) {
1434 &performStrictReply(
1435 "Added $nick with flags $users{$nick}{FLAGS}");
1436 my @hosts = keys %{ $users{$nick}{HOSTS} };
1437 &performStrictReply("hosts: @hosts");
1444 &DEBUG("args => @args");
1445 if ( &userAdd(@args) ) { # success.
1446 &performStrictReply(
1447 "Added $args[0] with flags $users{$args[0]}{FLAGS}");
1448 my @hosts = keys %{ $users{ $args[0] }{HOSTS} };
1449 &performStrictReply("hosts: @hosts");
1453 &performStrictReply("User $args[0] already exists");
1459 if ( &userDel( $args[0] ) ) { # success.
1460 &performStrictReply("Deleted $args[0] successfully.");
1464 &performStrictReply("User $args[0] does not exist.");
1471 if ( $message =~ /^sched$/ ) {
1476 foreach ( keys %sched ) {
1477 next unless ( exists $sched{$_}{TIME} );
1478 $time{ $sched{$_}{TIME} - time() }{$_} = 1;
1481 next unless ( exists $sched{$_}{RUNNING} );
1486 foreach ( sort { $a <=> $b } keys %time ) {
1487 my $str = join( ', ', sort keys %{ $time{$_} } );
1488 &DEBUG("time => $_, str => $str");
1489 push( @time, "$str (" . &Time2String($_) . ")" );
1492 &performStrictReply( &formListReply( 0, "Schedulers: ", @time ) );
1493 &performStrictReply(
1494 &formListReply( 0, "Scheds to run: ", sort @list ) );
1495 &performStrictReply(
1497 0, "Scheds running(should not happen?) ",
1505 # quite a cool hack: reply in DCC CHAT.
1506 $msgType = 'chat' if ( exists $dcc{'CHAT'}{$who} );
1509 $done++ if &parseCmdHook($message);
1510 $done++ unless ( &Modules() );
1513 &DEBUG("running non DCC CHAT command inside DCC CHAT!");
1522 # vim:ts=4:sw=4:expandtab:tw=80