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...");
506 &performStrictReply("reloaded.");
512 if ( $message =~ /^reset$/i ) {
513 return unless ( &hasFlag('n') );
515 &msg( $who, "resetting..." );
517 foreach ( keys %channels, keys %chanconf ) {
519 next if ( grep /^\Q$c\E$/i, @done );
526 &DEBUG('before clearircvars');
528 &DEBUG('before joinnextchan');
530 &DEBUG('after joinnextchan');
532 &status("USER reset $who");
533 &msg( $who, 'reset complete' );
539 if ( $message =~ /^rehash$/ ) {
540 return unless ( &hasFlag('n') );
542 &msg( $who, "rehashing..." );
544 &status("USER rehash $who");
545 &msg( $who, 'rehashed' );
551 ##### USER//CHAN SPECIFIC CONFIGURATION COMMANDS
554 if ( $message =~ /^chaninfo(\s+(.*))?$/ ) {
555 my @args = split /[\s\t]+/, $2; # hrm.
557 if ( scalar @args != 1 ) {
562 if ( !exists $chanconf{ $args[0] } ) {
563 &performStrictReply("no such channel $args[0]");
567 &performStrictReply("showing channel conf.");
568 foreach ( sort keys %{ $chanconf{ $args[0] } } ) {
569 &performStrictReply("$chan: $_ => $chanconf{$args[0]}{$_}");
571 &performStrictReply("End of chaninfo.");
577 if ( $message =~ /^(chanset|chanadd)(\s+(.*?))?$/ ) {
582 if ( !defined $args ) {
588 while ( $args =~ s/^($mask{chan})\s*// ) {
589 push( @chans, lc($1) );
592 if ( !scalar @chans ) {
593 push( @chans, '_default' );
597 my ( $what, $val ) = split /[\s\t]+/, $args, 2;
599 ### TODO: "cannot set values without +m".
600 return unless ( &hasFlag('n') );
603 if ( defined $what and $what !~ /^[-+]/ and !defined $val and $no_chan )
605 &performStrictReply("Showing $what values on all channels...");
608 foreach ( keys %chanconf ) {
610 if ( defined $chanconf{$_}{$what} ) {
611 $val = $chanconf{$_}{$what};
619 foreach ( keys %vals ) {
620 &performStrictReply( " $what = $_("
621 . scalar( keys %{ $vals{$_} } ) . "): "
622 . join( ' ', sort keys %{ $vals{$_} } ) );
625 &performStrictReply("End of list.");
630 ### TODO: move to UserDCC again.
631 if ( $cmd eq 'chanset' and !defined $what ) {
632 &DEBUG("showing channel conf.");
634 foreach $chan (@chans) {
635 if ( $chan eq '_default' ) {
636 &performStrictReply('Default channel settings');
639 &performStrictReply("chan: $chan (see _default also)");
643 foreach ( sort keys %{ $chanconf{$chan} } ) {
644 my $newstr = join( ', ', @items );
645 ### TODO: make length use channel line limit?
646 if ( length $newstr > 370 ) {
647 &performStrictReply(" $str");
651 push( @items, "$_ => $chanconf{$chan}{$_}" );
654 my $str = join( ', ', @items );
655 &performStrictReply(" $str");
661 $cache{confvars}{$what} = $val;
665 &chanSet( $cmd, $_, $what, $val );
671 if ( $message =~ /^(chanunset|chandel)(\s+(.*))?$/ ) {
672 return unless ( &hasFlag('n') );
677 if ( !defined $args ) {
684 if ( $args =~ s/^(\-)?($mask{chan})\s*// ) {
686 $delete = ($1) ? 1 : 0;
689 &VERB( "no chan arg; setting to default.", 2 );
694 if ( !exists $chanconf{$chan} ) {
695 &performStrictReply("no such channel $chan");
701 if ( !&getChanConf( $args, $chan ) ) {
702 &performStrictReply("$args does not exist for $chan");
706 my @chans = &ChanConfList($args);
707 &DEBUG( "scalar chans => " . scalar(@chans) );
708 if ( scalar @chans == 1 and $chans[0] eq '_default' and !$no_chan )
711 "ok, $args was set only for _default; unsetting for _defaul but setting for other chans."
714 my $val = $chanconf{$_}{_default};
715 foreach ( keys %chanconf ) {
716 $chanconf{$_}{$args} = $val;
718 delete $chanconf{_default}{$args};
719 $cache{confvars}{$args} = 0;
725 if ( $no_chan and !exists( $chanconf{_default}{$args} ) ) {
727 "ok, $args for _default does not exist, removing from all chans."
730 foreach ( keys %chanconf ) {
731 next unless ( exists $chanconf{$_}{$args} );
732 &DEBUG("delete chanconf{$_}{$args};");
733 delete $chanconf{$_}{$args};
735 $cache{confvars}{$args} = 0;
742 "Unsetting channel ($chan) option $args. (was $chanconf{$chan}{$args})"
744 delete $chanconf{$chan}{$args};
750 &performStrictReply("Deleting channel $chan for sure!");
751 $utime_chanfile = time();
755 &performStrictReply("Leaving $chan...");
757 delete $chanconf{$chan};
760 &performStrictReply("Prefix channel with '-' to delete for sure.");
766 if ( $message =~ /^newpass(\s+(.*))?$/ ) {
767 my (@args) = split /[\s\t]+/, $2 || '';
769 if ( scalar @args != 1 ) {
774 my $u = &getUser($who);
775 my $crypt = &mkcrypt( $args[0] );
777 &performStrictReply("Set your passwd to '$crypt'");
778 $users{$u}{PASS} = $crypt;
780 $utime_userfile = time();
786 if ( $message =~ /^chpass(\s+(.*))?$/ ) {
787 my (@args) = split /[\s\t]+/, $2 || '';
789 if ( !scalar @args ) {
794 if ( !&IsUser( $args[0] ) ) {
795 &performStrictReply("user $args[0] is not valid.");
799 my $u = &getUser( $args[0] );
801 &performStrictReply("Internal error, u = NULL.");
805 if ( scalar @args == 1 ) {
808 if ( !&IsFlag('n') and $who !~ /^\Q$verifyUser\E$/i ) {
809 &performStrictReply("cannot remove passwd of others.");
813 if ( !exists $users{$u}{PASS} ) {
814 &performStrictReply("$u does not have pass set anyway.");
818 &performStrictReply("Deleted pass from $u.");
820 $utime_userfile = time();
823 delete $users{$u}{PASS};
828 my $crypt = &mkcrypt( $args[1] );
829 &performStrictReply("Set $u's passwd to '$crypt'");
830 $users{$u}{PASS} = $crypt;
832 $utime_userfile = time();
838 if ( $message =~ /^chattr(\s+(.*))?$/ ) {
839 my (@args) = split /[\s\t]+/, $2 || '';
841 if ( !scalar @args ) {
848 if ( $args[0] =~ /^$mask{nick}$/i ) {
851 $user = &getUser( $args[0] );
857 $user = &getUser($who);
858 &DEBUG("user $who... nope.") unless ( defined $user );
859 $user = &getUser($verifyUser);
863 if ( !defined $user ) {
864 &performStrictReply("user does not exist.");
868 my $flags = $users{$user}{FLAGS};
869 if ( !defined $chflag ) {
870 &performStrictReply("Flags for $user: $flags");
874 &DEBUG("who => $who");
875 &DEBUG("verifyUser => $verifyUser");
876 if ( !&IsFlag('n') and $who !~ /^\Q$verifyUser\E$/i ) {
877 &performStrictReply("cannto change attributes of others.");
883 foreach ( split //, $chflag ) {
884 if ( $_ eq "+" ) { $state = 1; next; }
885 if ( $_ eq "-" ) { $state = 0; next; }
887 if ( !defined $state ) {
888 &performStrictReply("no initial + or - was found in attr.");
893 next if ( $flags =~ /\Q$_\E/ );
897 if ( &IsParam('owner')
898 and $param{owner} =~ /^\Q$user\E$/i
899 and $flags =~ /[nmo]/ )
901 &performStrictReply("not removing flag $_ for $user.");
904 next unless ( $flags =~ s/\Q$_\E// );
911 $utime_userfile = time();
915 $flags = join( '', sort split( '', $flags ) );
916 &performStrictReply("Current flags: $flags");
917 $users{$user}{FLAGS} = $flags;
920 &performStrictReply("No flags changed: $flags");
926 if ( $message =~ /^chnick(\s+(.*))?$/ ) {
927 my (@args) = split /[\s\t]+/, $2 || '';
929 if ( $who eq '_default' ) {
930 &WARN("$who or verifyuser tried to run chnick.");
934 if ( !scalar @args or scalar @args > 2 ) {
939 if ( scalar @args == 1 ) { # 1
940 $user = &getUser($who);
941 &DEBUG("nope, not $who.") unless ( defined $user );
942 $user ||= &getUser($verifyUser);
946 $user = &getUser( $args[0] );
950 if ( !defined $user ) {
951 &performStrictReply("user $who or $args[0] does not exist.");
955 if ( $user =~ /^\Q$chnick\E$/i ) {
956 &performStrictReply("user == chnick. why should I do that?");
960 if ( &getUser($chnick) ) {
961 &performStrictReply("user $chnick is already used!");
965 if ( !&IsFlag('n') and $who !~ /^\Q$verifyUser\E$/i ) {
966 &performStrictReply("cannto change nick of others.");
967 return 'REPLY' if ( $who eq '_default' );
971 foreach ( keys %{ $users{$user} } ) {
972 $users{$chnick}{$_} = $users{$user}{$_};
973 delete $users{$user}{$_};
975 undef $users{$user}; # ???
977 $utime_userfile = time();
980 &performStrictReply("Changed '$user' to '$chnick' successfully.");
985 if ( $message =~ /^(hostadd|hostdel)(\s+(.*))?$/ ) {
987 my (@args) = split /[\s\t]+/, $3 || '';
988 my $state = ( $1 eq "hostadd" ) ? 1 : 0;
990 if ( !scalar @args ) {
995 if ( $who eq '_default' ) {
996 &WARN("$who or verifyuser tried to run $cmd.");
1000 my ( $user, $mask );
1001 if ( $args[0] =~ /^$mask{nick}$/i ) { # <nick>
1002 return unless ( &hasFlag('n') );
1003 $user = &getUser( $args[0] );
1007 # FIXME: who or verifyUser. (don't remember why)
1008 $user = &getUser($who);
1012 if ( !defined $user ) {
1013 &performStrictReply("user $user does not exist.");
1017 if ( !defined $mask ) {
1018 &performStrictReply( "Hostmasks for $user: "
1019 . join( ' ', keys %{ $users{$user}{HOSTS} } ) );
1023 if ( !&IsFlag('n') and $who !~ /^\Q$verifyUser\E$/i ) {
1024 &performStrictReply("cannto change masks of others.");
1028 my $count = scalar keys %{ $users{$user}{HOSTS} };
1030 if ($state) { # add.
1031 if ( $mask !~ /^$mask{nuh}$/ ) {
1032 &performStrictReply(
1033 "error: mask ($mask) is not a real hostmask.");
1037 if ( exists $users{$user}{HOSTS}{$mask} ) {
1038 &performStrictReply("mask $mask already exists.");
1042 ### TODO: override support.
1043 $users{$user}{HOSTS}{$mask} = 1;
1045 &performStrictReply("Added $mask to list of masks.");
1050 if ( !exists $users{$user}{HOSTS}{$mask} ) {
1051 &performStrictReply("mask $mask does not exist.");
1055 ### TODO: wildcard support. ?
1056 delete $users{$user}{HOSTS}{$mask};
1058 if ( scalar keys %{ $users{$user}{HOSTS} } != $count ) {
1059 &performStrictReply("Removed $mask from list of masks.");
1062 &performStrictReply(
1063 "error: could not find $mask in list of masks.");
1068 $utime_userfile = time();
1074 if ( $message =~ /^(banadd|bandel)(\s+(.*))?$/ ) {
1077 my (@args) = split /[\s\t]+/, $3 || '';
1078 my $state = ( $1 eq "banadd" ) ? 1 : 0;
1080 if ( !scalar @args ) {
1085 my ( $mask, $chan, $time, $reason );
1087 if ( $flatarg =~ s/^($mask{nuh})\s*// ) {
1091 &DEBUG("arg does not contain nuh mask?");
1094 if ( $flatarg =~ s/^($mask{chan})\s*// ) {
1098 $chan = '*'; # _default instead?
1101 if ( $state == 0 ) { # delete.
1102 my @c = &banDel($mask);
1105 &unban( $mask, $_ );
1109 &performStrictReply("Removed $mask from chans: @c");
1112 &performStrictReply("$mask was not found in ban list.");
1123 if ( $flatarg =~ s/^(\d+)\s*// ) {
1125 &DEBUG("time = $time.");
1127 &performStrictReply("error: time cannot be negatime?");
1135 if ( $flatarg =~ s/^(.*)$// ) { # need length?
1139 if ( !&IsFlag('n') and $who !~ /^\Q$verifyUser\E$/i ) {
1140 &performStrictReply("cannto change masks of others.");
1144 if ( $mask !~ /^$mask{nuh}$/ ) {
1145 &performStrictReply("error: mask ($mask) is not a real hostmask.");
1149 if ( &banAdd( $mask, $chan, $time, $reason ) == 2 ) {
1150 &performStrictReply("ban already exists; overwriting.");
1152 &performStrictReply(
1153 "Added $mask for $chan (time => $time, reason => $reason)");
1158 if ( $message =~ /^whois(\s+(.*))?$/ ) {
1161 if ( !defined $arg ) {
1166 my $user = &getUser($arg);
1167 if ( !defined $user ) {
1168 &performStrictReply("whois: user '$arg' does not exist.");
1172 ### TODO: better (eggdrop-like) output.
1173 &performStrictReply("user: $user");
1174 foreach ( keys %{ $users{$user} } ) {
1175 my $ref = ref $users{$user}{$_};
1177 if ( $ref eq 'HASH' ) {
1179 ### DOES NOT WORK???
1180 foreach ( keys %{ $users{$user}{$type} } ) {
1181 &performStrictReply(" $type => $_");
1186 &performStrictReply(" $_ => $users{$user}{$_}");
1188 &performStrictReply("End of USER whois.");
1193 if ( $message =~ /^bans(\s+(.*))?$/ ) {
1196 if ( defined $arg ) {
1197 if ( $arg ne '_default' and !&validChan($arg) ) {
1198 &performStrictReply("error: chan $chan is invalid.");
1203 if ( !scalar keys %bans ) {
1204 &performStrictReply("Ban list is empty.");
1209 &performStrictReply(
1210 " mask: expire, time-added, count, who-by, reason");
1211 foreach $c ( keys %bans ) {
1212 next unless ( !defined $arg or $arg =~ /^\Q$c\E$/i );
1213 &performStrictReply(" $c:");
1215 foreach ( keys %{ $bans{$c} } ) {
1216 my $val = $bans{$c}{$_};
1218 if ( ref $val eq 'ARRAY' ) {
1219 my @array = @{$val};
1220 &performStrictReply(" $_: @array");
1223 &DEBUG("unknown ban: $val");
1227 &performStrictReply("END of bans.");
1232 if ( $message =~ /^banlist(\s+(.*))?$/ ) {
1235 if ( defined $arg and $arg !~ /^$mask{chan}$/ ) {
1236 &performStrictReply("error: chan $chan is invalid.");
1240 &DEBUG("bans for global or arg => $arg.");
1241 foreach ( keys %bans ) { #CHANGE!!!
1242 &DEBUG(" $_ => $bans{$_}.");
1245 &DEBUG("End of bans.");
1246 &performStrictReply("END of bans.");
1251 if ( $message =~ /^save$/ ) {
1252 return unless ( &hasFlag('o') );
1256 &performStrictReply('saved user and chan files');
1262 $message =~ s/^addignore/+ignore/;
1263 $message =~ s/^(del|un)ignore/-ignore/;
1266 if ( $message =~ /^(\+|\-)ignore(\s+(.*))?$/i ) {
1267 return unless ( &hasFlag('o') );
1268 my $state = ( $1 eq "+" ) ? 1 : 0;
1269 my $str = $1 . 'ignore';
1277 my ( $mask, $chan, $time, $comment );
1280 if ( $args =~ s/^($mask{nuh})\s*// ) {
1284 &ERROR("no NUH mask?");
1288 if ( !$state ) { # delignore.
1289 if ( &ignoreDel($mask) ) {
1290 &performStrictReply("ok, deleted ignores for $mask.");
1293 &performStrictReply("could not find $mask in ignore list.");
1303 if ( $args =~ s/^($mask{chan}|\*)\s*// ) {
1311 if ( $args =~ s/^(\d+)\s*// ) {
1312 $time = $1; # time is in minutes
1323 $comment = "added by $who";
1326 if ( &ignoreAdd( $mask, $chan, $time, $comment ) > 1 ) {
1327 &performStrictReply(
1328 "FIXME: $mask already in ignore list; written over anyway.");
1331 &performStrictReply("added $mask to ignore list.");
1337 if ( $message =~ /^ignore(\s+(.*))?$/ ) {
1340 if ( defined $arg ) {
1341 if ( $arg !~ /^$mask{chan}$/ ) {
1342 &performStrictReply("error: chan $chan is invalid.");
1346 if ( !&validChan($arg) ) {
1347 &performStrictReply("error: chan $arg is invalid.");
1351 &performStrictReply("Showing bans for $arg only.");
1354 if ( !scalar keys %ignore ) {
1355 &performStrictReply("Ignore list is empty.");
1359 ### TODO: proper (eggdrop-like) formatting.
1361 &performStrictReply(" mask: expire, time-added, who, comment");
1362 foreach $c ( keys %ignore ) {
1363 next unless ( !defined $arg or $arg =~ /^\Q$c\E$/i );
1364 &performStrictReply(" $c:");
1366 foreach ( keys %{ $ignore{$c} } ) {
1367 my $ref = ref $ignore{$c}{$_};
1368 if ( $ref eq 'ARRAY' ) {
1369 my @array = @{ $ignore{$c}{$_} };
1370 &performStrictReply(" $_: @array");
1373 &DEBUG("unknown ignore line?");
1377 &performStrictReply("END of ignore.");
1383 if ( $message =~ /^(useradd|userdel)(\s+(.*))?$/i ) {
1385 my @args = split /\s+/, $3 || '';
1387 my $state = ( $cmd eq "useradd" ) ? 1 : 0;
1389 if ( !scalar @args ) {
1394 if ( $cmd eq 'useradd' ) {
1395 if ( scalar @args != 2 ) {
1396 &performStrictReply('useradd requires hostmask argument.');
1400 elsif ( scalar @args != 1 ) {
1401 &performStrictReply('too many arguments.');
1408 if ( scalar @args == 1 ) {
1409 $args[1] = &getHostMask( $args[0] );
1410 &performStrictReply(
1411 "Attemping to guess $args[0]'s hostmask...");
1413 # crude hack... crappy Net::IRC
1418 # hopefully this is right.
1419 my $nick = ( keys %{ $cache{nuhInfo} } )[0];
1420 if ( !defined $nick ) {
1421 &performStrictReply(
1422 "couldn't get nuhinfo... adding user without a hostmask."
1427 my $mask = &makeHostMask( $cache{nuhInfo}{$nick}{NUH} );
1429 if ( &userAdd( $nick, $mask ) ) {
1432 &performStrictReply(
1433 "Added $nick with flags $users{$nick}{FLAGS}");
1434 my @hosts = keys %{ $users{$nick}{HOSTS} };
1435 &performStrictReply("hosts: @hosts");
1442 &DEBUG("args => @args");
1443 if ( &userAdd(@args) ) { # success.
1444 &performStrictReply(
1445 "Added $args[0] with flags $users{$args[0]}{FLAGS}");
1446 my @hosts = keys %{ $users{ $args[0] }{HOSTS} };
1447 &performStrictReply("hosts: @hosts");
1451 &performStrictReply("User $args[0] already exists");
1457 if ( &userDel( $args[0] ) ) { # success.
1458 &performStrictReply("Deleted $args[0] successfully.");
1462 &performStrictReply("User $args[0] does not exist.");
1469 if ( $message =~ /^sched$/ ) {
1474 foreach ( keys %sched ) {
1475 next unless ( exists $sched{$_}{TIME} );
1476 $time{ $sched{$_}{TIME} - time() }{$_} = 1;
1479 next unless ( exists $sched{$_}{RUNNING} );
1484 foreach ( sort { $a <=> $b } keys %time ) {
1485 my $str = join( ', ', sort keys %{ $time{$_} } );
1486 &DEBUG("time => $_, str => $str");
1487 push( @time, "$str (" . &Time2String($_) . ")" );
1490 &performStrictReply( &formListReply( 0, "Schedulers: ", @time ) );
1491 &performStrictReply(
1492 &formListReply( 0, "Scheds to run: ", sort @list ) );
1493 &performStrictReply(
1495 0, "Scheds running(should not happen?) ",
1503 # quite a cool hack: reply in DCC CHAT.
1504 $msgType = 'chat' if ( exists $dcc{'CHAT'}{$who} );
1507 $done++ if &parseCmdHook($message);
1508 $done++ unless ( &Modules() );
1511 &DEBUG("running non DCC CHAT command inside DCC CHAT!");
1520 # vim:ts=4:sw=4:expandtab:tw=80