http://www.perlmonks.org?node_id=1068372

three18ti has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks

EDIT: I think I solved my problem by registering my subroutine in my POE::Session->create, e.g.:

POE::Session->create( package_states => [ main => [ qw(_default _start irc_public irc_join irc_botcmd_sl +ap irc_botcmd_rot13) ], ], );

/EDIT

I'm working on an IRC bot, and going through the POE::Component::IRC docs. There is an example of a bot that takes commands in the POE::Cookbook. When I copy the code from the example, the test bot responds to the the !slap and !lookup commands as I would expect. The problem I am running into is when I copy the subroutine word for word (I attempted to write my own command first, but when that wasn't working I went back to the example method), I can see the command being triggered in the log, but the bot never responds to the channel.

What am I doing wrong? Like I say, I literally copied the example subroutine word for word so I'm puzzled as to why it works in the example but doesn't work in my test.

This is the logged even when I attempt to use the !slap command:

irc_botcmd_slap: 'foo!foo@workstation.local.tld' '#foo' 'foo' 'slap' +'slap'

The first 74 lines are boilerplate for configuring various irc options, the IRC code starts at `my $irc = POE::Component::IRC::State->spawn`

#!/usr/bin/perl use 5.010; use strict; use warnings; use POE; use Config::Any; use File::HomeDir; use Getopt::Long::Descriptive; use POE::Component::IRC::State; use POE::Component::IRC::Plugin::AutoJoin; use POE::Component::IRC::Plugin::BotCommand; my $home = File::HomeDir->my_home; # take options from command line my ($opt, $usage) = describe_options( "\%c \%o", [ "server-address|s=s" => 'IRC Server Address', + ], [ "server-port|p=s" => 'IRC Server Port [default: 6667 +]', ], [ "protocol|P=s" => 'IRC Server Protocol [default: +TCP]', ], [ "timeout|t=s" => 'IRC Server Connection Timeout +(in seconds) [default: 30]', ], [ "channel|c=s" => 'IRC Channel', + ], [ "config-name|n=s" => 'Config File Name', { default => 'testbot' }, + ], [ "nick|N=s" => 'IRC Nick', + ], [ "password|A=s" => 'IRC Password', + ], [ "username|u=s" => 'IRC Username, defaults to Nick + if unset', ], [ "hostname|h=s" => 'IRC Hostname', + ], [ "desc|d=s" => 'IRC User Desc.', + ], [], [ "verbose|v" => 'Print Status Messages' + ], [ "help|h" => 'Print This message and Exit', + ], ); ( print $usage->text ), exit if $opt->help; # get config name my $config = $opt->config_name; # look for config file my $cfg = Config::Any->load_stems( { stems => ["/etc/$config", "$home/etc/$config", "$home/etc/$con +fig", "./etc/$config", "./$config", ], use_ext => 1, } ); # take only the last loaded config file my $last_config = shift @$cfg; my ($file_name, $loaded_config); if ($last_config) { ($file_name, $loaded_config) = %$last_config; } else { ($file_name, $loaded_config) = ('NONE', {} ); } say "[*] Loaded config file $file_name" if $opt->verbose; # Thinking about config file design, my $server_address = $opt->server_address || $loaded_config->{'serve +r'}->{'address'} || 'myserver.net'; my $server_port = $opt->server_port || $loaded_config->{'serve +r'}->{'port'} || '6667'; my $server_protocol = $opt->protocol || $loaded_config->{'serve +r'}->{'protocol'} || 'tcp'; my $timeout = $opt->timeout || $loaded_config->{'serve +r'}->{'timeout'} || '30'; my $channel = $opt->channel || $loaded_config->{'serve +r'}->{'channel'} || [ '#foo',]; my $nick = $opt->nick || $loaded_config->{'user' +}->{'nick'} || 'testbot'; my $password = $opt->password || $loaded_config->{'user' +}->{'password'} || ''; my $username = $opt->username || $loaded_config->{'user' +}->{'username'} || $nick; my $hostname = $opt->hostname || $loaded_config->{'user' +}->{'hostname'} || 'foo.test.irc'; my $desc = $opt->desc || $loaded_config->{'user' +}->{'desc'}; my $irc = POE::Component::IRC::State->spawn( nick => $nick, Username => $username, ircname => $desc, server => $server_address, ); POE::Session->create( package_states => [ main => [ qw(_default _start irc_public irc_join) ], ], ); $poe_kernel->run(); sub _start { $irc->plugin_add( 'BotCommand', POE::Component::IRC::Plugin::BotCommand->new( In_channels => 1, Addressed => 0, Commands => { slap => 'Takes one argument: a nickname to slap.', } ) ); $irc->plugin_add( 'AutoJoin', POE::Component::IRC::Plugin::AutoJoin->new( Channels => $channel, ), ); $irc->yield( register => 'all' ); $irc->yield( 'connect' ); return; } sub _default { my ($event, $args) = @_[ARG0 .. $#_]; my @output = ( "$event: " ); for my $arg (@$args) { if (ref $arg eq 'ARRAY') { push @output, '[' . join ', ', @$arg . ']'; } else { push @output, "'$arg'"; } } print join ' ', @output, "\n"; return; } sub irc_public { my ($sender, $who, $where, $what) = @_[SENDER, ARG0 .. ARG2]; my $nick = ( split /!/, $who )[0]; my $irc = $_[SENDER]->get_heap; if (my ($rot13) = $what =~ /^rot13 (.+)/ ) { $rot13 =~ tr/a-zA-Z/n-za-mN-ZA-M/; $irc->yield( privmsg => $where => "$nick: $rot13" ); } } sub irc_join { my $nick = (split /!/, $_[ARG0])[0]; my $channel = $_[ARG1]; my $irc = $_[SENDER]->get_heap; if ($nick eq $irc->nick_name) { $irc->yield(privmsg => $channel, "Hi Everybody!"); } else { $irc->yield(privmsg => $channel, "Hi $nick!"); } } # the good old slap sub irc_botcmd_slap { my $nick = (split /!/, $_[ARG0])[0]; my $channel = $_[ARG0]; my ($where, $arg) = @_[ARG1, ARG2]; $irc->yield(privmsg => $where, "ACTION slaps $arg where: $where $c +hannel"); return; }

(actually, the !help command does not act as I would expect as it appends the channel name to the bots username, this is a publicly viewable message e.g.:

-YourBot/#foo- Commands: lookup, slap -YourBot/#foo- For more details, use: !help <command>

this is a mild annoyance and is really a low priority)

Thanks for the assistance