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