2 # UserDCC.pl: User Commands, DCC CHAT.
4 # Version: v0.2 (20010119)
5 # Created: 20000707 (from UserExtra.pl)
8 if (&IsParam("useStrict")) { use strict; }
16 if ($message =~ /^(exit|quit)$/i) {
17 # do ircII clients support remote close? if so, cool!
18 &status("userDCC: quit called. FIXME");
20 &status("userDCC: after dcc_close!");
26 if ($message =~ /^who$/) {
27 my $count = scalar(keys %{ $dcc{'CHAT'} });
28 my $dccCHAT = $message;
30 &pSReply("Start of who ($count users).");
31 foreach (keys %{ $dcc{'CHAT'} }) {
34 &pSReply("End of who.");
39 ### for those users with enough flags.
41 if ($message =~ /^tellme(\s+(.*))?$/i) {
43 if ($args =~ /^\s*$/) {
48 my $result = &doQuestion($args);
55 if ($message =~ /^4op(\s+($mask{chan}))?$/i) {
56 return unless (&hasFlag("o"));
65 if (!$channels{$chan}{'o'}{$ident}) {
66 &msg($who, "i don't have ops on $chan to do that.");
70 # on non-4mode(<4) servers, this may be exploited.
71 if ($channels{$chan}{'o'}{$who}) {
72 rawout("MODE $chan -o+o-o+o". (" $who" x 4));
74 rawout("MODE $chan +o-o+o-o". (" $who" x 4));
81 if ($message =~ /^backlog(\s+(.*))?$/i) {
82 return unless (&hasFlag("o"));
83 return unless (&hasParam("backlog"));
85 my $max = $param{'backlog'};
90 } elsif ($num !~ /^\d+/) {
91 &msg($who, "error: argument is not positive integer.");
93 } elsif ($num > $max or $num < 0) {
94 &msg($who, "error: argument is out of range (max $max).");
98 &msg($who, "Start of backlog...");
100 sleep 1 if ($_ % 4 == 0 and $_ != 0);
101 $conn->privmsg($who, "[".($_+1)."]: $backlog[$max-$num+$_]");
103 &msg($who, "End of backlog.");
109 if ($message =~ /^dumpvars$/i) {
110 return unless (&hasFlag("o"));
111 return unless (&IsParam("dumpvars"));
113 &status("Dumping all variables...");
120 if ($message =~ /^kick(\s+(\S+)(\s+(\S+))?)?/) {
121 return unless (&hasFlag("o"));
122 my ($nick,$chan) = (lc $2,lc $4);
129 if (&validChan($chan) == 0) {
130 &msg($who,"error: invalid channel \002$chan\002");
134 if (&IsNickInChan($nick,$chan) == 0) {
135 &msg($who,"$nick is not in $chan.");
145 if ($message =~ /^mode(\s+(.*))?$/) {
146 return unless (&hasFlag("n"));
147 my ($chan,$mode) = split /\s+/,$2,2;
154 if (&validChan($chan) == 0) {
155 &msg($who,"error: invalid channel \002$chan\002");
159 if (!$channels{$chan}{o}{$ident}) {
160 &msg($who,"error: don't have ops on \002$chan\002");
170 if ($message =~ /^part(\s+(\S+))?$/i) {
171 return unless (&hasFlag("o"));
174 if ($jchan !~ /^$mask{chan}$/) {
175 &msg($who, "error, invalid chan.");
180 if (!&validChan($jchan)) {
181 &msg($who, "error, I'm not on that chan.");
185 &msg($jchan, "Leaving. (courtesy of $who).");
190 # lobotomy. sometimes we want the bot to be _QUIET_.
191 if ($message =~ /^(lobotomy|bequiet)$/i) {
192 return unless (&hasFlag("o"));
195 &performReply("i'm already lobotomized");
197 &performReply("i have been lobotomized");
205 if ($message =~ /^(unlobotomy|benoisy)$/i) {
206 return unless (&hasFlag("o"));
209 &performReply("i have been unlobotomized, woohoo");
211 delete $cache{lobotomy};
212 # undef $cache{lobotomy}; # ??
214 &performReply("i'm not lobotomized");
221 if ($message =~ /^op(\s+(.*))?$/i) {
222 return unless (&hasFlag("o"));
227 if ($opee =~ /^(\S+)\s+(\S+)$/) {
230 if (!&validChan($2)) {
231 &msg($who,"error: invalid chan ($2).");
235 &msg($who,"error: invalid params.");
239 @chans = keys %channels;
245 next unless (&IsNickInChan($opee,$_));
247 if ($channels{$_}{'o'}{$opee}) {
248 &pSReply("op: $opee already has ops on $_");
253 &pSReply("opping $opee on $_");
258 &pSReply("op: opped on all possible channels.");
260 &DEBUG("op: found => '$found'.");
261 &DEBUG("op: op => '$op'.");
268 if ($message =~ /^deop(\s+(.*))?$/i) {
269 return unless (&hasFlag("o"));
274 if ($opee =~ /^(\S+)\s+(\S+)$/) {
277 if (!&validChan($2)) {
278 &msg($who,"error: invalid chan ($2).");
282 &msg($who,"error: invalid params.");
286 @chans = keys %channels;
292 next unless (&IsNickInChan($opee,$_));
294 if (!exists $channels{$_}{'o'}{$opee}) {
295 &status("deop: $opee already has no ops on $_");
300 &status("deopping $opee on $_ at ${who}'s request");
305 &status("deop: deopped on all possible channels.");
307 &DEBUG("deop: found => '$found'.");
308 &DEBUG("deop: op => '$op'.");
315 if ($message =~ s/^say\s+(\S+)\s+(.*)//) {
316 return unless (&hasFlag("o"));
317 my ($chan,$msg) = (lc $1, $2);
318 &DEBUG("chan => '$1', msg => '$msg'.");
320 if (&validChan($chan)) {
323 &msg($who,"i'm not on \002$1\002, sorry.");
329 if ($message =~ /^die$/) {
330 return unless (&hasFlag("n"));
334 &status("Dying by $who\'s request");
338 # global factoid substitution.
339 if ($message =~ m|^s([/,#])(.+?)\1(.*?)\1;?\s*$|) {
340 my ($delim,$op,$np) = ($1, $2, $3);
341 return unless (&hasFlag("n"));
342 ### TODO: support flags to do full-on global.
345 if ($np =~ /$delim/) {
346 &performReply("looks like you used the delimiter too many times. You may want to use a different delimiter, like ':' or '#'.");
350 ### TODO: fix up $op to support mysql/pgsql/dbm(perl)
351 ### TODO: => add db/sql specific function to fix this.
352 my @list = &searchTable("factoids", "factoid_key",
353 "factoid_value", $op);
356 &performReply("Expression didn't match anything.");
360 if (scalar @list > 100) {
361 &performReply("regex found more than 100 matches... not doing.");
365 &status("gsubst: going to alter ".scalar(@list)." factoids.");
366 &performReply("going to alter ".scalar(@list)." factoids.");
372 next if (&IsLocked($faqtoid) == 1);
373 my $result = &getFactoid($faqtoid);
375 &DEBUG("was($faqtoid) => '$was'.");
378 # we could support global local (once off).
379 if ($result =~ s/\Q$op/$np/gi) {
380 if (length $result > $param{'maxDataSize'}) {
381 &performReply("that's too long (or was long)");
384 &setFactInfo($faqtoid, "factoid_value", $result);
385 &status("update: '$faqtoid' =is=> '$result'; was '$was'");
387 &WARN("subst: that's weird... thought we found the string ($op) in '$faqtoid'.");
393 &ERROR("Some warnings/errors?");
396 &performReply("Ok... did s/$op/$np/ for ".
397 (scalar(@list) - $error)." factoids");
403 if ($message =~ /^jump(\s+(\S+))?$/i) {
404 return unless (&hasFlag("n"));
412 if ($2 =~ /^(\S+)(:(\d+))?$/) {
416 &msg($who,"invalid format.");
420 &status("jumping servers... $server...");
421 &rawout("QUIT :jumping to $server");
423 if (&irc($server,$port) == 0) {
429 if ($message =~ /^reload$/i) {
430 return unless (&hasFlag("n"));
432 &status("USER reload $who");
433 &pSReply("reloading...");
435 &pSReply("reloaded.");
441 if ($message =~ /^reset$/i) {
442 return unless (&hasFlag("n"));
444 &msg($who,"resetting...");
446 foreach ( keys %channels, keys %chanconf ) {
447 &DEBUG("reset: c => $c");
448 next if (grep /^\Q$_\E$/i, @done);
450 &DEBUG("reset: should part... c => $c");
456 &DEBUG("before clearircvars");
458 &DEBUG("before joinnextchan");
460 &DEBUG("after joinnextchan");
462 &status("USER reset $who");
463 &msg($who,"resetted");
469 if ($message =~ /^rehash$/) {
470 return unless (&hasFlag("n"));
472 &msg($who,"rehashing...");
474 &status("USER rehash $who");
475 &msg($who,"rehashed");
481 ##### USER//CHAN SPECIFIC CONFIGURATION COMMANDS
484 if ($message =~ /^chaninfo(\s+(.*))?$/) {
485 my @args = split /[\s\t]+/, $2; # hrm.
487 if (scalar @args != 1) {
492 if (!exists $chanconf{$args[0]}) {
493 &pSReply("no such channel $args[0]");
497 &pSReply("showing channel conf.");
498 foreach (sort keys %{ $chanconf{$args[0]} }) {
499 &pSReply("$chan: $_ => $chanconf{$args[0]}{$_}");
501 &pSReply("End of chaninfo.");
507 if ($message =~ /^(chanset|\+chan)(\s+(.*?))?$/) {
512 if (!defined $args) {
518 while ($args =~ s/^($mask{chan})\s*//) {
522 if (!scalar @chans) {
523 push(@chans, "_default");
527 my($what,$val) = split /[\s\t]+/, $args, 2;
529 ### TODO: "cannot set values without +m".
530 return unless (&hasFlag("n"));
533 if (defined $what and $what !~ /^[-+]/ and !defined $val and $no_chan) {
534 &pSReply("Showing $what values on all channels...");
537 foreach (keys %chanconf) {
538 my $val = $chanconf{$_}{$what} || "NOT-SET";
542 foreach (keys %vals) {
543 &pSReply(" $what = $_: ".join(' ', keys %{ $vals{$_} } ) );
546 &pSReply("End of list.");
551 ### TODO: move to UserDCC again.
552 if ($cmd eq "chanset" and !defined $what) {
553 &DEBUG("showing channel conf.");
555 foreach $chan ($chan, "_default") {
556 &pSReply("chan: $chan");
557 ### TODO: merge 2 or 3 per line.
560 foreach (sort keys %{ $chanconf{$chan} }) {
561 my $newstr = join(', ', @items);
562 if (length $newstr > 60) {
567 push(@items, "$_ => $chanconf{$chan}{$_}");
569 &pSReply(" $str") if (@items);
574 $cache{confvars}{$what} = $val;
578 &chanSet($cmd, $_, $what, $val);
584 if ($message =~ /^(chanunset|\-chan)(\s+(.*))?$/) {
585 return unless (&hasFlag("n"));
589 if (!defined $args) {
596 if ($args =~ s/^(\-)?($mask{chan})\s*//) {
598 $delete = ($1) ? 1 : 0;
599 &DEBUG("chan => $chan.");
601 &VERB("no chan arg; setting to default.",2);
606 if (!exists $chanconf{$chan}) {
607 &pSReply("no such channel $chan");
613 if (!&getChanConf($args,$chan)) {
614 &pSReply("$args does not exist for $chan");
618 my @chans = &ChanConfList($args);
619 &DEBUG("scalar chans => ".scalar(@chans) );
620 if (scalar @chans == 1 and $chans[0] eq "_default" and !$no_chan) {
621 &psReply("ok, $args was set only for _default; unsetting for _defaul but setting for other chans.");
623 my $val = $chanconf{$_}{_default};
624 foreach (keys %chanconf) {
625 $chanconf{$_}{$args} = $val;
627 delete $chanconf{_default}{$args};
628 $cache{confvars}{$args} = 0;
634 if ($no_chan and !exists($chanconf{_default}{$args})) {
635 &pSReply("ok, $args for _default does not exist, removing from all chans.");
637 foreach (keys %chanconf) {
638 next unless (exists $chanconf{$_}{$args});
639 &DEBUG("delete chanconf{$_}{$args};");
640 delete $chanconf{$_}{$args};
642 $cache{confvars}{$args} = 0;
648 &pSReply("Unsetting channel ($chan) option $args. (was $chanconf{$chan}{$args})");
649 delete $chanconf{$chan}{$args};
655 &pSReply("Deleting channel $chan for sure!");
656 $utime_chanfile = time();
660 &pSReply("Leaving $chan...");
662 delete $chanconf{$chan};
664 &pSReply("Prefix channel with '-' to delete for sure.");
670 if ($message =~ /^newpass(\s+(.*))?$/) {
671 my(@args) = split /[\s\t]+/, $2 || '';
673 if (scalar @args != 1) {
678 my $u = &getUser($who);
679 my $crypt = &mkcrypt($args[0]);
681 &pSReply("Set your passwd to '$crypt'");
682 $users{$u}{PASS} = $crypt;
684 $utime_userfile = time();
690 if ($message =~ /^chpass(\s+(.*))?$/) {
691 my(@args) = split /[\s\t]+/, $2 || '';
698 if (!&IsUser($args[0])) {
699 &pSReply("user $args[0] is not valid.");
703 my $u = &getUser($args[0]);
705 &pSReply("Internal error, u = NULL.");
709 if (scalar @args == 1) { # del pass.
710 if (!&IsFlag("n") and $who !~ /^\Q$verifyUser\E$/i) {
711 &pSReply("cannot remove passwd of others.");
715 if (!exists $users{$u}{PASS}) {
716 &pSReply("$u does not have pass set anyway.");
720 &pSReply("Deleted pass from $u.");
722 $utime_userfile = time();
725 delete $users{$u}{PASS};
730 my $crypt = &mkcrypt($args[1]);
731 &pSReply("Set $u's passwd to '$crypt'");
732 $users{$u}{PASS} = $crypt;
734 $utime_userfile = time();
740 if ($message =~ /^chattr(\s+(.*))?$/) {
741 my(@args) = split /[\s\t]+/, $2 || '';
749 if ($args[0] =~ /^$mask{nick}$/i) { # <nick>
750 $user = &getUser($args[0]);
753 $user = &getUser($who);
754 &DEBUG("user $who... nope.") unless (defined $user);
755 $user = &getUser($verifyUser);
759 if (!defined $user) {
760 &pSReply("user does not exist.");
764 my $flags = $users{$user}{FLAGS};
765 if (!defined $chflag) {
766 &pSReply("Flags for $user: $flags");
770 &DEBUG("who => $who");
771 &DEBUG("verifyUser => $verifyUser");
772 if (!&IsFlag("n") and $who !~ /^\Q$verifyUser\E$/i) {
773 &pSReply("cannto change attributes of others.");
779 foreach (split //, $chflag) {
780 if ($_ eq "+") { $state = 1; next; }
781 if ($_ eq "-") { $state = 0; next; }
783 if (!defined $state) {
784 &pSReply("no initial + or - was found in attr.");
789 next if ($flags =~ /\Q$_\E/);
792 if (&IsParam("owner")
793 and $param{owner} =~ /^\Q$user\E$/i
794 and $flags =~ /[nmo]/
796 &pSReply("not removing flag $_ for $user.");
799 next unless ($flags =~ s/\Q$_\E//);
806 $utime_userfile = time();
808 &pSReply("Current flags: $flags");
809 $users{$user}{FLAGS} = $flags;
811 &pSReply("No flags changed: $flags");
817 if ($message =~ /^chnick(\s+(.*))?$/) {
818 my(@args) = split /[\s\t]+/, $2 || '';
820 if ($who eq "_default") {
821 &WARN("$who or verifyuser tried to run chnick.");
825 if (!scalar @args or scalar @args > 2) {
830 if (scalar @args == 1) { # 1
831 $user = &getUser($who);
832 &DEBUG("nope, not $who.") unless (defined $user);
833 $user ||= &getUser($verifyUser);
836 $user = &getUser($args[0]);
840 if (!defined $user) {
841 &pSReply("user $who or $args[0] does not exist.");
845 if ($user =~ /^\Q$chnick\E$/i) {
846 &pSReply("user == chnick. why should I do that?");
850 if (&getUser($chnick)) {
851 &pSReply("user $chnick is already used!");
855 if (!&IsFlag("n") and $who !~ /^\Q$verifyUser\E$/i) {
856 &pSReply("cannto change nick of others.");
857 return "REPLY" if ($who eq "_default");
861 foreach (keys %{ $users{$user} }) {
862 $users{$chnick}{$_} = $users{$user}{$_};
863 delete $users{$user}{$_};
865 undef $users{$user}; # ???
867 $utime_userfile = time();
870 &pSReply("Changed '$user' to '$chnick' successfully.");
875 if ($message =~ /^([-+])host(\s+(.*))?$/) {
877 my(@args) = split /[\s\t]+/, $3 || '';
878 my $state = ($1 eq "+") ? 1 : 0;
885 if ($who eq "_default") {
886 &WARN("$who or verifyuser tried to run $cmd.");
891 if ($args[0] =~ /^$mask{nick}$/i) { # <nick>
892 return unless (&hasFlag("n"));
893 $user = &getUser($args[0]);
896 # who or verifyUser. FIXME!!!
897 $user = &getUser($who);
901 if (!defined $user) {
902 &pSReply("user $user does not exist.");
906 if (!defined $mask) {
908 &pSReply("Hostmasks for $user: $users{$user}{HOSTS}");
913 if (!&IsFlag("n") and $who !~ /^\Q$verifyUser\E$/i) {
914 &pSReply("cannto change masks of others.");
918 if ($mask !~ /^$mask{nuh}$/) {
919 &pSReply("error: mask ($mask) is not a real hostmask.");
923 my $count = scalar keys %{ $users{$user}{HOSTS} };
926 if (exists $users{$user}{HOSTS}{$mask}) {
927 &pSReply("mask $mask already exists.");
931 ### TODO: override support.
932 $users{$user}{HOSTS}{$mask} = 1;
934 &pSReply("Added $mask to list of masks.");
938 if (!exists $users{$user}{HOSTS}{$mask}) {
939 &pSReply("mask $mask does not exist.");
943 ### TODO: wildcard support. ?
944 delete $users{$user}{HOSTS}{$mask};
946 if (scalar keys %{ $users{$user}{HOSTS} } != $count) {
947 &pSReply("Removed $mask from list of masks.");
949 &pSReply("error: could not find $mask in list of masks.");
954 $utime_userfile = time();
960 if ($message =~ /^([-+])ban(\s+(.*))?$/) {
963 my(@args) = split /[\s\t]+/, $3 || '';
964 my $state = ($1 eq "+") ? 1 : 0;
971 my($mask,$chan,$time,$reason);
973 if ($flatarg =~ s/^($mask{nuh})\s*//) {
976 &DEBUG("arg does not contain nuh mask?");
979 if ($flatarg =~ s/^($mask{chan})\s*//) {
982 $chan = "*"; # _default instead?
985 if ($state == 0) { # delete.
986 my @c = &banDel($mask);
993 &pSReply("Removed $mask from chans: @c");
995 &pSReply("$mask was not found in ban list.");
1006 if ($flatarg =~ s/^(\d+)\s*//) {
1008 &DEBUG("time = $time.");
1010 &pSReply("error: time cannot be negatime?");
1017 if ($flatarg =~ s/^(.*)$//) { # need length?
1021 if (!&IsFlag("n") and $who !~ /^\Q$verifyUser\E$/i) {
1022 &pSReply("cannto change masks of others.");
1026 if ($mask !~ /^$mask{nuh}$/) {
1027 &pSReply("error: mask ($mask) is not a real hostmask.");
1031 if ( &banAdd($mask,$chan,$time,$reason) == 2) {
1032 &pSReply("ban already exists; overwriting.");
1034 &pSReply("Added $mask for $chan (time => $time, reason => $reason)");
1039 if ($message =~ /^whois(\s+(.*))?$/) {
1042 if (!defined $arg) {
1047 my $user = &getUser($arg);
1048 if (!defined $user) {
1049 &pSReply("whois: user $user does not exist.");
1053 ### TODO: better (eggdrop-like) output.
1054 &pSReply("user: $user");
1055 foreach (keys %{ $users{$user} }) {
1056 my $ref = ref $users{$user}{$_};
1058 if ($ref eq "HASH") {
1060 ### DOES NOT WORK???
1061 foreach (keys %{ $users{$user}{$type} }) {
1062 &pSReply(" $type => $_");
1067 &pSReply(" $_ => $users{$user}{$_}");
1069 &pSReply("End of USER whois.");
1074 if ($message =~ /^bans(\s+(.*))?$/) {
1078 if ($arg ne "_default" and !&validChan($arg) ) {
1079 &pSReply("error: chan $chan is invalid.");
1084 if (!scalar keys %bans) {
1085 &pSReply("Ban list is empty.");
1090 &pSReply(" mask: expire, time-added, count, who-by, reason");
1091 foreach $c (keys %bans) {
1092 next unless (!defined $arg or $arg =~ /^\Q$c\E$/i);
1095 foreach (keys %{ $bans{$c} }) {
1096 my $val = $bans{$c}{$_};
1098 if (ref $val eq "ARRAY") {
1099 my @array = @{ $val };
1100 &pSReply(" $_: @array");
1102 &DEBUG("unknown ban: $val");
1106 &pSReply("END of bans.");
1111 if ($message =~ /^banlist(\s+(.*))?$/) {
1114 if (defined $arg and $arg !~ /^$mask_chan$/) {
1115 &pSReply("error: chan $chan is invalid.");
1119 &DEBUG("bans for global or arg => $arg.");
1120 foreach (keys %bans) { #CHANGE!!!
1121 &DEBUG(" $_ => $bans{$_}.");
1124 &DEBUG("End of bans.");
1125 &pSReply("END of bans.");
1130 if ($message =~ /^save$/) {
1131 return unless (&hasFlag("o"));
1135 &News::writeNews() if (&ChanConfList("news"));
1141 $message =~ s/^addignore/+ignore/;
1142 $message =~ s/^(del|un)ignore/-ignore/;
1145 if ($message =~ /^(\+|\-)ignore(\s+(.*))?$/i) {
1146 return unless (&hasFlag("o"));
1147 my $state = ($1 eq "+") ? 1 : 0;
1148 my $str = $1."ignore";
1156 my($mask,$chan,$time,$comment);
1159 if ($args =~ s/^($mask{nuh})\s*//) {
1162 &ERROR("no NUH mask?");
1166 if (!$state) { # delignore.
1167 if ( &ignoreDel($mask) ) {
1168 &pSReply("ok, deleted X ignores.");
1170 &pSReply("could not find $mask in ignore list.");
1180 if ($args =~ s/^($mask{chan}|\*)\s*//) {
1187 if ($args =~ s/^(\d+)\s*//) {
1197 $comment = "added by $who";
1200 if ( &ignoreAdd($mask, $chan, $time, $comment) > 1) {
1201 &pSReply("warn: $mask already in ignore list; written over anyway. FIXME");
1203 &pSReply("added $mask to ignore list.");
1209 if ($message =~ /^ignore(\s+(.*))?$/) {
1213 if ($arg !~ /^$mask{chan}$/) {
1214 &pSReply("error: chan $chan is invalid.");
1218 if (!&validChan($arg)) {
1219 &pSReply("error: chan $arg is invalid.");
1223 &pSReply("Showing bans for $arg only.");
1226 if (!scalar keys %ignore) {
1227 &pSReply("Ignore list is empty.");
1231 ### TODO: proper (eggdrop-like) formatting.
1233 &pSReply(" mask: expire, time-added, who, comment");
1234 foreach $c (keys %ignore) {
1235 next unless (!defined $arg or $arg =~ /^\Q$c\E$/i);
1238 foreach (keys %{ $ignore{$c} }) {
1239 my $ref = ref $ignore{$c}{$_};
1240 if ($ref eq "ARRAY") {
1241 my @array = @{ $ignore{$c}{$_} };
1242 &pSReply(" $_: @array");
1244 &DEBUG("unknown ignore line?");
1248 &pSReply("END of ignore.");
1254 if ($message =~ /^(\+|\-|add|del)user(\s+(.*))?$/i) {
1256 my $strstr = $1."user";
1257 my @args = split /\s+/, $3 || '';
1259 my $state = ($str =~ /^(\+|add)$/) ? 1 : 0;
1261 if (!scalar @args) {
1267 if (scalar @args != 2) {
1268 &pSReply(".+host requires hostmask argument.");
1271 } elsif (scalar @args != 1) {
1272 &pSReply("too many arguments.");
1276 if ($state) { # adduser.
1277 if (scalar @args == 1) {
1278 $args[1] = &getHostMask($args[0]);
1279 &pSReply("Attemping to guess $args[0]'s hostmask...");
1281 # crude hack... crappy Net::IRC
1282 $conn->schedule(5, sub {
1283 # hopefully this is right.
1284 my $nick = (keys %{ $cache{nuhInfo} })[0];
1285 if (!defined $nick) {
1286 &pSReply("couldn't get nuhinfo... adding user without a hostmask.");
1291 my $mask = &makeHostMask( $cache{nuhInfo}{$nick}{NUH} );
1293 if ( &userAdd($nick, $mask) ) { # success.
1294 &pSReply("Added $nick with flags $users{$nick}{FLAGS}");
1295 my @hosts = keys %{ $users{$nick}{HOSTS} };
1296 &pSReply("hosts: @hosts");
1302 &DEBUG("args => @args");
1303 if ( &userAdd(@args) ) { # success.
1304 &pSReply("Added $args[0] with flags $users{$args[0]}{FLAGS}");
1305 my @hosts = keys %{ $users{$args[0]}{HOSTS} };
1306 &pSReply("hosts: @hosts");
1309 &pSReply("User $args[0] already exists");
1314 if ( &userDel($args[0]) ) { # success.
1315 &pSReply("Deleted $args[0] successfully.");
1318 &pSReply("User $args[0] does not exist.");
1325 if ($message =~ /^sched$/) {
1330 foreach (keys %sched) {
1331 next unless (exists $sched{$_}{TIME});
1332 $time{ $sched{$_}{TIME}-time() }{$_} = 1;
1335 next unless (exists $sched{$_}{RUNNING});
1340 foreach (sort { $a <=> $b } keys %time) {
1341 my $str = join(", ", sort keys %{ $time{$_} });
1342 &DEBUG("time => $_, str => $str");
1343 push(@time, "$str (".&Time2String($_).")");
1346 &pSReply( &formListReply(0, "Schedulers: ", @time ) );
1347 &pSReply( &formListReply(0, "Scheds to run: ", sort @list ) );
1348 &pSReply( &formListReply(0, "Scheds running(should not happen?) ", sort @run ) );
1353 # quite a cool hack: reply in DCC CHAT.
1357 $done++ if &parseCmdHook("main", $message);
1358 $done++ if &parseCmdHook("extra", $message);
1359 $done++ unless (&Modules());
1362 &DEBUG("running non DCC CHAT command inside DCC CHAT!");