diff --git a/PBot/AntiFlood.pm b/PBot/AntiFlood.pm index 1c4bd56c..e42d2719 100644 --- a/PBot/AntiFlood.pm +++ b/PBot/AntiFlood.pm @@ -126,10 +126,12 @@ sub whitelisted { } sub whitelist { - my ($self, $from, $nick, $user, $host, $arguments) = @_; - $arguments = lc $arguments; + my ($self, $from, $nick, $user, $host, $arguments, $stuff) = @_; - my ($command, $args) = split /\s+/, $arguments, 2; + my $arglist = $stuff->{arglist}; + $self->{pbot}->{interpreter}->lc_args($arglist); + + my $command = $self->{pbot}->{interpreter}->shift_arg($arglist); return "Usage: whitelist , where commands are: list/show, add, remove, set, unset" if not defined $command; @@ -153,7 +155,7 @@ sub whitelist { return $text; } when ("set") { - my ($channel, $mask, $flag, $value) = split /\s+/, $args, 4; + my ($channel, $mask, $flag, $value) = $self->{pbot}->{interpreter}->split_args($arglist, 4); return "Usage: whitelist set [flag] [value]" if not defined $channel or not defined $mask; if (not exists $self->{whitelist}->hash->{$channel}) { @@ -194,7 +196,7 @@ sub whitelist { return "Flag set."; } when ("unset") { - my ($channel, $mask, $flag) = split /\s+/, $args, 3; + my ($channel, $mask, $flag) = $self->{pbot}->{interpreter}->split_args($arglist, 3); return "Usage: whitelist unset " if not defined $channel or not defined $mask or not defined $flag; if (not exists $self->{whitelist}->hash->{$channel}) { @@ -214,7 +216,7 @@ sub whitelist { return "Flag unset."; } when ("add") { - my ($channel, $mask, $mode) = split /\s+/, $args, 3; + my ($channel, $mask, $mode) = $self->{pbot}->{interpreter}->split_args($arglist, 3); return "Usage: whitelist add [mode (user or ban, default: user)]" if not defined $channel or not defined $mask; $mode = 'user' if not defined $mode; @@ -231,7 +233,7 @@ sub whitelist { return "/say $mask whitelisted in channel $channel"; } when ("remove") { - my ($channel, $mask) = split /\s+/, $args, 2; + my ($channel, $mask) = $self->{pbot}->{interpreter}->split_args($arglist, 2); return "Usage: whitelist remove " if not defined $channel or not defined $mask; if(not defined $self->{whitelist}->hash->{$channel}) { diff --git a/PBot/AntiSpam.pm b/PBot/AntiSpam.pm index a2fde504..36eb89aa 100644 --- a/PBot/AntiSpam.pm +++ b/PBot/AntiSpam.pm @@ -70,9 +70,9 @@ sub is_spam { sub antispam_cmd { my ($self, $from, $nick, $user, $host, $arguments, $stuff) = @_; - my @pargs = @{$stuff->{argumentspos}}; + my $arglist = $stuff->{arglist}; - my $command = shift @pargs; + my $command = $self->{pbot}->{interpreter}->shift_arg($arglist); return "Usage: antispam , where commands are: list/show, add, remove, set, unset" if not defined $command; @@ -91,7 +91,7 @@ sub antispam_cmd { return $text; } when ("set") { - my ($namespace, $keyword, $flag, $value) = $self->{pbot}->{interpreter}->split_args(\@pargs, 4); + my ($namespace, $keyword, $flag, $value) = $self->{pbot}->{interpreter}->split_args($arglist, 4); return "Usage: antispam set [flag] [value]" if not defined $namespace or not defined $keyword; if (not exists $self->{keywords}->hash->{$namespace}) { @@ -132,7 +132,7 @@ sub antispam_cmd { return "Flag set."; } when ("unset") { - my ($namespace, $keyword, $flag) = $self->{pbot}->{interpreter}->split_args(\@pargs, 3); + my ($namespace, $keyword, $flag) = $self->{pbot}->{interpreter}->split_args($arglist, 3); return "Usage: antispam unset " if not defined $namespace or not defined $keyword or not defined $flag; if (not exists $self->{keywords}->hash->{$namespace}) { @@ -152,7 +152,7 @@ sub antispam_cmd { return "Flag unset."; } when ("add") { - my ($namespace, $keyword) = $self->{pbot}->{interpreter}->split_args(\@pargs, 2); + my ($namespace, $keyword) = $self->{pbot}->{interpreter}->split_args($arglist, 2); return "Usage: antispam add " if not defined $namespace or not defined $keyword; $self->{keywords}->hash->{$namespace}->{$keyword}->{owner} = "$nick!$user\@$host"; $self->{keywords}->hash->{$namespace}->{$keyword}->{created_on} = gettimeofday; @@ -160,7 +160,7 @@ sub antispam_cmd { return "/say Added `$keyword`."; } when ("remove") { - my ($namespace, $keyword) = $self->{pbot}->{interpreter}->split_args(\@pargs, 2); + my ($namespace, $keyword) = $self->{pbot}->{interpreter}->split_args($arglist, 2); return "Usage: antispam remove " if not defined $namespace or not defined $keyword; if(not defined $self->{keywords}->hash->{$namespace}) { diff --git a/PBot/BlackList.pm b/PBot/BlackList.pm index c9bb411a..a87f67f7 100644 --- a/PBot/BlackList.pm +++ b/PBot/BlackList.pm @@ -170,15 +170,17 @@ sub check_blacklist { } sub blacklist { - my ($self, $from, $nick, $user, $host, $arguments) = @_; - $arguments = lc $arguments; + my ($self, $from, $nick, $user, $host, $arguments, $stuff) = @_; - my ($command, $args) = split /\s+/, $arguments, 2; + my $arglist = $stuff->{arglist}; + $self->{pbot}->{interpreter}->lc_args($arglist); + + my $command = $self->{pbot}->{interpreter}->shift_arg($arglist); return "Usage: blacklist , where commands are: list/show, add, remove" if not defined $command; - given($command) { - when($_ eq "list" or $_ eq "show") { + given ($command) { + when ($_ eq "list" or $_ eq "show") { my $text = "Blacklist:\n"; my $entries = 0; foreach my $channel (sort keys %{ $self->{blacklist} }) { @@ -195,8 +197,8 @@ sub blacklist { $text .= "none" if $entries == 0; return "/msg $nick $text"; } - when("add") { - my ($mask, $channel) = split /\s+/, $args, 2; + when ("add") { + my ($mask, $channel) = $self->{pbot}->{interpreter}->split_args($arglist, 2); return "Usage: blacklist add [channel]" if not defined $mask; $channel = '.*' if not defined $channel; @@ -205,8 +207,8 @@ sub blacklist { $self->add($channel, $mask); return "/say $mask blacklisted in channel $channel"; } - when("remove") { - my ($mask, $channel) = split /\s+/, $args, 2; + when ("remove") { + my ($mask, $channel) = $self->{pbot}->{interpreter}->split_args($arglist, 2); return "Usage: blacklist remove [channel]" if not defined $mask; $channel = '.*' if not defined $channel; diff --git a/PBot/BotAdminCommands.pm b/PBot/BotAdminCommands.pm index 21f49a2a..11149c48 100644 --- a/PBot/BotAdminCommands.pm +++ b/PBot/BotAdminCommands.pm @@ -72,7 +72,7 @@ sub in_channel { return $usage; } - my ($channel, $command) = split / /, $arguments, 2; + my ($channel, $command) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2); return $usage if not defined $channel or not defined $command; $stuff->{admin_channel_override} = $channel; @@ -112,9 +112,9 @@ sub logout { sub adminadd { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; - my ($name, $channel, $hostmask, $level, $password) = split /\s+/, $arguments, 5; + my ($name, $channel, $hostmask, $level, $password) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 5); if(not defined $name or not defined $channel or not defined $hostmask or not defined $level or not defined $password) { @@ -139,9 +139,9 @@ sub adminadd { sub adminrem { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; - my ($channel, $hostmask) = split /\s+/, $arguments, 2; + my ($channel, $hostmask) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2); if(not defined $channel or not defined $hostmask) { return "/msg $nick Usage: adminrem "; @@ -172,8 +172,8 @@ sub adminrem { sub adminset { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; - my ($channel, $hostmask, $key, $value) = split /\s+/, $arguments, 4 if defined $arguments; + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; + my ($channel, $hostmask, $key, $value) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 4); if(not defined $channel or not defined $hostmask) { return "Usage: adminset [key] [value]"; @@ -219,8 +219,8 @@ sub adminset { sub adminunset { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; - my ($channel, $hostmask, $key) = split /\s+/, $arguments, 3 if defined $arguments; + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; + my ($channel, $hostmask, $key) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 3); if(not defined $channel or not defined $hostmask) { return "Usage: adminunset "; @@ -250,7 +250,7 @@ sub join_channel { my $self = shift; my ($from, $nick, $user, $host, $arguments) = @_; - foreach my $channel (split /\s+/, $arguments) { + foreach my $channel (split /[\s+,]/, $arguments) { $self->{pbot}->{logger}->log("$nick!$user\@$host made me join $channel\n"); $self->{pbot}->{chanops}->join_channel($channel); } @@ -264,7 +264,7 @@ sub part_channel { $arguments = $from if not $arguments; - foreach my $channel (split /\s+/, $arguments) { + foreach my $channel (split /[\s+,]/, $arguments) { $self->{pbot}->{logger}->log("$nick!$user\@$host made me part $channel\n"); $self->{pbot}->{chanops}->part_channel($channel); } diff --git a/PBot/ChanOpCommands.pm b/PBot/ChanOpCommands.pm index ce6c9d8a..d7ed5b6e 100644 --- a/PBot/ChanOpCommands.pm +++ b/PBot/ChanOpCommands.pm @@ -49,7 +49,7 @@ sub initialize { sub ban_user { my $self = shift; my ($from, $nick, $user, $host, $arguments, $stuff) = @_; - my ($target, $channel, $length) = split(/\s+/, $arguments, 3); + my ($target, $channel, $length) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 3); $channel = '' if not defined $channel; $length = '' if not defined $length; @@ -114,7 +114,7 @@ sub unban_user { return ""; } - my ($target, $channel, $immediately) = split /\s+/, $arguments; + my ($target, $channel, $immediately) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 3); if (defined $target and defined $channel and $channel !~ /^#/) { my $temp = $target; @@ -152,7 +152,7 @@ sub unban_user { sub mute_user { my $self = shift; my ($from, $nick, $user, $host, $arguments, $stuff) = @_; - my ($target, $channel, $length) = split(/\s+/, $arguments, 3); + my ($target, $channel, $length) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 3); if (not defined $from) { $self->{pbot}->{logger}->log("Command missing ~from parameter!\n"); @@ -222,7 +222,7 @@ sub unmute_user { return ""; } - my ($target, $channel, $immediately) = split /\s+/, $arguments; + my ($target, $channel, $immediately) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 3); if (defined $target and defined $channel and $channel !~ /^#/) { my $temp = $target; diff --git a/PBot/Channels.pm b/PBot/Channels.pm index 61ee15bf..ef37277f 100644 --- a/PBot/Channels.pm +++ b/PBot/Channels.pm @@ -43,8 +43,8 @@ sub initialize { } sub set { - my ($self, $from, $nick, $user, $host, $arguments) = @_; - my ($channel, $key, $value) = split /\s+/, $arguments, 3; + my ($self, $from, $nick, $user, $host, $arguments, $stuff) = @_; + my ($channel, $key, $value) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 3); if(not defined $channel) { return "Usage: chanset [key [value]]"; @@ -54,8 +54,8 @@ sub set { } sub unset { - my ($self, $from, $nick, $user, $host, $arguments) = @_; - my ($channel, $key) = split /\s+/, $arguments; + my ($self, $from, $nick, $user, $host, $arguments, $stuff) = @_; + my ($channel, $key) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2); if(not defined $channel or not defined $key) { return "Usage: chanunset "; diff --git a/PBot/DualIndexHashObject.pm b/PBot/DualIndexHashObject.pm index 1c801266..13af9455 100644 --- a/PBot/DualIndexHashObject.pm +++ b/PBot/DualIndexHashObject.pm @@ -189,7 +189,11 @@ sub levenshtein_matches { my $length = (length($primary_index_key) > length($index)) ? length $primary_index_key : length $index; if($distance_result / $length < $distance) { - $result .= $comma . $index; + if ($index =~ / /) { + $result .= $comma . "\"$index\""; + } else { + $result .= $comma . $index; + } $comma = ", "; } } @@ -220,7 +224,11 @@ sub levenshtein_matches { $header = "" if $last_header eq $header; $last_header = $header; $comma = '; ' if $comma ne '' and $header ne ''; - $result .= $comma . $header . $index2; + if ($index2 =~ / /) { + $result .= $comma . $header . "\"$index2\""; + } else { + $result .= $comma . $header . $index2; + } $comma = ", "; } } diff --git a/PBot/FactoidCommands.pm b/PBot/FactoidCommands.pm index 64b57772..52083f53 100644 --- a/PBot/FactoidCommands.pm +++ b/PBot/FactoidCommands.pm @@ -20,7 +20,6 @@ use POSIX qw(strftime); use Storable; use PBot::Utils::SafeFilename; -use PBot::Utils::ValidateString; sub new { if(ref($_[1]) eq 'HASH') { @@ -100,7 +99,7 @@ sub initialize { sub call_factoid { my $self = shift; my ($from, $nick, $user, $host, $arguments, $stuff) = @_; - my ($chan, $keyword, $args) = split /\s+/, $arguments, 3; + my ($chan, $keyword, $args) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 3); if(not defined $chan or not defined $keyword) { return "Usage: fact [arguments]"; @@ -171,7 +170,9 @@ sub log_factoid { sub find_factoid_with_optional_channel { my ($self, $from, $arguments, $command, $usage, $explicit, $exact_channel) = @_; - my ($from_chan, $from_trigger, $remaining_args) = split /\s+/, $arguments, 3; + + my $arglist = $self->{pbot}->{interpreter}->make_args($arguments); + my ($from_chan, $from_trigger, $remaining_args) = $self->{pbot}->{interpreter}->split_args($arglist, 3); if (not defined $from_chan or (not defined $from_chan and not defined $from_trigger)) { return "Usage: $command [channel] " if not $usage; @@ -192,8 +193,8 @@ sub find_factoid_with_optional_channel { # not a channel or global, so must be a keyword my $keyword = $from_chan; $from_chan = $from; - $remaining_args = $from_trigger . (length $remaining_args ? " $remaining_args" : ""); $from_trigger = $keyword; + (undef, $remaining_args) = $self->{pbot}->{interpreter}->split_args($arglist, 2); } } @@ -326,8 +327,7 @@ sub list_undo_history { } sub factundo { - my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; + my ($self, $from, $nick, $user, $host, $arguments, $stuff) = @_; my $usage = "Usage: factundo [-l [N]] [-r N] [channel] (-l list undo history, optionally starting from N; -r jump to revision N)"; @@ -348,6 +348,7 @@ sub factundo { return $usage if not @$args; $arguments = join ' ', @$args; + my $arglist = $self->{pbot}->{interpreter}->make_args($arguments); my ($channel, $trigger) = $self->find_factoid_with_optional_channel($from, $arguments, 'factundo', undef, 1, 1); my $deleted; @@ -355,7 +356,7 @@ sub factundo { if (not defined $trigger) { # factoid not found or some error, try to continue and load undo file if it exists $deleted = 1; - ($channel, $trigger) = split /\s+/, $arguments, 2; + ($channel, $trigger) = $self->{pbot}->{interpreter}->split_args($arglist, 2); if (not defined $trigger) { $trigger = $channel; $channel = $from; @@ -519,19 +520,16 @@ sub factset { my $self = shift; my ($from, $nick, $user, $host, $args) = @_; - $args = validate_string($args); - my ($channel, $trigger, $arguments) = $self->find_factoid_with_optional_channel($from, $args, 'factset', 'Usage: factset [channel] [key [value]]', 1); return $channel if not defined $trigger; # if $trigger is not defined, $channel is an error message - my ($key, $value) = split /\s+/, $arguments, 2; + my $arglist = $self->{pbot}->{interpreter}->make_args($arguments); + my ($key, $value) = $self->{pbot}->{interpreter}->split_args($arglist, 2); $channel = '.*' if $channel !~ /^#/; - my ($owner_channel, $owner_trigger) = $self->{pbot}->{factoids}->find_factoid($channel, $trigger, undef, 1, 1); my $admininfo; - if (defined $owner_channel) { $admininfo = $self->{pbot}->{admins}->loggedin($owner_channel, "$nick!$user\@$host"); } else { @@ -600,9 +598,12 @@ sub factunset { my $usage = 'Usage: factunset [channel] '; - my ($channel, $trigger, $key) = $self->find_factoid_with_optional_channel($from, $args, 'factset', $usage, 1); + my ($channel, $trigger, $arguments) = $self->find_factoid_with_optional_channel($from, $args, 'factunset', $usage, 1); return $channel if not defined $trigger; # if $trigger is not defined, $channel is an error message + my $arglist = $self->{pbot}->{interpreter}->make_args($arguments); + my ($key) = $self->{pbot}->{interpreter}->split_args($arglist, 1); + return $usage if not length $key; my ($owner_channel, $owner_trigger) = $self->{pbot}->{factoids}->find_factoid($channel, $trigger, undef, 1, 1); @@ -731,9 +732,8 @@ sub list { sub factmove { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; - $arguments = validate_string($arguments); - my ($src_channel, $source, $target_channel, $target) = split /\s+/, $arguments, 5 if length $arguments; + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; + my ($src_channel, $source, $target_channel, $target) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 5); my $usage = "Usage: factmove [target factoid]"; @@ -821,11 +821,10 @@ sub factmove { sub factalias { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; - $arguments = validate_string($arguments); + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; + + my ($chan, $alias, $command) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 3); - my ($chan, $alias, $command) = split /\s+/, $arguments, 3 if defined $arguments; - if (defined $chan and not ($chan eq '.*' or $chan =~ m/^#/)) { # $chan doesn't look like a channel, so shift everything right # and replace $chan with $from @@ -838,6 +837,8 @@ sub factalias { $chan = $from; } + $chan = '.*' if $chan !~ /^#/; + if (not length $alias or not length $command) { return "Usage: factalias [channel] "; } @@ -878,7 +879,6 @@ sub add_regex { my $self = shift; my ($from, $nick, $user, $host, $arguments) = @_; my $factoids = $self->{pbot}->{factoids}->{factoids}->hash; - $arguments = validate_string($arguments); my ($keyword, $text) = $arguments =~ /^(.*?)\s+(.*)$/ if defined $arguments; $from = '.*' if not defined $from or $from !~ /^#/; @@ -911,16 +911,19 @@ sub add_regex { sub factadd { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; my ($from_chan, $keyword, $text); - $arguments = validate_string($arguments); + my @arglist = @{$stuff->{arglist}}; - if (defined $arguments) { - if ($arguments =~ /^(#\S+|global|\.\*)\s+(\S+)\s+(?:is\s+)?(.*)$/i) { - ($from_chan, $keyword, $text) = ($1, $2, $3); - } elsif ($arguments =~ /^(\S+)\s+(?:is\s+)?(.*)$/i) { - ($from_chan, $keyword, $text) = ($from, $1, $2); + if (@arglist) { + if ($arglist[0] =~ m/(?:^#|^global$|^\.\*$)/i) { + splice @arglist, 2, 1 if lc $arglist[2] eq 'is'; + ($from_chan, $keyword, $text) = $self->{pbot}->{interpreter}->split_args(\@arglist, 3); + } else { + $from_chan = $from; + splice @arglist, 1, 1 if lc $arglist[1] eq 'is'; + ($keyword, $text) = $self->{pbot}->{interpreter}->split_args(\@arglist, 2); } } @@ -965,10 +968,10 @@ sub factadd { sub factrem { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; my $factoids = $self->{pbot}->{factoids}->{factoids}->hash; - my ($from_chan, $from_trig) = split /\s+/, $arguments; + my ($from_chan, $from_trig) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2); if (not defined $from_trig) { $from_trig = $from_chan; @@ -1038,10 +1041,10 @@ sub histogram { sub factshow { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; my $factoids = $self->{pbot}->{factoids}->{factoids}->hash; - my ($chan, $trig) = split /\s+/, $arguments; + my ($chan, $trig) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2); if (not defined $trig) { $trig = $chan; @@ -1093,7 +1096,8 @@ sub factlog { if (not defined $trigger) { # factoid not found or some error, try to continue and load factlog file if it exists - ($channel, $trigger) = split /\s+/, "@$args", 2; + my $arglist = $self->{pbot}->{interpreter}->make_args("@$args"); + ($channel, $trigger) = $self->{pbot}->{interpreter}->split_args($arglist, 2); if (not defined $trigger) { $trigger = $channel; $channel = $from; @@ -1138,10 +1142,10 @@ sub factlog { sub factinfo { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; my $factoids = $self->{pbot}->{factoids}->{factoids}->hash; - my ($chan, $trig) = split /\s+/, $arguments; + my ($chan, $trig) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2); if (not defined $trig) { $trig = $chan; @@ -1178,13 +1182,13 @@ sub factinfo { sub top20 { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; my $factoids = $self->{pbot}->{factoids}->{factoids}->hash; my %hash = (); my $text = ""; my $i = 0; - my ($channel, $args) = split /\s+/, $arguments, 2 if defined $arguments; + my ($channel, $args) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2); if(not defined $channel) { return "Usage: top20 [nick or 'recent']"; @@ -1366,7 +1370,11 @@ sub factfind { $text .= $chan eq '.*' ? "[global channel] " : "[$chan] "; $last_chan = $chan; } - $text .= "$trigger "; + if ($trigger =~ / /) { + $text .= "\"$trigger\" "; + } else { + $text .= "$trigger "; + } $last_trigger = $trigger; } } @@ -1393,8 +1401,6 @@ sub factchange { my $factoids = $self->{pbot}->{factoids}->{factoids}->hash; my ($channel, $trigger, $keyword, $delim, $tochange, $changeto, $modifier); - $arguments = validate_string($arguments); - my $needs_disambig; if (defined $arguments) { diff --git a/PBot/IgnoreListCommands.pm b/PBot/IgnoreListCommands.pm index 9eeab9d7..477d4101 100644 --- a/PBot/IgnoreListCommands.pm +++ b/PBot/IgnoreListCommands.pm @@ -46,11 +46,11 @@ sub initialize { sub ignore_user { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; return "/msg $nick Usage: ignore nick!user\@host [channel] [timeout]" if not defined $arguments; - my ($target, $channel, $length) = split /\s+/, $arguments, 3; + my ($target, $channel, $length) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 3); if(not defined $target) { return "/msg $nick Usage: ignore host [channel] [timeout]"; @@ -95,8 +95,8 @@ sub ignore_user { sub unignore_user { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; - my ($target, $channel) = split /\s+/, $arguments if defined $arguments; + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; + my ($target, $channel) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2); if(not defined $target) { return "/msg $nick Usage: unignore host [channel]"; diff --git a/PBot/Interpreter.pm b/PBot/Interpreter.pm index ecbe6968..386bbc82 100644 --- a/PBot/Interpreter.pm +++ b/PBot/Interpreter.pm @@ -206,8 +206,12 @@ sub interpret { return undef; } - if ($stuff->{command} =~ /^tell\s+(\p{PosixGraph}{1,20})\s+about\s+(.*?)\s+(.*)$/is) { - ($keyword, $arguments, $stuff->{nickoverride}) = ($2, $3, $1); + my $cmdlist = $self->make_args($stuff->{command}); + + if ($self->arglist_size($cmdlist) >= 4 and lc $cmdlist->[0] eq 'tell' and lc $cmdlist->[2] eq 'about') { + $stuff->{nickoverride} = $cmdlist->[1]; + ($keyword, $arguments) = $self->split_args($cmdlist, 2, 3); + $arguments = '' if not defined $arguments; my $similar = $self->{pbot}->{nicklist}->is_present_similar($stuff->{from}, $stuff->{nickoverride}); if ($similar) { $stuff->{nickoverride} = $similar; @@ -216,25 +220,15 @@ sub interpret { delete $stuff->{nickoverride}; delete $stuff->{force_nickoverride}; } - } elsif ($stuff->{command} =~ /^tell\s+(\p{PosixGraph}{1,20})\s+about\s+(.*)$/is) { - ($keyword, $stuff->{nickoverride}) = ($2, $1); - my $similar = $self->{pbot}->{nicklist}->is_present_similar($stuff->{from}, $stuff->{nickoverride}); - if ($similar) { - $stuff->{nickoverride} = $similar; - $stuff->{force_nickoverride} = 1; - } else { - delete $stuff->{nickoverride}; - delete $stuff->{force_nickoverride}; - } - } elsif ($stuff->{command} =~ /^(.*?)\s+(.*)$/s) { - ($keyword, $arguments) = ($1, $2); } else { - $keyword = $stuff->{command}; + ($keyword, $arguments) = $self->split_args($cmdlist, 2); + $arguments = "" if not defined $arguments; } - if (length $keyword > 30) { - $keyword = substr($keyword, 0, 30); - $self->{pbot}->{logger}->log("Truncating keyword to 30 chars: $keyword\n"); + # FIXME: make this a registry item + if (length $keyword > 128) { + $keyword = substr($keyword, 0, 128); + $self->{pbot}->{logger}->log("Truncating keyword to 128 chars: $keyword\n"); } # parse out a substituted command @@ -318,16 +312,30 @@ sub interpret { # unescape any escaped pipes $arguments =~ s/\\\|\s*\{/| {/g if defined $arguments; + $arguments = validate_string($arguments); + # set arguments as a plain string $stuff->{arguments} = $arguments; - # set arguments as a positional array - my @args = split / /, $arguments; - my @pargs; + # set arguments as an array + $stuff->{arglist} = $self->make_args($arguments); + + # handle this shit + return $self->SUPER::execute_all($stuff); +} + +# creates an array of arguments from a string +sub make_args { + my ($self, $string) = @_; + + my @args = split / /, $string; + my @arglist; + my @arglist_quotes; while (@args) { my $arg = shift @args; + # is this a quoted argument? if ($arg =~ /^["']/) { my $string = $arg; if (@args) { @@ -336,43 +344,73 @@ sub interpret { } my ($extracted, $rest) = extract_quotelike $string; if (defined $extracted) { + # preserve quotes for $rest in split_args() + push @arglist_quotes, $extracted; + # strip quote characters $extracted =~ s/^(.)//; $extracted =~ s/$1$//; - push @pargs, $extracted; + push @arglist, $extracted; + $rest =~ s/^ //; @args = split / /, $rest; } else { # mismatched quotes, shove the remainder as the last positional argument - push @pargs, $rest; + push @arglist, $rest; last; } } else { - push @pargs, $arg; + push @arglist, $arg; + push @arglist_quotes, $arg; } } - $stuff->{argumentspos} = \@pargs; + # copy original args with quotes intact to end of arglist + push @arglist, @arglist_quotes; + return \@arglist; +} - return $self->SUPER::execute_all($stuff); +# returns size of array of arguments +sub arglist_size { + my ($self, $args) = @_; + return @$args / 2; +} + +# shifts first argument off array of arguments +sub shift_arg { + my ($self, $args) = @_; + splice @$args, @$args / 2, 1; # remove original quoted argument + return shift @$args; } # splits array of arguments into array with overflow arguments filling up last position # split_args(qw/dog cat bird hamster/, 3) => ("dog", "cat", "bird hamster") sub split_args { - my ($self, $args, $count) = @_; + my ($self, $args, $count, $offset) = @_; my @result; - while (--$count) { - my $arg = shift @$args; - push @result, $arg; - } + my $max = $self->arglist_size($args); - my $rest = join ' ', @$args; - push @result, $rest; + my $i = $offset // 0; + do { + my $arg = $args->[$i++]; + push @result, $arg; + } while (--$count > 1 and $i < $max); + + # get rest from 2nd half of arglist, which contains original quotes + my $rest = join ' ', @$args[@$args / 2 + $i .. @$args - 1]; + push @result, $rest if length $rest; return @result; } +# lowercases array of arguments +sub lc_args { + my ($self, $args) = @_; + for (my $i = 0; $i < @$args; $i++) { + $args->[$i] = lc $args->[$i]; + } +} + sub truncate_result { my ($self, $from, $nick, $text, $original_result, $result, $paste) = @_; my $max_msg_len = $self->{pbot}->{registry}->get_value('irc', 'max_msg_len'); diff --git a/PBot/RegistryCommands.pm b/PBot/RegistryCommands.pm index 179ae723..c83e13b1 100644 --- a/PBot/RegistryCommands.pm +++ b/PBot/RegistryCommands.pm @@ -42,8 +42,8 @@ sub initialize { sub regset { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; - my ($section, $item, $key, $value) = split /\s+/, $arguments, 4 if defined $arguments; + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; + my ($section, $item, $key, $value) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 4); if(not defined $section or not defined $item) { return "Usage: regset
[key [value]]"; @@ -57,8 +57,8 @@ sub regset { sub regunset { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; - my ($section, $item, $key) = split /\s+/, $arguments, 3 if defined $arguments; + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; + my ($section, $item, $key) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 3); if(not defined $section or not defined $item or not defined $key) { return "Usage: regunset
" @@ -69,8 +69,8 @@ sub regunset { sub regadd { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; - my ($section, $item, $value) = split /\s+/, $arguments, 3 if defined $arguments; + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; + my ($section, $item, $value) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 3); if(not defined $section or not defined $item or not defined $value) { return "Usage: regadd
"; @@ -84,8 +84,8 @@ sub regadd { sub regrem { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; - my ($section, $item) = split /\s+/, $arguments if defined $arguments; + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; + my ($section, $item) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2); if(not defined $section or not defined $item) { return "Usage: regrem
"; @@ -106,10 +106,10 @@ sub regrem { sub regshow { my $self = shift; - my ($from, $nick, $user, $host, $arguments) = @_; + my ($from, $nick, $user, $host, $arguments, $stuff) = @_; my $registry = $self->{pbot}->{registry}->{registry}->hash; - my ($section, $item) = split /\s+/, $arguments if defined $arguments; + my ($section, $item) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2); if(not defined $section or not defined $item) { return "Usage: regshow
";