Bot::Cobalt::Manual::Plugins::Tutorial - Let's write a simple plugin
Quick-start plugin authoring guide.
Let's write a simple plugin that will respond to a command with a random string.
We'll at least need a package name, a version, some utilities, and an object constructor.
Declare our package:
package My::Bot::Cobalt::Plugin; our $VERSION = '0.01';
We might need Bot::Cobalt::Common utilities. It's good practice to use strict and warnings explicitly, although Bot::Cobalt::Common will import them for you. It's even better to make warnings fatal as well via strictures:
use strictures 1; use Bot::Cobalt::Common;
We probably also want the syntax sugar exported by Bot::Cobalt. This provides a simpler function interface to common core methods; we'll be able to call broadcast() to relay events and logger() to log messages.
broadcast()
logger()
use Bot::Cobalt;
(See Bot::Cobalt::Core::Sugar for more on exported sugar.)
We can add a simple empty constructor:
sub new { bless {}, shift }
Our plugin can't be loaded unless it can handle Cobalt_register and Cobalt_unregister events. It's also probably not very useful unless it's registered to receive some kind of event, most often from Bot::Cobalt::IRC.
Let's register to receive the in-channel command 'fortune' -- we'll figure out some responses to it later. Since we 'use Bot::Cobalt' we have the register() and logger() functions available:
register()
sub Cobalt_register { my ($self, $core) = splice @_, 0, 2; register( $self, 'SERVER', ## A list of events to catch. qw/ public_cmd_fortune / ); ## It's polite to log that we're here now. logger->info("Loaded - $VERSION"); return PLUGIN_EAT_NONE } sub Cobalt_unregister { my ($self, $core) = splice @_, 0, 2; logger->info("Unloaded"); return PLUGIN_EAT_NONE }
Notice the PLUGIN_EAT_NONE? Our event handlers should always return a Object::Pluggable::Constants constant indicating what to do with the event after the handler is complete. This is typically one of PLUGIN_EAT_NONE or PLUGIN_EAT_ALL, indicating whether to let the event continue on down the pipeline or be terminated, respectively.
Now we're loadable and will register to receive the 'SERVER' event public_cmd_fortune -- we just need a handler for it.
The first argument after the $self and $core objects will be a reference to a Bot::Cobalt::IRC::Message::Public object. We'll de-reference it and call some common methods to find out what we want to know.
$self
$core
sub Bot_public_cmd_fortune { my ($self, $core) = splice @_, 0, 2; ## Get our (de-referenced) message object. my $msg = ${ $_[0] }; ## Get our server context, source nickname, and channel. my $context = $msg->context; my $src_nick = $msg->src_nick; my $channel = $msg->channel; ## We'll write our response method fortune() later. my $fortune = $self->fortune; my $response_string = "$src_nick: $fortune"; ## Relay our response string back to Bot::Cobalt::IRC broadcast( 'message', $context, $channel, $response_string ); ## This one eats the event when it's complete. return PLUGIN_EAT_ALL }
For convenience, we'll store our fortune cookies in the DATA filehandle until we need them.
At the bottom of your plugin module:
1; ## Perl modules must return a true value __DATA__ You are not dead yet. Watch for further reports. Don't look up. You look tired. Fine day for friends. Crappy day for you.
Add as many as you like, one per line. When we want to retrieve them, we just read DATA like a normal file handle.
Let's write our fortune() method to pull a random fortune from our retrieved DATA -- this is nice and simple:
sub fortune { my ($self) = @_; $self->{fortunes} = [ readline(DATA) ] unless defined $self->{fortunes}; return $self->{fortunes}->[ rand( @{$self->{fortunes}} ) ] }
package My::Bot::Cobalt::Plugin; our $VERSION = '0.01'; use strictures 1; use Bot::Cobalt::Common; use Bot::Cobalt; sub new { bless {}, shift } sub Cobalt_register { my ($self, $core) = splice @_, 0, 2; register( $self, 'SERVER', ## A list of events to catch. qw/ public_cmd_fortune / ); ## It's polite to log that we're here now. logger->info("Loaded - $VERSION"); return PLUGIN_EAT_NONE } sub Cobalt_unregister { my ($self, $core) = splice @_, 0, 2; logger->info("Unloaded"); return PLUGIN_EAT_NONE } sub Bot_public_cmd_fortune { my ($self, $core) = splice @_, 0, 2; ## Get our (de-referenced) message object. my $msg = ${ $_[0] }; ## Get our server context, source nickname, and channel. my $context = $msg->context; my $src_nick = $msg->src_nick; my $channel = $msg->channel; my $fortune = $self->fortune; my $response_string = "$src_nick: $fortune"; ## Relay our response string back to Bot::Cobalt::IRC broadcast( 'message', $context, $channel, $response_string ); ## This one eats the event when it's complete. return PLUGIN_EAT_ALL } sub fortune { my ($self) = @_; $self->{fortunes} = [ readline(DATA) ] unless defined $self->{fortunes}; return $self->{fortunes}->[ rand( @{$self->{fortunes}} ) ] } 1; ## Perl modules must return a true value __DATA__ You are not dead yet. Watch for further reports. Don't look up. You look tired. Fine day for friends. Crappy day for you.
Bot::Cobalt::Manual::Plugins - Plugin authoring handbook
Bot::Cobalt::Core
Bot::Cobalt::Core::Sugar
Bot::Cobalt::IRC
Bot::Cobalt::IRC::Event
Bot::Cobalt::IRC::Message
Jon Portnoy <avenj@cobaltirc.org>
http://www.cobaltirc.org
To install Bot::Cobalt, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Bot::Cobalt
CPAN shell
perl -MCPAN -e shell install Bot::Cobalt
For more information on module installation, please visit the detailed CPAN module installation guide.