X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=src%2FModules%2FTopic.pl;h=36c1a3f03984fae43c0c5bf1b77ee68425a8a6d9;hb=ccc02c22796957aa2f2951c1146d58645261ad0f;hp=093bdf533ef763a6779e4514f5aa0cfb17500108;hpb=687c9d8ef506268cc98d6e3ed14c7c4aac93d273;p=infobot.git diff --git a/src/Modules/Topic.pl b/src/Modules/Topic.pl index 093bdf5..36c1a3f 100644 --- a/src/Modules/Topic.pl +++ b/src/Modules/Topic.pl @@ -6,8 +6,8 @@ # use strict; -use vars qw(%topiccmp); -no strict "refs"; ### FIXME!!! +use vars qw(%topiccmp %topic %channels %cache %orig); +use vars qw($who $chan $conn $uh $ident); ############################### ##### INTERNAL FUNCTIONS @@ -16,219 +16,207 @@ no strict "refs"; ### FIXME!!! ### # Usage: &topicDecipher(chan); sub topicDecipher { - my $chan = shift; - my @results; + my ($chan) = @_; + my @results; - if (!exists $topic{$chan}{'Current'}) { - &DEBUG("Topic: does not exist for $chan."); - return; - } + return if (!exists $topic{$chan}); + return if (!exists $topic{$chan}{'Current'}); - foreach (split /\|\|/, $topic{$chan}{'Current'}) { - s/^\s+//; - s/\s+$//; + foreach (split /\|\|/, $topic{$chan}{'Current'}) { + s/^\s+//; + s/\s+$//; - # very nice fix to solve the null subtopic problem. - ### if nick contains a space, treat topic as ownerless. - if (/^\(.*?\)$/) { - next unless ($1 =~ /\s/); - } + # very nice fix to solve the null subtopic problem. + # if nick contains a space, treat topic as ownerless. + if (/^\(.*?\)$/) { + next unless ($1 =~ /\s/); + } - my $subtopic = $_; - my $owner = "Unknown"; - if (/(.*)\s+\((.*?)\)$/) { - $subtopic = $1; - $owner = $2; - } + my $subtopic = $_; + my $owner = 'Unknown'; - if (grep /^\Q$subtopic\E\|\|\Q$owner\E$/, @results) { - &DEBUG("topic: we have found a dupe in the topic, not adding."); - next; - } + if (/(.*)\s+\((.*?)\)$/) { + $subtopic = $1; + $owner = $2; + } - push(@results, "$subtopic||$owner"); - } + if (grep /^\Q$subtopic\E\|\|\Q$owner\E$/, @results) { + &status("Topic: we have found a dupe ($subtopic) in the topic, not adding."); + next; + } - return @results; + push(@results, "$subtopic||$owner"); + } + + return @results; } ### # Usage: &topicCipher(@topics); sub topicCipher { - if (!@_) { - &DEBUG("topicCipher: topic is NULL."); - return; - } + return if (!@_); - my $result; - foreach (@_) { - my ($subtopic, $setby) = split /\|\|/; - - $result .= " || $subtopic"; - next if ($setby eq "" or $setby =~ /unknown/i); + my @topic; + foreach (@_) { + my ($subtopic, $setby) = split /\|\|/; - $result .= " (" . $setby . ")"; - } + if ($param{'topicAuthor'} eq '1' and (!$setby =~ /^(unknown|)$/i)) { + push(@topic, "$subtopic ($setby)"); + } else { + push(@topic, "$subtopic"); + } + } - return substr($result, 4); + return join(' || ', @topic); } ### -# Usage: &topicNew($chan, $topic, $updateMsg, $topicUpdate); +# Usage: &topicNew($chan, $topic, $updateMsg); sub topicNew { - my ($chan, $topic, $updateMsg, $topicUpdate) = @_; - my $maxlen = 470; - - &DEBUG("topic: chan{$chan} is +t.") if ($channels{$chan}{t}); - &DEBUG("topic: chan{$chan} is -t.") unless ($channels{$chan}{t}); - &DEBUG("topic: I have +o.") if ($channels{$chan}{o}{$ident}); - &DEBUG("topic: I don't have +o.") unless ($channels{$chan}{o}{$ident}); - - if ($channels{$chan}{t} and !$channels{$chan}{o}{$ident}) { - &msg($who, "error: cannot change topic without ops. (channel is +t) :("); - return 0; - } - - if (defined $topiccmp{$chan} and $topiccmp{$chan} eq $topic) { - &msg($who, "warning: action had no effect on topic; no change required."); - return 0; - } - - # bail out if the new topic is too long. - my $newlen = length($chan.$topic); - if ($newlen > $maxlen) { - &msg($who, "new topic will be too long. ($newlen > $maxlen)"); - return 0; - } - - $topic{$chan}{'Current'} = $topic; - - # notification that the topic was altered. - if (!$topicUpdate) { # for cached changes with '-'. - &performReply("okay"); + my ($chan, $topic, $updateMsg) = @_; + my $maxlen = 470; + + if ($channels{$chan}{t} and !$channels{$chan}{o}{$ident}) { + &msg($who, "error: cannot change topic without ops. (channel is +t) :("); + return 0; + } + + if (defined $topiccmp{$chan} and $topiccmp{$chan} eq $topic) { + &msg($who, "warning: action had no effect on topic; no change required."); + return 0; + } + + # bail out if the new topic is too long. + my $newlen = length($chan.$topic); + if ($newlen > $maxlen) { + &msg($who, "new topic will be too long. ($newlen > $maxlen)"); + return 0; + } + + $topic{$chan}{'Current'} = $topic; + + if ($cache{topicNotUpdate}{$chan}) { + &msg($who, "done. 'flush' to finalize changes."); + delete $cache{topicNotUpdate}{$chan}; + return 1; + } + + if (defined $updateMsg && $updateMsg ne '') { + &msg($who, $updateMsg); + } + + $topic{$chan}{'Last'} = $topic; + $topic{$chan}{'Who'} = $orig{who}."!".$uh; + $topic{$chan}{'Time'} = time(); + + if ($topic) { + $conn->topic($chan, $topic); + &topicAddHistory($chan, $topic); + } else { + $conn->topic($chan, ' '); + } + return 1; - } - - if ($updateMsg ne "") { - &msg($who, $updateMsg); - } - - $topic{$chan}{'Last'} = $topic; - $topic{$chan}{'Who'} = $orig{who}."!".$uh; - $topic{$chan}{'Time'} = time(); - rawout("TOPIC $chan :$topic"); - &topicAddHistory($chan,$topic); - return 1; } ### # Usage: &topicAddHistory($chan,$topic); sub topicAddHistory { - my ($chan, $topic) = @_; - my $dupe = 0; + my ($chan, $topic) = @_; + my $dupe = 0; - return 1 if ($topic eq ""); # required fix. + return 1 if ($topic eq ''); # required fix. - foreach (@{ $topic{$chan}{'History'} }) { - next if ($_ ne "" and $_ ne $topic); - # checking length is required. + foreach (@{ $topic{$chan}{'History'} }) { + next if ($_ ne '' and $_ ne $topic); + # checking length is required. - $dupe++; - last; - } + # slightly weird to put a return statement in a loop. + return 1; + } - return 1 if $dupe; + # WTF IS THIS FOR? - my @topics = @{ $topic{$chan}{'History'} }; - unshift(@topics, $topic); - pop(@topics) while (scalar @topics > 6); - $topic{$chan}{'History'} = \@topics; + my @topics = @{ $topic{$chan}{'History'} }; + unshift(@topics, $topic); + pop(@topics) while (scalar @topics > 6); + $topic{$chan}{'History'} = \@topics; - return $dupe; + return $dupe; } ############################### ##### HELPER FUNCTIONS ############################### -### TODO. -# sub topicNew { -# sub topicDelete { -# sub topicList { -# sub topicModify { -# sub topicMove { -# sub topicShuffle { -# sub topicHistory { -# sub topicRestore { -# sub topicRehash { -# sub topicHelp { - -############################### -##### MAIN -############################### +# cmd: add. +sub do_add { + my ($chan, $args) = @_; -### -# Usage: &Topic($cmd, $args); -sub Topic { - my ($chan, $cmd, $args) = @_; - my $topicUpdate = 1; - - if ($cmd =~ /^-(\S+)/) { - $topicUpdate = 0; - $cmd = $1; - } - - if ($cmd =~ /^(add)$/i) { - ### CMD: ADD: - if ($args eq "") { - &help("topic add"); - return $noreply; + if ($args eq '') { + &help('topic add'); + return; } # heh, joeyh. 19990819. -xk if ($who =~ /\|\|/) { - &msg($who, "error: you have an invalid nick, loser!"); - return $noreply; + &msg($who, 'error: you have an invalid nick, loser!'); + return; } + return if ($channels{$chan}{t} and !&hasFlag('T')); + my @prev = &topicDecipher($chan); - my $new = "$args ($orig{who})"; + my $new; + # If bot new to chan and topic is blank, it still got a (owner). This is fix + if ($param{'topicAuthor'} eq '1') { + $new = "$args ($orig{who})"; + } else { + $new = "$args"; + } $topic{$chan}{'What'} = "Added '$args'."; + if (scalar @prev) { - $new = &topicCipher(@prev, sprintf("%s||%s", $args, $who)); + my $str = sprintf("%s||%s", $args, $who); + $new = &topicCipher(@prev, $str); } - &topicNew($chan, $new, "", $topicUpdate); - } elsif ($cmd =~ /^(del|delete|rm|remove|kill|purge)$/i) { - ### CMD: DEL: + &topicNew($chan, $new, ''); +} + +# cmd: delete. +sub do_delete { + my ($chan, $args) = @_; my @subtopics = &topicDecipher($chan); my $topiccount = scalar @subtopics; if ($topiccount == 0) { - &msg($who, "No topic set."); - return $noreply; + &msg($who, 'No topic set.'); + return; } - if ($args eq "") { - &help("topic del"); - return $noreply; + if ($args eq '') { + &help('topic del'); + return; } - $args = ",".$args.","; - $args =~ s/\s+//g; - $args =~ s/(first|1st)/1/i; - $args =~ s/last/$topiccount/i; - $args =~ s/,-(\d+)/,1-$1/; - $args =~ s/(\d+)-,/,$1-$topiccount/; + for ($args) { + $_ = sprintf(",%s,", $args); + s/\s+//g; + s/(first|1st)/1/i; + s/last/$topiccount/i; + s/,-(\d+)/,1-$1/; + s/(\d+)-,/,$1-$topiccount/; + } if ($args !~ /[\,\-\d]/) { &msg($who, "error: Invalid argument ($args)."); - return $noreply; + return; } - foreach (split ",", $args) { - next if ($_ eq ""); - my @delete; + my @delete; + foreach (split ',', $args) { + next if ($_ eq ''); # change to hash list instead of array? if (/^(\d+)-(\d+)$/) { @@ -240,25 +228,28 @@ sub Topic { push(@delete, $1); } else { &msg($who, "error: Invalid sub-argument ($_)."); - return $noreply; + return; } - $topic{$chan}{'What'} = "Deleted ".join("/",@delete); + $topic{$chan}{'What'} = 'Deleted '.join("/",@delete); + } - foreach (@delete) { - if ($_ > $topiccount || $_ < 1) { + foreach (@delete) { + if ($_ > $topiccount || $_ < 1) { &msg($who, "error: argument out of range. (max: $topiccount)"); - return $noreply; - } - # skip if already deleted. - # only checked if x-y range is given. - next unless (defined($subtopics[$_-1])); - - my ($subtopic,$whoby) = split('\|\|', $subtopics[$_-1]); - $whoby = "unknown" if ($whoby eq ""); - &msg($who, "Deleting topic: $subtopic ($whoby)"); - undef $subtopics[$_-1]; + return; } + + # skip if already deleted. + # only checked if x-y range is given. + next unless (defined($subtopics[$_-1])); + + my ($subtopic,$whoby) = split('\|\|', $subtopics[$_-1]); + + $whoby = 'unknown' if ($whoby eq ''); + + &msg($who, "Deleting topic: $subtopic ($whoby)"); + undef $subtopics[$_-1]; } my @newtopics; @@ -267,14 +258,17 @@ sub Topic { push(@newtopics, $_); } - &topicNew($chan, &topicCipher(@newtopics), "", $topicUpdate); + &topicNew($chan, &topicCipher(@newtopics), ''); +} + +# cmd: list +sub do_list { + my ($chan, $args) = @_; + my @topics = &topicDecipher($chan); - } elsif ($cmd =~ /^list$/i) { - ### CMD: LIST: - my @topics = &topicDecipher($chan); if (!scalar @topics) { &msg($who, "No topics for \002$chan\002."); - return $noreply; + return; } &msg($who, "Topics for \002$chan\002:"); @@ -284,18 +278,25 @@ sub Topic { foreach (@topics) { my ($subtopic, $setby) = split /\|\|/; - &msg($who, sprintf(" %d. \002[\002%-10s\002]\002 %s", - $i, $setby, $subtopic)); + my $str = sprintf(" %d. [%-10s] %s", $i, $setby, $subtopic); + # is there a better way of doing this? + $str =~ s/ (\[)/ \002$1/g; + $str =~ s/ (\])/ \002$1/g; + + &msg($who, $str); $i++; } + &msg($who, "End of Topics."); +} - } elsif ($cmd =~ /^(mod|modify|change|alter)$/i) { - ### CMD: MOD: +# cmd: modify. +sub do_modify { + my ($chan, $args) = @_; - if ($args eq "") { - &help("topic mod"); - return $noreply; + if ($args eq '') { + &help('topic mod'); + return; } # a warning message instead of halting. we kind of trust the user now. @@ -307,199 +308,269 @@ sub Topic { # SAR patch. mu++ if ($args =~ m|^\s*s([/,#])(.+?)\1(.*?)\1([a-z]*);?\s*$|) { - my ($delim, $op, $np, $flags) = ($1,quotemeta $2,$3,$4); + my ($delim, $op, $np, $flags) = ($1,$2,$3,$4); if ($flags !~ /^(g)?$/) { - &msg($who, "error: Invalid flags to regex."); - return $noreply; + &msg($who, "error: Invalid flags to regex."); + return; } my $topic = $topic{$chan}{'Current'}; - if (($flags eq "g" and $topic =~ s/$op/$np/g) || - ($flags eq "" and $topic =~ s/$op/$np/)) { + ### TODO: use m### to make code safe! + if (($flags eq 'g' and $topic =~ s/\Q$op\E/$np/g) || + ($flags eq '' and $topic =~ s/\Q$op\E/$np/) + ) { - $_ = "Modifying topic with sar s/$op/$np/."; - &topicNew($chan, $topic, $_, $topicUpdate); + $_ = "Modifying topic with sar s/$op/$np/."; + &topicNew($chan, $topic, $_); } else { - &msg($who, "warning: regex not found in topic."); + &msg($who, "warning: regex not found in topic."); } - return $noreply; + + return; } &msg($who, "error: Invalid regex. Try s/1/2/, s#3#4#..."); +} - } elsif ($cmd =~ /^(mv|move)$/i) { - ### CMD: MV: +# cmd: move. +sub do_move { + my ($chan, $args) = @_; - if ($args eq "") { - &help("topic mv"); - return $noreply; + if ($args eq '') { + &help('topic mv'); + return; } + my ($from, $action, $to); + # better way of doing this? if ($args =~ /^(first|last|\d+)\s+(before|after|swap)\s+(first|last|\d+)$/i) { - my ($from, $action, $to) = ($1,$2,$3); - my @subtopics = &topicDecipher($chan); - my @newtopics; - my $topiccount = scalar @subtopics; - - if ($topiccount == 1) { - &msg($who, "error: impossible to move the only subtopic, dumbass."); - return $noreply; - } + ($from, $action, $to) = ($1,$2,$3); + } else { + &msg($who, "Invalid arguments."); + return; + } - # Is there an easier way to do this? - $from =~ s/first/1/i; - $to =~ s/first/1/i; - $from =~ s/last/$topiccount/i; - $to =~ s/last/$topiccount/i; + my @subtopics = &topicDecipher($chan); + my @newtopics; + my $topiccount = scalar @subtopics; - if ($from > $topiccount || $to > $topiccount || $from < 1 || $to < 1) { - &msg($who, "error: or is out of range."); - return $noreply; - } + if ($topiccount == 1) { + &msg($who, "error: impossible to move the only subtopic, dumbass."); + return; + } - if ($from == $to) { - &msg($who, "error: and are the same."); - return $noreply; - } + # Is there an easier way to do this? + $from =~ s/first/1/i; + $to =~ s/first/1/i; + $from =~ s/last/$topiccount/i; + $to =~ s/last/$topiccount/i; - $topic{$chan}{'What'} = "Move $from to $to"; + if ($from > $topiccount || $to > $topiccount || $from < 1 || $to < 1) { + &msg($who, "error: or is out of range."); + return; + } - if ($action =~ /^(swap)$/i) { - my $tmp = $subtopics[$to - 1]; - $subtopics[$to - 1] = $subtopics[$from - 1]; - $subtopics[$from - 1] = $tmp; + if ($from == $to) { + &msg($who, "error: and are the same."); + return; + } - $_ = "Swapped #\002$from\002 with #\002$to\002."; - &topicNew($chan, &topicCipher(@subtopics), $_, $topicUpdate); - return $noreply; - } + $topic{$chan}{'What'} = "Move $from to $to"; - # action != swap: - # Is there a better way to do this? guess not. - my $i = 1; - my $subtopic = $subtopics[$from - 1]; - foreach (@subtopics) { - my $j = $i*2 - 1; - $newtopics[$j] = $_ if ($i != $from); - $i++; - } + if ($action =~ /^(swap)$/i) { + my $tmp = $subtopics[$to - 1]; + $subtopics[$to - 1] = $subtopics[$from - 1]; + $subtopics[$from - 1] = $tmp; - if ($action =~ /^(before|b4)$/i) { - $newtopics[$to*2-2] = $subtopic; - } else { - # action =~ /after/. - $newtopics[$to*2] = $subtopic; - } + $_ = "Swapped #\002$from\002 with #\002$to\002."; + &topicNew($chan, &topicCipher(@subtopics), $_); + return; + } - undef @subtopics; # lets reuse this array. - foreach (@newtopics) { - next if ($_ eq ""); - push(@subtopics, $_); - } + # action != swap: + # Is there a better way to do this? guess not. + my $i = 1; + my $subtopic = $subtopics[$from - 1]; + foreach (@subtopics) { + my $j = $i*2 - 1; + $newtopics[$j] = $_ if ($i != $from); + $i++; + } - $_ = "Moved #\002$from\002 $action #\002$to\002."; - &topicNew($chan, &topicCipher(@subtopics), $_, $topicUpdate); + if ($action =~ /^(before|b4)$/i) { + $newtopics[$to*2-2] = $subtopic; + } else { + # action =~ /after/. + $newtopics[$to*2] = $subtopic; + } - return $noreply; + undef @subtopics; # lets reuse this array. + foreach (@newtopics) { + next if (!defined $_ or $_ eq ''); + push(@subtopics, $_); } - &msg($who, "Invalid arguments."); + $_ = "Moved #\002$from\002 $action #\002$to\002."; + &topicNew($chan, &topicCipher(@subtopics), $_); +} - } elsif ($cmd =~ /^shuffle$/i) { - ### CMD: SHUFFLE: - my @subtopics = &topicDecipher($chan); +# cmd: shuffle. +sub do_shuffle { + my ($chan, $args) = @_; + my @subtopics = &topicDecipher($chan); my @newtopics; - $topic{$chan}{'What'} = "shuffled"; + $topic{$chan}{'What'} = 'shuffled'; foreach (&makeRandom(scalar @subtopics)) { push(@newtopics, $subtopics[$_]); } $_ = "Shuffling the bag of lollies."; - &topicNew($chan, &topicCipher(@newtopics), $_, $topicUpdate); + &topicNew($chan, &topicCipher(@newtopics), $_); +} - } elsif ($cmd =~ /^(history)$/i) { - ### CMD: HISTORY: - if (!scalar @{$topic{$chan}{'History'}}) { +# cmd: history. +sub do_history { + my ($chan, $args) = @_; + + if (!scalar @{ $topic{$chan}{'History'} }) { &msg($who, "Sorry, no topics in history list."); - return $noreply; + return; } &msg($who, "History of topics on \002$chan\002:"); - for (1 .. scalar @{$topic{$chan}{'History'}}) { - my $topic = ${$topic{$chan}{'History'}}[$_-1]; + for (1 .. scalar @{ $topic{$chan}{'History'} }) { + my $topic = ${ $topic{$chan}{'History'} }[$_-1]; &msg($who, " #\002$_\002: $topic"); # To prevent excess floods. sleep 1 if (length($topic) > 160); } + &msg($who, "End of list."); +} + +# cmd: restore. +sub do_restore { + my ($chan, $args) = @_; - } elsif ($cmd =~ /^restore$/i) { - ### CMD: RESTORE: - if ($args eq "") { - &help("topic restore"); - return $noreply; + if ($args eq '') { + &help('topic restore'); + return; } $topic{$chan}{'What'} = "Restore topic $args"; # following needs to be verified. if ($args =~ /^last$/i) { - if (${$topic{$chan}{'History'}}[0] eq $topic{$chan}{'Current'}) { + if (${ $topic{$chan}{'History'} }[0] eq $topic{$chan}{'Current'}) { &msg($who,"error: cannot restore last topic because it's mine."); - return $noreply; + return; } $args = 1; } - if ($args =~ /\d+/) { - if ($args > $#{$topic{$chan}{'History'}} || $args < 1) { - &msg($who, "error: argument is out of range."); - return $noreply; - } - - $_ = "Changing topic according to request."; - &topicNew($chan, ${$topic{$chan}{'History'}}[$args-1], $_, $topicUpdate); + if ($args !~ /\d+/) { + &msg($who, "error: argument is not positive integer."); + return; + } - return $noreply; + if ($args > $#{ $topic{$chan}{'History'} } || $args < 1) { + &msg($who, "error: argument is out of range."); + return; } - &msg($who, "error: argument is not positive integer."); + $_ = "Changing topic according to request."; + &topicNew($chan, ${ $topic{$chan}{'History'} }[$args-1], $_); +} + +# cmd: rehash. +sub do_rehash { + my ($chan) = @_; - } elsif ($cmd =~ /^rehash$/i) { - ### CMD: REHASH. $_ = "Rehashing topic..."; - $topic{$chan}{'What'} = "Rehash"; + $topic{$chan}{'What'} = 'Rehash'; &topicNew($chan, $topic{$chan}{'Current'}, $_, 1); +} + +# cmd: info. +sub do_info { + my ($chan) = @_; - } elsif ($cmd =~ /^info$/i) { - ### CMD: INFO. my $reply = "no topic info."; if (exists $topic{$chan}{'Who'} and exists $topic{$chan}{'Time'}) { $reply = "topic on \002$chan\002 was last set by ". $topic{$chan}{'Who'}. ". This was done ". - &Time2String(time() - $topic{$chan}{'Time'}) ." ago."; + &Time2String(time() - $topic{$chan}{'Time'}) .' ago'. + ". Length: ".length($topic{$chan}{'Current'}); my $change = $topic{$chan}{'What'}; - $reply .= "Change => $change" if (defined $change); + $reply .= ". Change => $change" if (defined $change); } &performStrictReply($reply); - } else { - ### CMD: HELP: - if ($cmd ne "" and $cmd !~ /^help/i) { - &msg($who, "Invalid command [$cmd]."); - &msg($who, "Try 'help topic'."); - return $noreply; +} + +############################### +##### MAIN +############################### + +### +# Usage: &Topic($cmd, $args); +sub Topic { + my ($chan, $cmd, $args) = @_; + + if ($cmd =~ /^-(\S+)/) { + $cache{topicNotUpdate}{$chan} = 1; + $cmd = $1; } - &help("topic"); - } + if ($cmd =~ /^(add)$/i) { + &do_add($chan, $args); + + } elsif ($cmd =~ /^(del|delete|rm|remove|kill|purge)$/i) { + &do_delete($chan, $args); - return $noreply; + } elsif ($cmd =~ /^list$/i) { + &do_list($chan, $args); + + } elsif ($cmd =~ /^(mod|modify|change|alter)$/i) { + &do_modify($chan, $args); + + } elsif ($cmd =~ /^(mv|move)$/i) { + &do_move($chan, $args); + + } elsif ($cmd =~ /^shuffle$/i) { + &do_shuffle($chan, $args); + + } elsif ($cmd =~ /^(history)$/i) { + &do_history($chan, $args); + + } elsif ($cmd =~ /^restore$/i) { + &do_restore($chan, $args); + + } elsif ($cmd =~ /^(flush|rehash)$/i) { + &do_rehash($chan); + + } elsif ($cmd =~ /^info$/i) { + &do_info($chan); + + } else { + ### HELP: + if ($cmd ne '' and $cmd !~ /^help/i) { + &msg($who, "Invalid command [$cmd]."); + &msg($who, "Try 'help topic'."); + return; + } + + &help('topic'); + } + + return; } 1; + +# vim:ts=4:sw=4:expandtab:tw=80