File Coverage

blib/lib/POE/Component/IRC/Plugin/Connector.pm
Criterion Covered Total %
statement 78 108 72.2
branch 5 12 41.6
condition 4 9 44.4
subroutine 19 24 79.1
pod 2 11 18.1
total 108 164 65.8


line stmt bran cond sub pod time code
1             package POE::Component::IRC::Plugin::Connector;
2             $POE::Component::IRC::Plugin::Connector::VERSION = '6.95';
3 3     3   2742 use strict;
  3         6  
  3         118  
4 3     3   16 use warnings FATAL => 'all';
  3         4  
  3         207  
5 3     3   14 use Carp;
  3         6  
  3         197  
6 3     3   15 use POE;
  3         6  
  3         22  
7 3     3   1180 use POE::Component::IRC::Plugin qw( :ALL );
  3         4  
  3         4896  
8              
9             sub new {
10 2     2 1 3110 my ($package) = shift;
11 2 50       10 croak "$package requires an even number of arguments" if @_ & 1;
12 2         10 my %args = @_;
13              
14 2         11 $args{ lc $_ } = delete $args{$_} for keys %args;
15 2         18 $args{lag} = 0;
16 2         11 return bless \%args, $package;
17             }
18              
19             sub PCI_register {
20 2     2 0 629 my ($self, $irc) = splice @_, 0, 2;
21              
22 2         10 $self->{irc} = $irc;
23 2         15 POE::Session->create(
24             object_states => [
25             $self => [ qw(_start _auto_ping _reconnect _shutdown _start_ping _start_time_out _stop_ping _time_out) ],
26             ],
27             );
28              
29 2         291 $irc->raw_events(1);
30 2         11 $irc->plugin_register( $self, 'SERVER', qw(connected disconnected 001 error socketerr pong raw) );
31              
32 2         200 return 1;
33             }
34              
35             sub PCI_unregister {
36 2     2 0 1200 my ($self, $irc) = splice @_, 0, 2;
37 2         5 delete $self->{irc};
38 2         9 $poe_kernel->post( $self->{SESSION_ID} => '_shutdown' );
39 2         187 $poe_kernel->refcount_decrement( $self->{SESSION_ID}, __PACKAGE__ );
40 2         79 return 1;
41             }
42              
43             sub S_connected {
44 2     2 0 113 my ($self, $irc) = splice @_, 0, 2;
45 2         15 $poe_kernel->post( $self->{SESSION_ID}, '_start_time_out' );
46 2         318 return PCI_EAT_NONE;
47             }
48              
49             sub S_001 {
50 2     2 0 82 my ($self, $irc) = splice @_, 0, 2;
51 2         29 $poe_kernel->post( $self->{SESSION_ID}, '_start_ping' );
52 2         265 return PCI_EAT_NONE;
53             }
54              
55             sub S_disconnected {
56 1     1 0 48 my ($self, $irc) = splice @_, 0, 2;
57 1         6 $poe_kernel->post( $self->{SESSION_ID}, '_stop_ping' );
58 1         172 $poe_kernel->post( $self->{SESSION_ID}, '_reconnect' );
59 1         133 return PCI_EAT_NONE;
60             }
61              
62             sub S_error {
63 2     2 0 145 my ($self, $irc) = splice @_, 0, 2;
64 2         14 $poe_kernel->post( $self->{SESSION_ID}, '_stop_ping' );
65 2         328 $poe_kernel->post( $self->{SESSION_ID}, '_reconnect' );
66 2         262 return PCI_EAT_NONE;
67             }
68              
69             sub S_socketerr {
70 0     0 0 0 my ($self, $irc) = splice @_, 0, 2;
71 0         0 $poe_kernel->post( $self->{SESSION_ID}, '_stop_ping' );
72 0         0 $poe_kernel->post( $self->{SESSION_ID}, '_reconnect' );
73 0         0 return PCI_EAT_NONE;
74             }
75              
76             sub S_pong {
77 0     0 0 0 my ($self, $irc) = splice @_, 0, 2;
78 0         0 my $ping = shift @{ $self->{pings} };
  0         0  
79 0 0       0 return PCI_EAT_NONE if !$ping;
80 0         0 $self->{lag} = time() - $ping;
81 0         0 $self->{seen_traffic} = 1;
82 0         0 return PCI_EAT_NONE;
83             }
84              
85             sub S_raw {
86 25     25 0 1409 my ($self,$irc) = splice @_, 0, 2;
87 25         56 $self->{seen_traffic} = 1;
88 25         61 return PCI_EAT_NONE;
89             }
90              
91             sub lag {
92 0     0 1 0 return $_[0]->{lag};
93             }
94              
95             sub _start {
96 2     2   641 my ($kernel, $self) = @_[KERNEL, OBJECT];
97              
98 2         10 $self->{SESSION_ID} = $_[SESSION]->ID();
99 2         19 $kernel->refcount_increment( $self->{SESSION_ID}, __PACKAGE__ );
100 2 50       91 $kernel->yield( '_start_ping' ) if $self->{irc}->connected();
101 2         26 return;
102             }
103              
104             sub _start_ping {
105 2     2   1532 my ($kernel, $self) = @_[KERNEL, OBJECT];
106 2         7 $self->{pings} = [ ];
107 2         11 $kernel->delay( '_time_out' => undef );
108 2   50     345 $kernel->delay( '_auto_ping' => $self->{delay} || 300 );
109 2         431 return;
110             }
111              
112             sub _auto_ping {
113 0     0   0 my ($kernel, $self) = @_[KERNEL, OBJECT];
114              
115 0 0       0 if (!$self->{seen_traffic}) {
116 0         0 my $time = time();
117 0         0 $self->{irc}->yield( 'ping' => $time );
118 0         0 push @{ $self->{pings} }, $time;
  0         0  
119             }
120              
121 0         0 $self->{seen_traffic} = 0;
122 0         0 $kernel->yield( '_start_ping' );
123 0         0 return;
124             }
125              
126             sub _stop_ping {
127 5     5   2340 my ($kernel, $self) = @_[KERNEL, OBJECT];
128 5         13 delete $self->{pings};
129 5         37 $kernel->delay( '_auto_ping' => undef );
130 5         534 $kernel->delay( '_time_out' => undef );
131 5         402 return;
132             }
133              
134             sub _shutdown {
135 2     2   404 my ($kernel,$self) = @_[KERNEL, OBJECT];
136              
137 2         6 $kernel->yield( '_stop_ping' );
138 2         115 $kernel->delay('_reconnect');
139 2         171 return;
140             }
141              
142             sub _reconnect {
143 4     4   2001775 my ($kernel, $self, $session, $sender) = @_[KERNEL, OBJECT, SESSION, SENDER];
144              
145 4         11 my %args;
146 4 50 33     22 if (ref $self->{servers} eq 'ARRAY' && @{ $self->{servers} }) {
  0         0  
147 0         0 @args{qw(Server Port)} = @{ $self->{servers}->[0] };
  0         0  
148 0         0 push @{ $self->{servers} }, shift @{ $self->{servers} };
  0         0  
  0         0  
149             }
150              
151 4 100       19 if ($sender eq $session) {
152 1         13 $self->{irc}->yield('connect' => %args);
153             }
154             else {
155 3   50     16 $kernel->delay( '_reconnect' => $self->{reconnect} || 60 );
156             }
157              
158 4         825 return;
159             }
160              
161             sub _start_time_out {
162 2     2   439 my ($kernel, $self) = @_[KERNEL, OBJECT];
163 2   50     36 $kernel->delay( '_time_out' => $self->{timeout} || 60 );
164 2         450 return;
165             }
166              
167             sub _time_out {
168 0     0     my ($kernel, $self) = @_[KERNEL, OBJECT];
169 0           $self->{irc}->disconnect();
170 0           return;
171             }
172              
173             1;
174              
175             =encoding utf8
176              
177             =head1 NAME
178              
179             POE::Component::IRC::Plugin::Connector - A PoCo-IRC plugin that deals with the
180             messy business of staying connected to an IRC server
181              
182             =head1 SYNOPSIS
183              
184             use POE qw(Component::IRC Component::IRC::Plugin::Connector);
185              
186             my $irc = POE::Component::IRC->spawn();
187              
188             POE::Session->create(
189             package_states => [
190             main => [ qw(_start lag_o_meter) ],
191             ],
192             );
193              
194             $poe_kernel->run();
195              
196             sub _start {
197             my ($kernel, $heap) = @_[KERNEL ,HEAP];
198             $irc->yield( register => 'all' );
199              
200             $heap->{connector} = POE::Component::IRC::Plugin::Connector->new();
201              
202             $irc->plugin_add( 'Connector' => $heap->{connector} );
203              
204             $irc->yield ( connect => { Nick => 'testbot', Server => 'someserver.com' } );
205              
206             $kernel->delay( 'lag_o_meter' => 60 );
207             return;
208             }
209              
210             sub lag_o_meter {
211             my ($kernel,$heap) = @_[KERNEL,HEAP];
212             print 'Time: ' . time() . ' Lag: ' . $heap->{connector}->lag() . "\n";
213             $kernel->delay( 'lag_o_meter' => 60 );
214             return;
215             }
216              
217             =head1 DESCRIPTION
218              
219             POE::Component::IRC::Plugin::Connector is a L
220             plugin that deals with making sure that your IRC bot stays connected to the IRC
221             network of your choice. It implements the general algorithm as demonstrated at
222             L.
223              
224             =head1 METHODS
225              
226             =head2 C
227              
228             Takes two optional arguments:
229              
230             B<'delay'>, the frequency, in seconds, at which the plugin will ping the IRC
231             server. Defaults to 300.
232              
233             B<'reconnect'>, the time in seconds, to wait before trying to reconnect to
234             the server. Defaults to 60.
235              
236             B<'servers'>, an array reference of IRC servers to consider. Each element should
237             be an array reference containing a server host and (optionally) a port number.
238             The plugin will cycle through this list of servers whenever it reconnects.
239              
240             Returns a plugin object suitable for use in
241             L's C method.
242              
243             =head2 C
244              
245             Returns the current 'lag' in seconds between sending PINGs to the IRC server
246             and getting PONG responses. Probably not likely to be wholely accurate.
247              
248             =head1 AUTHOR
249              
250             Chris "BinGOs" Williams
251              
252             =head1 SEE ALSO
253              
254             L
255              
256             L
257              
258             =cut