File Coverage

blib/lib/POE/Component/IRC/Plugin/CycleEmpty.pm
Criterion Covered Total %
statement 51 70 72.8
branch 9 20 45.0
condition n/a
subroutine 12 14 85.7
pod 2 8 25.0
total 74 112 66.0


line stmt bran cond sub pod time code
1             package POE::Component::IRC::Plugin::CycleEmpty;
2             $POE::Component::IRC::Plugin::CycleEmpty::VERSION = '6.95';
3 3     3   4325 use strict;
  3         8  
  3         122  
4 3     3   14 use warnings FATAL => 'all';
  3         5  
  3         397  
5 3     3   21 use Carp;
  3         5  
  3         246  
6 3     3   15 use IRC::Utils qw( parse_user uc_irc );
  3         5  
  3         189  
7 3     3   14 use POE::Component::IRC::Plugin qw( :ALL );
  3         6  
  3         2946  
8              
9             sub new {
10 2     2 1 3146 my ($package) = shift;
11 2 50       10 croak "$package requires an even number of arguments" if @_ & 1;
12 2         7 my %self = @_;
13 2         9 return bless \%self, $package;
14             }
15              
16             sub PCI_register {
17 2     2 0 1168 my ($self, $irc) = @_;
18              
19 2 50       34 if (!$irc->isa('POE::Component::IRC::State')) {
20 0         0 die __PACKAGE__ . " requires PoCo::IRC::State or a subclass thereof";
21             }
22              
23 2         13 $self->{cycling} = { };
24 2         6 $self->{irc} = $irc;
25 2         12 $irc->plugin_register($self, 'SERVER', qw(join kick part quit));
26 2         117 return 1;
27             }
28              
29             sub PCI_unregister {
30 2     2 0 1051 return 1;
31             }
32              
33             sub S_join {
34 2     2 0 99 my ($self, $irc) = splice @_, 0, 2;
35 2         5 my $chan = ${ $_[1] };
  2         78  
36 2         8 delete $self->{cycling}->{$chan};
37 2         7 return PCI_EAT_NONE;
38             }
39              
40             sub S_kick {
41 0     0 0 0 my ($self, $irc) = splice @_, 0, 2;
42 0         0 my $chan = ${ $_[1] };
  0         0  
43 0         0 my $victim = ${ $_[2] };
  0         0  
44 0 0       0 $self->_cycle($chan) if $victim ne $irc->nick_name();
45 0         0 return PCI_EAT_NONE;
46             }
47              
48             sub S_part {
49 2     2 0 63 my ($self, $irc) = splice @_, 0, 2;
50 2         3 my $parter = parse_user(${ $_[0] });
  2         8  
51 2         22 my $chan = ${ $_[1] };
  2         4  
52 2 100       5 $self->_cycle($chan) if $parter ne $irc->nick_name();
53 2         5 return PCI_EAT_NONE;
54             }
55              
56             sub S_quit {
57 0     0 0 0 my ($self, $irc) = splice @_, 0, 2;
58 0         0 my $quitter = parse_user(${ $_[0] });
  0         0  
59 0         0 my $channels = @{ $_[2] }[0];
  0         0  
60 0 0       0 if ($quitter ne $irc->nick_name()) {
61 0         0 for my $chan (@{ $channels }) {
  0         0  
62 0         0 $self->_cycle($chan);
63             }
64             }
65 0         0 return PCI_EAT_NONE;
66             }
67              
68             sub _cycle {
69 1     1   3 my ($self, $chan) = @_;
70 1         2 my $irc = $self->{irc};
71 1 50       5 if ($irc->channel_list($chan) == 1) {
72 1 50       3 if (!$irc->is_channel_operator($chan, $irc->nick_name)) {
73 1         4 $self->{cycling}->{ uc_irc($chan) } = 1;
74 1         12 my $topic = $irc->channel_topic($chan);
75 1         4 $irc->yield(part => $chan);
76 1         89 $irc->yield(join => $chan => $irc->channel_key($chan));
77 1 50       80 $irc->yield(topic => $chan => $topic->{Value}) if defined $topic->{Value};
78 1 50       3 $irc->yield(mode => $chan => '+k ' . $irc->channel_key($chan)) if defined $irc->channel_key($chan);
79             }
80             }
81 1         2 return;
82             }
83              
84             sub is_cycling {
85 1     1 1 327 my ($self, $value) = @_;
86 1 50       5 return 1 if $self->{cycling}->{ uc_irc($value) };
87 0           return;
88             }
89              
90             1;
91              
92             =encoding utf8
93              
94             =head1 NAME
95              
96             POE::Component::IRC::Plugin::CycleEmpty - A PoCo-IRC plugin which cycles
97             channels if they become empty and opless.
98              
99             =head1 SYNOPSIS
100              
101             use POE::Component::IRC::Plugin::CycleEmpty;
102              
103             $irc->plugin_add('CycleEmpty', POE::Component::IRC::Plugin::CycleEmpty->new());
104              
105             =head1 DESCRIPTION
106              
107             POE::Component::IRC::Plugin::CycleEmpty is a L
108             plugin. When a channel member quits, gets kicked, or parts, the plugin will
109             cycle the channel if the IRC component is alone on that channel and is not
110             a channel operator. If there was a topic or a key set on the channel, they
111             will be restored upon rejoining.
112              
113             This is useful for regaining ops in small channels if the IRC network does
114             not have ChanServ or IRCNet's +R channel mode.
115              
116             This plugin requires the IRC component to be
117             L or a subclass thereof.
118              
119             =head1 METHODS
120              
121             =head2 C
122              
123             Returns a plugin object suitable for feeding to
124             L's C method.
125              
126             =head2 C
127              
128             One argument:
129              
130             A channel name
131              
132             Returns 1 if the plugin is currently cycling that channel, 0 otherwise.
133             Useful if need to ignore the fact that the Component just parted the channel
134             in question.
135              
136             =head1 AUTHOR
137              
138             Hinrik Ern SigurEsson, hinrik.sig@gmail.com
139              
140             =cut