Bot-Cobalt
view release on metacpan or search on metacpan
lib/Bot/Cobalt/IRC.pm view on Meta::CPAN
Component::IRC::Plugin::CTCP
Component::IRC::Plugin::AutoJoin
Component::IRC::Plugin::Connector
Component::IRC::Plugin::NickServID
Component::IRC::Plugin::NickReclaim
/;
## Bot::Cobalt::Common pulls the rest of these:
use IRC::Utils 'parse_mode_line';
use Moo;
has NON_RELOADABLE => (
## Well, really, it's sort-of unloadable.
## ... but life usually sucks when you do.
## Call _set_NON_RELOADABLE if you really need to
isa => Bool,
is => 'rwp',
default => sub { 1 },
);
## We keep references to our ircobjs; core tracks these also,
## but there is no guarantee that we're the only IRC plugin loaded.
has ircobjs => (
lazy => 1,
is => 'rw',
isa => HashObj,
coerce => 1,
default => sub { {} },
);
has flood => (
is => 'ro',
isa => Object,
lazy => 1,
predicate => 'has_flood',
default => sub {
my $ccfg = core->get_core_cfg;
my $count = $ccfg->opts->{FloodCount} || 5;
my $secs = $ccfg->opts->{FloodTime} || 6;
Bot::Cobalt::IRC::FloodChk->new(
count => $count,
in => $secs,
)
},
);
## Outgoing IRC traffic is handled by UserEvents role:
with 'Bot::Cobalt::IRC::Role::UserEvents';
## Administrative commands:
with 'Bot::Cobalt::IRC::Role::AdminCmds';
sub Cobalt_register {
my ($self, $core) = splice @_, 0, 2;
register($self, SERVER => 'all' );
broadcast( 'initialize_irc' );
## Start a lazy cleanup timer for flood->expire
$core->timer_set( 180,
+{ Event => 'ircplug_chk_floodkey_expire' },
'IRCPLUG_CHK_FLOODKEY_EXPIRE'
);
logger->info("Loaded");
PLUGIN_EAT_NONE
}
sub Cobalt_unregister {
my ($self, $core) = splice @_, 0, 2;
logger->info("Unregistering and dropping servers.");
$self->_clear_context($_) for keys %{ $self->ircobjs };
logger->debug("Clean unload");
PLUGIN_EAT_NONE
}
sub Bot_initialize_irc {
my ($self, $core) = splice @_, 0, 2;
## The IRC: directive in cobalt.conf provides context 'Main'
## (This will override any 'Main' specified in multiserv.conf)
## Munge core->irc() hash into our plugin's opts()
my $p_cfg = $core->cfg->plugins->plugin( plugin_alias($self) );
$p_cfg->opts->{Networks}->{Main} = $core->cfg->core->irc;
if (exists $p_cfg->opts->{Networks}->{'-ALL'}) {
## Reserved by core Auth plugin
logger->error("-ALL is not a valid context name, disregarding.");
delete $p_cfg->opts->{Networks}->{'-ALL'}
}
my $active_contexts = 0;
for my $context (keys %{ $p_cfg->opts->{Networks} } ) {
++$active_contexts;
next if defined $p_cfg->opts->{Networks}->{$context}->{Enabled}
and $p_cfg->opts->{Networks}->{$context}->{Enabled} == 0;
logger->debug("Found configured context $context");
broadcast( 'ircplug_connect', $context );
}
unless ($active_contexts) {
logger->error("No contexts configured/enabled!");
}
logger->info("Connecting to $active_contexts contexts");
PLUGIN_EAT_ALL
}
sub Bot_ircplug_connect {
my ($self, $core) = splice @_, 0, 2;
my $context = ${ $_[0] };
## Spawn an IRC Component and a Session to manage it.
##
## Called for each configured context.
##
## The sessions call the same object with different contexts in HEAP;
## the handlers do some processing and relay the event from the
## PoCo::IRC syndicator to the Bot::Cobalt::Core pipeline.
lib/Bot/Cobalt/IRC.pm view on Meta::CPAN
broadcast( 'user_quit', $quit );
}
sub irc_snotice {
my ($self, $heap, $kernel) = @_[OBJECT, HEAP, KERNEL];
my $context = $heap->{Context};
## These are weird.
## There should be at least a string.
my ($string, $target, $sender) = @_[ARG0 .. ARG2];
## FIXME test / POD
broadcast( 'server_notice', $context, $string, $target, $sender );
}
sub irc_topic {
my ($self, $kernel, $heap) = @_[OBJECT, KERNEL, HEAP];
my ($src, $channel, $topic) = @_[ARG0 .. ARG2];
my $context = $heap->{Context};
my $irc = $self->ircobjs->{$context};
my $topic_obj = Bot::Cobalt::IRC::Event::Topic->new(
context => $context,
src => $src,
channel => $channel,
topic => $topic,
);
## Bot_topic_changed
broadcast( 'topic_changed', $topic_obj );
}
### Internals.
sub Bot_rehashed {
my ($self, $core) = splice @_, 0, 2;
my $type = ${ $_[0] };
if ($type eq 'core' || $type eq 'channels') {
logger->info("Rehash received ($type), resetting ajoins");
$self->_reset_ajoins;
}
## FIXME nickservid rehash if needed
return PLUGIN_EAT_NONE
}
sub Bot_ircplug_chk_floodkey_expire {
my ($self, $core) = splice @_, 0, 2;
## Lazy flood tracker cleanup.
## These are just arrays of timestamps, but they gotta be cleaned up
## when they're stale.
$self->flood->expire if $self->has_flood;
$core->timer_set( 60,
{ Event => 'ircplug_chk_floodkey_expire' },
'IRCPLUG_CHK_FLOODKEY_EXPIRE'
);
return PLUGIN_EAT_ALL
}
sub Bot_ircplug_flood_rem_ignore {
my ($self, $core) = splice @_, 0, 2;
my $context = ${ $_[0] };
my $mask = ${ $_[1] };
## Internal timer-fired event to remove temp ignores.
logger->info("Clearing temp ignore: $mask ($context)");
$core->ignore->del( $context, $mask );
broadcast( 'flood_ignore_deleted', $context, $mask );
return PLUGIN_EAT_ALL
}
sub flood_ignore {
## Pass me a context and a mask
## Set a temporary ignore and a timer to remove it
my ($self, $context, $mask) = @_;
my $corecf = core->get_core_cfg;
my $ignore_time = $corecf->opts->{FloodIgnore} || 20;
$self->flood->clear($context, $mask);
logger->info(
"Issuing temporary ignore due to flood: $mask ($context)"
);
my $added = core->ignore->add(
$context, $mask, "flood_ignore", __PACKAGE__
);
broadcast( 'flood_ignore_added', $context, $mask );
core->timer_set( $ignore_time,
{
Event => 'ircplug_flood_rem_ignore',
Args => [ $context, $mask ],
},
);
}
sub _reset_ajoins {
my ($self) = @_;
my $corecf = core->get_core_cfg;
my $servers = core->Servers;
CONTEXT: for my $context (keys %$servers) {
my $chanscf = core->get_channels_cfg($context) // {};
my $irc = core->get_irc_obj($context) || next CONTEXT;
my %ajoin;
CHAN: for my $channel (keys %$chanscf) {
my $key = $chanscf->{$channel}->{password} // '';
$ajoin{$channel} = $key;
}
logger->debug("Removing AutoJoin plugin for $context");
$irc->plugin_del('AutoJoin');
logger->debug("Loading new AutoJoin plugin for $context");
$irc->plugin_add('AutoJoin' =>
POE::Component::IRC::Plugin::AutoJoin->new(
Channels => \%ajoin,
RejoinOnKick => $corecf->opts->{Chan_RetryAfterKick} // 1,
Rejoin_delay => $corecf->opts->{Chan_RejoinDelay} // 5,
NickServ_delay => $corecf->opts->{Chan_NickServDelay} // 1,
Retry_when_banned => $corecf->opts->{Chan_RetryAfterBan} // 60,
),
);
}
}
1;
__END__
=pod
=head1 NAME
Bot::Cobalt::IRC -- Bot::Cobalt IRC bridge
=head1 DESCRIPTION
For a description of the commands provided by the IRC bridge, see
L<Bot::Cobalt::IRC::Role::AdminCmds>.
This is the core plugin providing IRC functionality to
L<Bot::Cobalt>; incoming and outgoing IRC activity
( run in 0.587 second using v1.01-cache-2.11-cpan-437f7b0c052 )