Why not adopt me?
NAME
Bot::Cobalt::IRC -- Bot::Cobalt IRC bridge
DESCRIPTION
For a description of the commands provided by the IRC bridge, see Bot::Cobalt::IRC::Role::AdminCmds.
This is the core plugin providing IRC functionality to Bot::Cobalt; incoming and outgoing IRC activity is handled just like any other plugin pipeline event.
This core IRC plugin provides a multi-server IRC interface via POE::Component::IRC. Subclasses or other IRC plugins should follow this pattern and provide a compatible event interface.
The IRC plugin does various work on incoming events we consider important enough to re-broadcast from the IRC component. This makes life easier on plugins and reduces code redundancy.
Arguments may vary by event. See below.
If you're trying to write Cobalt plugins, you probably want to start off with Bot::Cobalt::Manual::Plugins -- this is a reference for IRC-related events specifically.
EMITTED EVENTS
Connection state events
Bot_connected
Issued when an irc_001 (welcome msg) event is received.
Indicates the bot is now talking to an IRC server.
my ($self, $core) = splice @_, 0, 2;
my $context = ${$_[0]};
my $server_name = ${$_[1]};
The relevant $core->Servers->{$context} object is updated prior to broadcasting this event. This means that 'maxmodes' and 'casemap' are now available for retrieval. You might use these to properly compare two nicknames, for example:
## grab eq_irc() from IRC::Utils
## also available if you "use Bot::Cobalt::Common;"
## see perldoc Bot::Cobalt::Common and Bot::Cobalt::Manual::Plugins
use IRC::Utils qw/ eq_irc /;
my $context = ${$_[0]};
## most servers are 'rfc1459', some may be ascii or -strict
## (some return totally fubar values, and we'll default to rfc1459)
my $casemap = $core->Servers->{$context}->casemap;
my $is_equal = IRC::Utils::eq_irc($nick_a, $nick_b, $casemap);
See Bot::Cobalt::IRC::Server for details on using a Server object.
Bot_disconnected
Broadcast when irc_disconnected is received.
my ($self, $core) = splice @_, 0, 2;
my $context = ${$_[0]};
my $server_name = ${$_[1]};
$core->Servers->{$context}->connected will be false until a reconnect.
Bot_server_error
Issued on unknown ERROR : events. Not a socket error, but connecting failed.
The IRC component will provide a maybe-not-useful reason:
my ($self, $core) = splice @_, 0, 2;
my $context = ${$_[0]};
my $reason = ${$_[1]};
Incoming message events
Bot_public_msg
Broadcast upon receiving public text (text in a channel).
my ($self, $core) = splice @_, 0, 2;
my $msg = ${$_[0]};
my $context = $msg->context;
my $stripped = $msg->stripped;
...
$msg is a Bot::Cobalt::IRC::Message object; in the case of public messages it is a Bot::Cobalt::IRC::Message::Public object.
See Bot::Cobalt::IRC::Message for complete documentation regarding available methods.
IMPORTANT: We don't automatically decode any character encodings. This means that text may be a byte-string of unknown encoding. Storing or displaying the text may present complications. You may want decode_irc from IRC::Utils for these applications. See "ENCODING" in IRC::Utils for more on encodings + IRC.
Also see:
Bot_public_cmd_CMD
Broadcast when a public command is triggered.
Plugins can catch these events to respond to specific commands.
CMD is the public command triggered; ie the first "word" of something like (if CmdChar is '!'): !kick --> Bot_public_cmd_kick
Syntax is precisely the same as "Bot_public_msg", with one major caveat: $msg->message_array will not contain the command.
This event is pushed to the pipeline before _public_msg.
Bot_private_msg
Broadcast when a private message is received.
Syntax is the same as "Bot_public_msg", except the first spotted destination is stored in key target
The default IRC interface plugins only spawn a single client per server. It's fairly safe to assume that target
is the bot's current nickname.
Bot_got_notice
Broadcast when a /NOTICE is received.
Syntax is the same as "Bot_public_msg".
Bot_ctcp_action
Broadcast when a CTCP ACTION (/ME in most clients) is received.
Syntax is similar to "Bot_public_msg".
If the ACTION appears to have been directed at a channel, the channel method will return the same value as target -- otherwise it will return an empty string.
Sent notification events
Bot_message_sent
Broadcast when a PRIVMSG has been sent to the server via an event; in other words, when a 'message' event was sent.
Carries a copy of the target and text:
my ($self, $core) = splice @_, 0, 2;
my $context = ${$_[0]};
my $target = ${$_[1]};
my $string = ${$_[2]};
This being IRC, there is no guarantee that the message actually made it to its intended destination ;-)
Bot_notice_sent
Broadcast when a NOTICE has been sent out via a 'notice' event.
Same syntax as "Bot_message_sent".
Bot_ctcp_sent
Broadcast when a CTCP has been sent via a CTCP handler such as "action".
my $context = ${$_[0]};
my $ctcp_type = ${$_[1]}; ## 'ACTION' for example
my $target = ${$_[2]};
my $content = ${$_[3]};
Bot_raw_sent
Broadcast when a raw string has been sent via "send_raw".
Arguments are the server context name and the raw string sent.
Channel state events
Bot_chan_sync
Broadcast when we've finished receiving channel status info. This generally indicates we're ready to talk to the channel.
Carries the channel name:
my ($self, $core) = splice @_, 0, 2;
my $context = ${$_[0]};
my $channel = ${$_[1]};
Bot_topic_changed
Broadcast when a channel topic has changed.
Carries a Bot::Cobalt::IRC::Event::Topic object:
my ($self, $core) = @splice @_, 0, 2;
my $topic_obj = ${$_[0]};
my $context = $topic_obj->context;
my $setter = $topic_obj->src_nick;
my $new_topic = $topic_obj->topic;
Bot::Cobalt::IRC::Event::Topic is a subclass of Bot::Cobalt::IRC::Event and Bot::Cobalt::IRC::Event::Channel -- see the documentation for those base classes for complete details on available methods.
Note that the topic setter may be a server, just a nickname, the name of a service, or some other arbitrary string.
Bot_mode_changed
Broadcast when a channel mode has changed.
my ($self, $core) = splice @_, 0, 2;
my $modechg = ${$_[0]};
my $context = $modechg->context;
my $modestr = $modechg->mode;
my $modeargs = $modechg->args;
my $modehash = $modechg->hash;
The hashref returned by <-hash>> is produced by "parse_mode_line" in IRC::Utils.
It has two keys: modes and args. They are both ARRAY references:
my @modes = @{ $modechg->hash->{modes} };
my @args = @{ $modechg->hash->{args} };
If parsing failed, the hash is empty.
The trick to parsing modes is determining whether or not they have args that need to be pulled out. You can walk each individual mode and handle known types:
MODE: for my $mode (@modes) {
for ($mode) {
next MODE if $mode =~ /[cimnpstCMRS]/; # oftc-hybrid/bc6 param-less modes
if ($mode eq 'l') { ## limit mode has an arg
my $limit = shift @args;
...
}
if ($mode eq 'b') {
## shift off a ban ...
}
## etc
}
}
Theoretically, you can find out which types should have args via ISUPPORT:
my $irc = $self->Servers->{$context}->irc;
my $is_chanmodes = $irc->isupport('CHANMODES')
|| 'b,k,l,imnpst'; ## oldschool set
## $m_list modes add/delete modes from a list (bans for example)
## $m_always modes always have a param specified.
## $m_only modes only have a param specified on a '+' operation.
## $m_never will never have a parameter.
my ($m_list, $m_always, $m_only, $m_never) = split ',', $is_chanmodes;
## get status modes (ops, voice ...)
## allegedly not all servers report all PREFIX modes
my $m_status = $irc->isupport('PREFIX') || '(ov)@+';
$m_status =~ s/^\((\w+)\).*$/$1/;
See http://www.irc.org/tech_docs/005.html for more information on ISUPPORT.
As of this writing the Cobalt core provides no convenience method for this.
Bot_user_joined
Broadcast when a user joins a channel we are on.
my ($self, $core) = splice @_, 0, 2;
my $join = ${$_[0]};
my $nickname = $join->src_nick;
my $context = $join->context;
Carries a Bot::Cobalt::IRC::Event::Channel object.
Bot_self_joined
Broadcast when the bot joins a channel.
A "Bot_user_joined" is still issued as well.
Carries the same syntax and caveats as "Bot_self_left" (below)
Bot_user_left
Broadcast when a user parts a channel we are on.
my ($self, $core) = splice @_, 0, 2;
my $part = ${$_[0]};
Carries a Bot::Cobalt::IRC::Event::Channel object; also see "Bot_user_joined".
Bot_self_left
Broadcast when the bot parts a channel, possibly via coercion.
A plugin can catch Bot_part events to find out that the bot was told to depart from a channel. However, the bot may've been forced to PART by the IRCD. Many daemons provide a 'REMOVE' and/or 'SAPART' that will do this. Bot_self_left indicates the bot left the channel, as determined by matching the bot's nickname against the user who left.
${$_[1]} is the channel name.
my ($self, $core) = splice @_, 0, 2;
my $context = ${$_[0]};
my $channel = ${$_[1]};
IMPORTANT:
Uses eq_irc with the server's CASEMAPPING to determine whether this is actually the bot leaving, in order to cope with servers issuing forced parts with incorrect case.
This method may be unreliable on servers with an incorrect CASEMAPPING in ISUPPORT, as it will fall back to normal rfc1459 rules.
Also see "Bot_user_left"
Bot_self_kicked
Broadcast when the bot was seemingly kicked from a channel.
my ($self, $core) = splice @_, 0, 2;
my $context = ${$_[0]};
my ($src, $chan, $reason) = (${$_[1]}, ${$_[2]}, ${$_[3]});
Relies on the same logic as "Bot_self_left" -- be sure to read the note in that section (above).
The bot will probably attempt to auto-rejoin unless configured otherwise.
Bot_user_kicked
Broadcast when a user (maybe us) is kicked.
my ($self, $core) = splice @_, 0, 2;
my $kick = ${$_[0]};
my $kicked = $kick->kicked;
my $kicked_by = $kick->src_nick;
my $reason = $kick->reason;
Carries a Bot::Cobalt::IRC::Event::Kick object.
Bot_invited
Broadcast when the bot has been invited to a channel.
my ($self, $core) = splice @_, 0, 2;
my $invite = ${$_[0]};
my $invited_to = $invite->channel;
my $invited_by = $invite->src_nick;
Carries a Bot::Cobalt::IRC::Event::Channel object.
User state events
Bot_umode_changed
Broadcast when mode changes on the bot's nickname (umode).
my ($self, $core) = splice @_, 0, 2;
my $modechg = ${$_[0]};
my $modestr = $modechg->mode;
Carries a Bot::Cobalt::IRC::Event::Mode object.
Bot_nick_changed
Broadcast when a visible user's nickname changes.
my ($self, $core) = splice @_, 0, 2;
my $nchange = ${$_[0]};
my $old = $nchange->old_nick;
my $new = $nchange->new_nick;
if ( $nchange->equal ) {
## Case change only
}
Carries a Bot::Cobalt::IRC::Event::Nick object.
equal is determined by attempting to get server CASEMAPPING= (falling back to 'rfc1459' rules) and using IRC::Utils to check whether this appears to be just a case change. This method may be unreliable on servers with an incorrect CASEMAPPING value in ISUPPORT.
Bot_self_nick_changed
Broadcast when our own nickname changed, possibly via coercion.
my ($self, $core) = splice @_, 0, 2;
my $context = ${$_[0]};
my $new_nick = ${$_[1]};
Bot_user_quit
Broadcast when a visible user has quit.
We can only receive quit notifications if we share channels with the user, of course.
my ($self, $core) = splice @_, 0, 2;
my $quit = ${ $_[0] };
my $nickname = $quit->src_nick;
my $reason = $quit->reason;
Carries a Bot::Cobalt::IRC::Event::Quit object.
Outgoing message triggers
It's possible to write plugins that register for USER events to catch messages before they are dispatched to IRC.
These events are prefixed with Outgoing_.
Using this mechanism, you can write output filters by registering for a USER event:
## in your Cobalt_register, perhaps:
$core->plugin_register( $self, 'USER',
[ 'message' ],
);
## handler:
sub Outgoing_message {
my ($self, $core) = splice @_, 0, 2;
my $context = ${ $_[0] };
my $target = ${ $_[1] };
## You can modify these references directly.
## This is the same as Plugin::OutputFilters::StripFormat:
${ $_[2] } = strip_formatting( ${ $_[2] } );
## If you EAT_ALL, the message won't be sent:
return PLUGIN_EAT_NONE
}
The following USER events are emitted:
Outgoing_message
Syndicated when a "message" event has been received.
Event arguments are references to the context, target, and message string, respectively.
Outgoing_notice
Syndicated when a "notice" event has been received; arguments are the same as "Outgoing_message".
Outgoing_ctcp
Syndicated when a CTCP is about to be sent via "action" or a similar CTCP handler.
my $context = ${ $_[0] };
my $ctcp_type = ${ $_[1] };
my $target = ${ $_[2] };
my $content = ${ $_[3] };
ACCEPTED EVENTS
Outgoing IRC commands
message
A message
event for our context triggers a PRIVMSG send.
broadcast( 'message', $context, $target, $string );
An "Outgoing_message" USER event will be issued prior to sending.
Upon completion a "Bot_message_sent" event will be broadcast.
notice
A notice
event for our context triggers a NOTICE.
broadcast( 'notice', $context, $target, $string );
An "Outgoing_notice" USER event will be issued prior to sending.
Upon completion a "Bot_notice_sent" event will be broadcast.
action
A action
event sends a CTCP ACTION (also known as '/me') to a channel or nickname.
broadcast( 'action', $context, $target, $string );
An "Outgoing_ctcp" USER event will be issued prior to sending.
Upon completion a "Bot_ctcp_sent" event will be broadcast.
send_raw
Quote a raw string to the IRC server.
Does no parsing or sanity checking.
broadcast( 'send_raw', $raw );
A "Bot_raw_sent" will be broadcast.
mode
A mode
event for our context attempts a mode change.
Typically the target will be either a channel or the bot's own nickname.
broadcast( 'mode', $context, $target, $modestr );
## example for Main context:
broadcast( 'mode', 'Main', '#mychan', '+ik some_key' );
This being IRC, there is no guarantee that the bot has privileges to effect the changes, or that the changes took place.
topic
A topic
event for our context attempts to change channel topic.
broadcast( 'topic', $context, $channel, $new_topic );
kick
A kick
event for our context attempts to kick a user.
A reason can be supplied:
broadcast( 'kick', $context, $channel, $target, $reason );
join
A join
event for our context attempts to join a channel.
broadcast( 'join', $context, $channel );
Catch "Bot_chan_sync" to check for channel sync status.
part
A part
event for our context attempts to leave a channel.
A reason can be supplied:
broadcast( 'part', $context, $channel, $reason );
There is no guarantee that we were present on the channel in the first place.
Server control
ircplug_connect
Takes the name of a configured context.
Attempts to initialize a connection for the named context (if the configuration can be found).
This interface is evolving and subject to change.
ircplug_disconnect
Same arguments and caveats as ircplug_connect.
SEE ALSO
AUTHOR
Jon Portnoy <avenj@cobaltirc.org>