Permalink
Browse files

Added optional argument specification to Plugin::BotCommand.

  • Loading branch information...
1 parent bdfa9c6 commit 9b3ded74be8007c35f2b62f3964f51689f9410b8 @okxchg okxchg committed May 29, 2012
@@ -14,6 +14,13 @@ sub new {
$args{Method} = 'notice' if !defined $args{Method};
for my $cmd (keys %{ $args{Commands} }) {
+ if (ref $args{Commands}->{$cmd} eq 'HASH') {
+ croak "$cmd: no info provided"
+ if !exists $args{Commands}->{$cmd}->{info} ;
+ croak "$cmd: no arguments provided"
+ if !@{ $args{Commands}->{$cmd}->{args} };
+
+ }
$args{Commands}->{lc $cmd} = delete $args{Commands}->{$cmd};
}
return bless \%args, $package;
@@ -114,6 +121,20 @@ sub _handle_cmd {
}
if (defined $self->{Commands}->{$cmd}) {
+ if (ref $self->{Commands}->{$cmd} eq 'HASH') {
+ my @args_array = defined $args ? split /\s+/, $args : ();
+ if (@args_array != @{ $self->{Commands}->{$cmd}->{args} }) {
+ $irc->yield($self->{Method}, $where,
+ "Not enough or too many arguments. See help for $cmd");
+ return;
+ }
+
+ $args = {};
+ for (@{ $self->{Commands}->{$cmd}->{args} }) {
+ $args->{$_} = shift @args_array;
+ }
+ }
+
$irc->send_event_next("irc_botcmd_$cmd" => $who, $where, $args);
}
elsif ($cmd =~ /^help$/i) {
@@ -139,7 +160,19 @@ sub _get_help {
if (defined $args) {
my $cmd = (split /\s+/, $args, 2)[0];
if (exists $self->{Commands}->{$cmd}) {
- @help = split /\015?\012/, $self->{Commands}->{$cmd};
+ if (ref $self->{Commands}->{$cmd} eq 'HASH') {
+ push @help, "$cmd ".join ' ', @{ $self->{Commands}->{$cmd}->{args} };
+ push @help, "\n";
+ push @help, split /\015?\012/, $self->{Commands}->{$cmd}->{info};
+ push @help, "Arguments:";
+ for my $arg (@{ $self->{Commands}->{$cmd}->{args} }) {
+ push @help, "\t$arg: ".$self->{Commands}->{$cmd}->{$arg}
+ if defined $self->{Commands}->{$cmd}->{$arg};
+ }
+ }
+ else {
+ @help = split /\015?\012/, $self->{Commands}->{$cmd};
+ }
}
else {
push @help, "Unknown command: $cmd";
@@ -163,6 +196,11 @@ sub add {
my ($self, $cmd, $usage) = @_;
$cmd = lc $cmd;
return if exists $self->{Commands}->{$cmd};
+
+ if (ref $usage eq 'HASH') {
+ return if !exists $usage->{info} || !@{ $usage->{args} };
+ }
+
$self->{Commands}->{$cmd} = $usage;
return 1;
}
@@ -289,6 +327,22 @@ B<'Commands'>, a hash reference, with your commands as keys, and usage
information as values. If the usage string contains newlines, the plugin
will send one message for each line.
+If a command's value is a HASH ref like this:
+
+ $irc->plugin_add('BotCommand', POE::Component::IRC::Plugin::BotCommand->new(
+ Commands => {
+ slap => {
+ info => 'Slap someone',
+ args => [qw(nickname)],
+ nickname => 'nickname to slap'
+ }
+ }
+ ));
+
+The args array reference is than used to validate number of arguments required
+and to name arguments passed to event handler. Help is than generated from
+C<info> and other hash keys which represent arguments (they are optional).
+
=head3 Accepting commands
B<'In_channels'>, a boolean value indicating whether to accept commands in
@@ -359,8 +413,9 @@ L<POE::Component::IRC|POE::Component::IRC>'s C<plugin_add> method.
=head2 C<add>
Adds a new command. Takes two arguments, the name of the command, and a string
-containing its usage information. Returns false if the command has already been
-defined, true otherwise.
+or hash reference containing its usage information (see C<new>). Returns false
+if the command has already been defined or no info or arguments are provided,
+true otherwise.
=head2 C<remove>
@@ -370,7 +425,7 @@ if the command wasn't defined to begin with, true otherwise.
=head2 C<list>
Takes no arguments. Returns a list of key/value pairs, the keys being the
-command names and the values being the usage strings.
+command names and the values being the usage strings or hash references.
=head1 OUTPUT EVENTS
@@ -387,7 +442,8 @@ every time someone issued that command. It receives the following arguments:
=item * C<ARG1> is the name of the channel in which the command was issued,
or the sender's nickname if this was a private message.
-=item * C<ARG2>: a string of arguments to the command, or undef if there
+=item * C<ARG2>: a string of arguments to the command, or hash reference with
+arguments in case you defined command along with arguments, or undef if there
were no arguments
=back
@@ -5,7 +5,7 @@ use POE;
use POE::Component::IRC;
use POE::Component::IRC::Plugin::BotCommand;
use POE::Component::Server::IRC;
-use Test::More tests => 18;
+use Test::More tests => 22;
my $bot1 = POE::Component::IRC->spawn(
Flood => 1,
@@ -31,6 +31,7 @@ POE::Session->create(
irc_join
irc_botcmd_cmd1
irc_botcmd_cmd2
+ irc_botcmd_cmd3
irc_disconnected
)],
],
@@ -89,18 +90,25 @@ sub irc_001 {
my $plugin = POE::Component::IRC::Plugin::BotCommand->new(
Commands => {
cmd1 => 'First test command',
+ cmd2 => {
+ info => 'First test command with argument count checking',
+ args => [qw(test_arg test_arg2)],
+ test_arg => 'Description of first arg',
+ test_arg2 => 'Description of second arg',
+ },
foo => 'This will get removed',
},
);
- ok($irc->plugin_add(BotCommand => $plugin), 'Add plugin with two commands');
- ok($plugin->add(cmd2 => 'Second test command'), 'Add another command');
+ ok($irc->plugin_add(BotCommand => $plugin), 'Add plugin with three commands');
+ ok($plugin->add(cmd3 => 'Third test command'), 'Add another command');
ok($plugin->remove('foo'), 'Remove command');
my %cmds = $plugin->list();
- is(keys %cmds, 2, 'Correct number of commands');
+ is(keys %cmds, 3, 'Correct number of commands');
ok($cmds{cmd1}, 'First command is present');
ok($cmds{cmd2}, 'Second command is present');
+ ok($cmds{cmd3}, 'Third command is present');
}
sub irc_join {
@@ -116,8 +124,11 @@ sub irc_join {
# try command
$bot2->yield(privmsg => $where, "TestBot1: cmd1 foo bar");
+ # try command with predefined arguments
+ $bot2->yield(privmsg => $where, "TestBot1: cmd2 foo bar");
+
# and one with color
- $bot2->yield(privmsg => $where, "\x0302TestBot1\x0f: \x02cmd2\x0f");
+ $bot2->yield(privmsg => $where, "\x0302TestBot1\x0f: \x02cmd3\x0f");
}
sub irc_botcmd_cmd1 {
@@ -135,6 +146,17 @@ sub irc_botcmd_cmd2 {
my $nick = (split /!/, $user)[0];
my $irc = $sender->get_heap();
+ is($nick, $bot2->nick_name(), 'Command with args (user)');
+ is($where, '#testchannel', 'Command with args (channel)');
+ is_deeply($args, { test_arg => 'foo', test_arg2 => 'bar' },
+ 'Command with args (arguments)');
+}
+
+sub irc_botcmd_cmd3 {
+ my ($sender, $user, $where, $args) = @_[SENDER, ARG0..ARG2];
+ my $nick = (split /!/, $user)[0];
+ my $irc = $sender->get_heap();
+
is($nick, $bot2->nick_name(), 'Colored command (user)');
is($where, '#testchannel', 'Colored command (channel)');
ok(!defined $args, 'Colored command (arguments)');
@@ -5,7 +5,7 @@ use POE;
use POE::Component::IRC;
use POE::Component::IRC::Plugin::BotCommand;
use POE::Component::Server::IRC;
-use Test::More tests => 14;
+use Test::More tests => 23;
my $bot1 = POE::Component::IRC->spawn(
Flood => 1,
@@ -35,6 +35,15 @@ POE::Session->create(
],
);
+my @bar_help = (
+ "bar arg1 arg2",
+ "\n",
+ "Test command2",
+ "Arguments:",
+ "\targ1: What to bar",
+ "\targ2: Where to bar"
+);
+
$poe_kernel->run();
sub _start {
@@ -121,13 +130,22 @@ sub irc_notice {
like($what, qr/^Unknown command:/, 'Bot reply');
my ($p) = grep { $_->isa('POE::Component::IRC::Plugin::BotCommand') } values %{ $bot1->plugin_list() };
ok($p->add(foo => 'Test command'), 'Add command foo');
+ ok($p->add(bar => {
+ info => 'Test command2',
+ args => [qw(arg1 arg2)],
+ arg1 => 'What to bar', arg2 => 'Where to bar'
+ }), 'Add command bar');
$irc->yield(privmsg => $where, "TestBot1: help");
+ $irc->yield(privmsg => $where, "TestBot1: help bar");
}
elsif ($heap->{replies} == 4) {
is($nick, $bot1->nick_name(), 'Bot nickname');
- like($what, qr/^Commands: foo/, 'Bot reply');
+ like($what, qr/^Commands: bar, foo/, 'Bot reply');
}
- elsif ($heap->{replies} == 5) {
+ elsif ($heap->{replies} >= 6 && $heap->{replies} <= 11) {
+ is($nick, $bot1->nick_name(), 'Bot nickname');
+ is($what, shift @bar_help, 'Command with args help');
+
$bot1->yield('quit');
$bot2->yield('quit');
}

0 comments on commit 9b3ded7

Please sign in to comment.