—use
strict;
use
warnings;
use
Carp;
our
$VERSION
=
'6.12'
;
sub
new {
my
(
$package
) =
shift
;
croak
"$package requires an even number of arguments"
if
@_
& 1;
my
%args
=
@_
;
$args
{
lc
$_
} =
delete
$args
{
$_
}
for
keys
%args
;
if
(!
defined
$args
{poll} ||
$args
{poll} !~ /^\d+$/) {
$args
{poll} = 30;
}
# the $irc->nick_name() and offending nickname will be...
#...the same on start, thus won't change
$args
{_did_start} = 0;
$args
{_claims} = {};
return
bless
\
%args
,
$package
;
}
sub
PCI_register {
my
(
$self
,
$irc
) =
@_
;
$irc
->plugin_register(
$self
,
'SERVER'
,
qw(433 001)
);
$irc
->plugin_register(
$self
,
'USER'
,
qw(nick)
);
# we will store the original nickname so we would know...
#...what we need to reclaim, without sending dozens of...
#...requests to reclaim foo_, foo__, foo___ etc.
$self
->{_nick} =
$irc
->{nick};
return
1;
}
##############
### sub U_nick
#######
# Basically, since we store the "real" nick in $self->{_nick}
# we need to adjust it if the PoCo::IRC user wants the bot
# to change its nick via ->yield(nick => 'foo');
# problem is that the "reclaiming" process also triggers this event
# we deal with it by using $self->{_claims} which stores all the
# nick with underscores that NickReclaim appended.
#
# if we get a new "real" nick, reset the $self->{_claims}
# and store "real" nick in $self->{_nick} so we would know
# what to reclaim in case we need to.
##############
sub
U_nick {
my
$self
=
shift
;
my
(
$nick
) = ${
$_
[1 ] } =~ /^NICK +(.+)/i;
return
PCI_EAT_NONE
if
exists
$self
->{_claims}{
$nick
};
# we got a new "real" nick, reset old nicks with underscores...
#...we don't need those anymore.
$self
->{_claims} = {};
$self
->{_nick} =
$nick
;
return
PCI_EAT_NONE;
}
sub
PCI_unregister {
return
1;
}
########
## sub S_001
########
# This is basically a tiny little bit that will differentiate
# between successful reclaims and the startup routine
# when $irc->nick_name() returns the nick which we need to reclaim
######
sub
S_001 {
$_
[0]->{_did_start} = 1;
return
PCI_EAT_NONE;
}
# ERR_NICKNAMEINUSE
sub
S_433 {
my
(
$self
,
$irc
) =
splice
@_
, 0, 2;
# this is the nickname which we failed to get...
my
$offending
= ${
$_
[2] }->[0];
# only reclaim if we don't have a nick we can use...
#...and it's not a startup routine where ->nick_name cannot
#...be used (and needs to be reclaimed)
if
(!
$self
->{_did_start} ||
$irc
->nick_name() eq
$offending
) {
# we will store the nick with the underscore in ->{_claims}...
#...so in sub U_nick{} we would know which ones were caused...
#...by NickReclaim and which ones need to change the "real" nick
$offending
.=
'_'
;
$self
->{_claims}{
$offending
} = 1;
# we will kindly ask the server to give us the nick with an underscore...
$irc
->yield(
nick
=>
$offending
);
}
# cancel old alarm, we won't need it anymore, considering we are going...
#...to post a new one.
# BingOS, is there a ->is_still_alarm() method to check if the alarm..
#...is pending to go off? I couldn't find it in the docs, but would be
#...nice to have (and use right here)
$irc
->delay_remove(
$self
->{_alarm_id} );
$self
->{_alarm_id} =
$irc
->delay(
[
nick
=>
$self
->{_nick} ],
$self
->{poll}
);
# note that we are asking the server to give us ->{_nick} which is...
#....our "real" nick.
return
PCI_EAT_NONE;
}
1;
__END__
=head1 NAME
POE::Component::IRC::Plugin::NickReclaim - A PoCo-IRC plugin for reclaiming
your nickname
=head1 SYNOPSIS
use strict;
use warnings;
use POE qw(Component::IRC Component::IRC::Plugin::NickReclaim);
my $nickname = 'Flibble' . $$;
my $ircname = 'Flibble the Sailor Bot';
my $ircserver = 'irc.blahblahblah.irc';
my $port = 6667;
my $irc = POE::Component::IRC->spawn(
nick => $nickname,
server => $ircserver,
port => $port,
ircname => $ircname,
) or die "Oh noooo! $!";
POE::Session->create(
package_states => [
main => [ qw(_start) ],
],
);
$poe_kernel->run();
sub _start {
$irc->yield( register => 'all' );
# Create and load our NickReclaim plugin, before we connect
$irc->plugin_add( 'NickReclaim' =>
POE::Component::IRC::Plugin::NickReclaim->new( poll => 30 ) );
$irc->yield( connect => { } );
return;
}
=head1 DESCRIPTION
POE::Component::IRC::Plugin::NickReclaim - A
L<POE::Component::IRC|POE::Component::IRC> plugin automagically deals with
your bot's nickname being in use and reclaims it when it becomes available
again.
It registers and handles 'irc_433' events. On receiving a 433 event it will
reset the nickname to the 'nick' specified with C<spawn> or C<connect>,
appendedwith an underscore, and then poll to try and change it to the
original nickname.
=head1 METHODS
=head2 C<new>
Takes one optional argument:
B<'poll'>, the number of seconds between nick change attempts, default is 30;
Returns a plugin object suitable for feeding to
L<POE::Component::IRC|POE::Component::IRC>'s C<plugin_add> method.
=head1 AUTHOR
Chris 'BinGOs' Williams
With amendments applied by Zoffix Znet
=head1 SEE ALSO
L<POE::Component::IRC|POE::Component::IRC>
=cut