File Coverage

blib/lib/POE/Component/IRC.pm
Criterion Covered Total %
statement 454 719 63.1
branch 156 338 46.1
condition 50 135 37.0
subroutine 63 84 75.0
pod 27 51 52.9
total 750 1327 56.5


line stmt bran cond sub pod time code
1             package POE::Component::IRC;
2             $POE::Component::IRC::VERSION = '6.95';
3 79     79   8488800 use strict;
  79         176  
  79         3485  
4 79     79   433 use warnings FATAL => 'all';
  79         231  
  79         5643  
5 79     79   491 use Carp;
  79         156  
  79         7551  
6 79         578 use POE qw(Wheel::SocketFactory Wheel::ReadWrite Driver::SysRW
7 79     79   3852 Filter::Line Filter::Stream Filter::Stackable);
  79         252099  
8 79     79   2242646 use POE::Filter::IRCD;
  79         209733  
  79         11390  
9 79     79   47796 use POE::Filter::IRC::Compat;
  79         422  
  79         3643  
10 79     79   39348 use POE::Component::IRC::Constants qw(:ALL);
  79         307  
  79         14872  
11 79     79   32125 use POE::Component::IRC::Plugin qw(:ALL);
  79         270  
  79         10275  
12 79     79   48130 use POE::Component::IRC::Plugin::DCC;
  79         311  
  79         3340  
13 79     79   44938 use POE::Component::IRC::Plugin::ISupport;
  79         269  
  79         3722  
14 79     79   43234 use POE::Component::IRC::Plugin::Whois;
  79         606  
  79         4286  
15 79     79   645 use Socket qw(AF_INET SOCK_STREAM unpack_sockaddr_in inet_ntoa inet_aton);
  79         199  
  79         7679  
16 79     79   596 use base qw(POE::Component::Syndicator);
  79         783  
  79         54217  
17              
18             our ($GOT_SSL, $GOT_CLIENT_DNS, $GOT_SOCKET6, $GOT_ZLIB);
19              
20             BEGIN {
21 79     79   1025205 eval {
22 79         10653 require POE::Component::SSLify;
23 0         0 import POE::Component::SSLify qw( Client_SSLify SSLify_ContextCreate );
24 0         0 $GOT_SSL = 1;
25             };
26 79         461 eval {
27 79         49205 require POE::Component::Client::DNS;
28 79 50       6533308 $GOT_CLIENT_DNS = 1 if $POE::Component::Client::DNS::VERSION >= 0.99;
29             };
30 79         489 eval {
31 79         10986 require POE::Filter::Zlib::Stream;
32 0 0       0 $GOT_ZLIB = 1 if $POE::Filter::Zlib::Stream::VERSION >= 1.96;
33             };
34             # Socket6 provides AF_INET6 where earlier Perls' Socket don't.
35 79         361 eval {
36 79         9662 Socket->import(qw(AF_INET6 unpack_sockaddr_in6 inet_ntop));
37 79         516 $GOT_SOCKET6 = 1;
38             };
39 79 50       956723 if (!$GOT_SOCKET6) {
40 0         0 eval {
41 0         0 require Socket6;
42 0         0 Socket6->import(qw(AF_INET6 unpack_sockaddr_in6 inet_ntop));
43 0         0 $GOT_SOCKET6 = 1;
44             };
45 0 0       0 if (!$GOT_SOCKET6) {
46             # provide a dummy sub so code compiles
47 0         0 *AF_INET6 = sub { ~0 };
  0         0  
48             }
49             }
50             }
51              
52             # BINGOS: I have bundled up all the stuff that needs changing
53             # for inherited classes into _create. This gets called from 'spawn'.
54             # $self->{OBJECT_STATES_ARRAYREF} contains event mappings to methods that have
55             # the same name, gets passed to POE::Session->create as $self => [ ];
56             # $self->{OBJECT_STATES_HASHREF} contains event mappings to methods, where the
57             # event and the method have diferent names.
58             # $self->{IRC_CMDS} contains the traditional %irc_commands, mapping commands
59             # to events and the priority that the command has.
60             sub _create {
61 115     115   363 my ($self) = @_;
62              
63             $self->{IRC_CMDS} = {
64 115         12102 rehash => [ PRI_HIGH, 'noargs', ],
65             die => [ PRI_HIGH, 'noargs', ],
66             restart => [ PRI_HIGH, 'noargs', ],
67             quit => [ PRI_NORMAL, 'oneoptarg', ],
68             version => [ PRI_HIGH, 'oneoptarg', ],
69             time => [ PRI_HIGH, 'oneoptarg', ],
70             trace => [ PRI_HIGH, 'oneoptarg', ],
71             admin => [ PRI_HIGH, 'oneoptarg', ],
72             info => [ PRI_HIGH, 'oneoptarg', ],
73             away => [ PRI_HIGH, 'oneoptarg', ],
74             users => [ PRI_HIGH, 'oneoptarg', ],
75             lusers => [ PRI_HIGH, 'oneoptarg', ],
76             locops => [ PRI_HIGH, 'oneoptarg', ],
77             operwall => [ PRI_HIGH, 'oneoptarg', ],
78             wallops => [ PRI_HIGH, 'oneoptarg', ],
79             motd => [ PRI_HIGH, 'oneoptarg', ],
80             who => [ PRI_HIGH, 'oneoptarg', ],
81             nick => [ PRI_HIGH, 'onlyonearg', ],
82             oper => [ PRI_HIGH, 'onlytwoargs', ],
83             invite => [ PRI_HIGH, 'onlytwoargs', ],
84             squit => [ PRI_HIGH, 'onlytwoargs', ],
85             kill => [ PRI_HIGH, 'onlytwoargs', ],
86             privmsg => [ PRI_NORMAL, 'privandnotice', ],
87             privmsglo => [ PRI_NORMAL+1, 'privandnotice', ],
88             privmsghi => [ PRI_NORMAL-1, 'privandnotice', ],
89             notice => [ PRI_NORMAL, 'privandnotice', ],
90             noticelo => [ PRI_NORMAL+1, 'privandnotice', ],
91             noticehi => [ PRI_NORMAL-1, 'privandnotice', ],
92             squery => [ PRI_NORMAL, 'privandnotice', ],
93             join => [ PRI_HIGH, 'oneortwo', ],
94             summon => [ PRI_HIGH, 'oneortwo', ],
95             sconnect => [ PRI_HIGH, 'oneandtwoopt', ],
96             whowas => [ PRI_HIGH, 'oneandtwoopt', ],
97             stats => [ PRI_HIGH, 'spacesep', ],
98             links => [ PRI_HIGH, 'spacesep', ],
99             mode => [ PRI_HIGH, 'spacesep', ],
100             servlist => [ PRI_HIGH, 'spacesep', ],
101             cap => [ PRI_HIGH, 'spacesep', ],
102             part => [ PRI_HIGH, 'commasep', ],
103             names => [ PRI_HIGH, 'commasep', ],
104             list => [ PRI_HIGH, 'commasep', ],
105             whois => [ PRI_HIGH, 'commasep', ],
106             ctcp => [ PRI_HIGH, 'ctcp', ],
107             ctcpreply => [ PRI_HIGH, 'ctcp', ],
108             ping => [ PRI_HIGH, 'oneortwo', ],
109             pong => [ PRI_HIGH, 'oneortwo', ],
110             };
111              
112 5290         15586 my %event_map = map {($_ => $self->{IRC_CMDS}->{$_}->[CMD_SUB])}
113 115         565 keys %{ $self->{IRC_CMDS} };
  115         1058  
114              
115             $self->{OBJECT_STATES_HASHREF} = {
116 115         2958 %event_map,
117             quote => 'sl',
118             };
119              
120 115         1173 $self->{OBJECT_STATES_ARRAYREF} = [qw(
121             syndicator_started
122             _parseline
123             _sock_down
124             _sock_failed
125             _sock_up
126             _socks_proxy_connect
127             _socks_proxy_response
128             debug
129             connect
130             _resolve_addresses
131             _do_connect
132             _quit_timeout
133             _send_login
134             _got_dns_response
135             ison
136             kick
137             remove
138             nickserv
139             shutdown
140             sl
141             sl_login
142             sl_high
143             sl_delayed
144             sl_prioritized
145             topic
146             userhost
147             )];
148              
149 115         959 return;
150             }
151              
152             # BINGOS: the component can now configure itself via _configure() from
153             # either spawn() or connect()
154             ## no critic (Subroutines::ProhibitExcessComplexity)
155             sub _configure {
156 206     206   2926 my ($self, $args) = @_;
157 206         443 my $spawned = 0;
158              
159 206 50 33     2963 if (ref $args eq 'HASH' && keys %{ $args }) {
  206         953  
160 206         1284 $spawned = delete $args->{spawned};
161 206         2815 $self->{use_localaddr} = delete $args->{localaddr};
162 206         377 @{ $self }{ keys %{ $args } } = values %{ $args };
  206         748  
  206         479  
  206         557  
163             }
164              
165 206 50       899 if ($ENV{POCOIRC_DEBUG}) {
166 0         0 $self->{debug} = 1;
167 0         0 $self->{plugin_debug} = 1;
168             }
169              
170 206 50       2788 if ($self->{debug}) {
171 0         0 $self->{ircd_filter}->debug(1);
172 0         0 $self->{ircd_compat}->debug(1);
173             }
174              
175 206 50 66     1160 if ($self->{useipv6} && !$GOT_SOCKET6) {
176 0         0 warn "'useipv6' option specified, but Socket/Socket6 was not found\n";
177             }
178              
179 206 50 33     1731 if ($self->{usessl} && !$GOT_SSL) {
180 0         0 warn "'usessl' option specified, but POE::Component::SSLify was not found\n";
181             }
182              
183 206 100       902 $self->{dcc}->nataddr($self->{nataddr}) if exists $self->{nataddr};
184 206 50       2781 $self->{dcc}->dccports($self->{dccports}) if exists $self->{dccports};
185              
186 206 100       896 $self->{port} = 6667 if !$self->{port};
187 206 100       3194 $self->{msg_length} = 450 if !defined $self->{msg_length};
188              
189 206 50       697 if ($self->{use_localaddr}) {
190             $self->{localaddr} = $self->{use_localaddr}
191 0 0       0 . ($self->{localport} ? (':'.$self->{localport}) : '');
192             }
193              
194             # Make sure that we have reasonable defaults for all the attributes.
195             # The "IRC*" variables are ircII environment variables.
196 206 100       2227 if (!defined $self->{nick}) {
197             $self->{nick} = $ENV{IRCNICK} || eval { scalar getpwuid($>) }
198 115   0     688 || $ENV{USER} || $ENV{LOGNAME} || 'WankerBot';
199             }
200              
201 206 100       3083 if (!defined $self->{username}) {
202             $self->{username} = eval { scalar getpwuid($>) } || $ENV{USER}
203 115   0     242 || $ENV{LOGNAME} || 'foolio';
204             }
205              
206 206 100       718 if (!defined $self->{ircname}) {
207 115   50     770 $self->{ircname} = $ENV{IRCNAME} || eval { (getpwuid $>)[6] }
208             || 'Just Another Perl Hacker';
209             }
210              
211 206 50 66     1377 if (!defined $self->{server} && !$spawned) {
212 0 0       0 die "No IRC server specified\n" if !$ENV{IRCSERVER};
213 0         0 $self->{server} = $ENV{IRCSERVER};
214             }
215              
216 206 50       754 if (defined $self->{webirc}) {
217 0 0       0 if (!(ref $self->{webirc} ne 'HASH')) {
218 0         0 die "webirc param expects a hashref";
219             }
220 0         0 for my $expect_key (qw(pass user host ip)) {
221 0 0       0 if (!exists $self->{webirc}{$expect_key}) {
222 0         0 die "webirc value is missing key '$expect_key'";
223             }
224             }
225             }
226              
227 206         568 return;
228             }
229              
230             sub debug {
231 0     0 1 0 my ($self, $switch) = @_[OBJECT, ARG0];
232              
233 0         0 $self->{debug} = $switch;
234 0         0 $self->{ircd_filter}->debug( $switch );
235 0         0 $self->{ircd_compat}->debug( $switch );
236 0         0 return;
237             }
238              
239             # Parse a message from the IRC server and generate the appropriate
240             # event(s) for listening sessions.
241             sub _parseline {
242 2552     2552   184097 my ($session, $self, $ev) = @_[SESSION, OBJECT, ARG0];
243              
244 2552 50       7840 return if !$ev->{name};
245 2552 100       6733 $self->send_event(irc_raw => $ev->{raw_line} ) if $self->{raw};
246              
247             # record our nickname
248 2552 100       20433 if ( $ev->{name} eq '001' ) {
249 91         904 $self->{INFO}{RealNick} = ( split / /, $ev->{raw_line} )[2];
250             }
251              
252 2552         6800 $ev->{name} = 'irc_' . $ev->{name};
253 2552         4711 $self->send_event( $ev->{name}, @{$ev->{args}} );
  2552         11274  
254              
255 2552 100       397250 if ($ev->{name} =~ /^irc_ctcp_(.+)$/) {
256 12         28 $self->send_event(irc_ctcp => $1 => @{$ev->{args}});
  12         49  
257             }
258              
259 2552         9961 return;
260             }
261              
262             # Internal function called when a socket is closed.
263             sub _sock_down {
264 91     91   42138 my ($kernel, $self) = @_[KERNEL, OBJECT];
265              
266             # Destroy the RW wheel for the socket.
267 91         610 delete $self->{socket};
268 91         29312 delete $self->{localaddr};
269 91         344 $self->{connected} = 0;
270              
271             # Stop any delayed sends.
272 91         269 $self->{send_queue} = [ ];
273 91         374 $self->{send_time} = 0;
274 91         532 $kernel->delay( sl_delayed => undef );
275              
276             # Reset the filters if necessary
277 91         8004 $self->_compress_uplink( 0 );
278 91         405 $self->_compress_downlink( 0 );
279 91         808 $self->{ircd_compat}->chantypes( [ '#', '&' ] );
280 91         376 $self->{ircd_compat}->identifymsg(0);
281              
282             # post a 'irc_disconnected' to each session that cares
283 91         630 $self->send_event(irc_disconnected => $self->{server} );
284 91         12098 return;
285             }
286              
287             sub disconnect {
288 0     0 1 0 my ($self) = @_;
289 0         0 $self->yield('_sock_down');
290 0         0 return;
291             }
292              
293             # Internal function called when a socket fails to be properly opened.
294             sub _sock_failed {
295 1     1   387 my ($self, $op, $errno, $errstr) = @_[OBJECT, ARG0..ARG2];
296              
297 1         4 delete $self->{socketfactory};
298 1         19 $self->send_event(irc_socketerr => "$op error $errno: $errstr" );
299 1         79 return;
300             }
301              
302             # Internal function called when a connection is established.
303             sub _sock_up {
304 91     91   118074 my ($kernel, $self, $session, $socket) = @_[KERNEL, OBJECT, SESSION, ARG0];
305              
306             # We no longer need the SocketFactory wheel. Scrap it.
307 91         655 delete $self->{socketfactory};
308              
309             # Remember what IP address we're connected through, for multihomed boxes.
310 91         2257 my $localaddr;
311 91 50       679 if ($GOT_SOCKET6) {
312 91         187 eval {
313 91         2527 $localaddr = (unpack_sockaddr_in6( getsockname $socket ))[1];
314 1         8 $localaddr = inet_ntop( AF_INET6, $localaddr );
315             };
316             }
317              
318 91 100       971 if ( !$localaddr ) {
319 90         743 $localaddr = (unpack_sockaddr_in( getsockname $socket ))[1];
320 90         498 $localaddr = inet_ntoa($localaddr);
321             }
322              
323 91         319 $self->{localaddr} = $localaddr;
324              
325 91 50       461 if ( $self->{socks_proxy} ) {
326 0         0 $self->{socket} = POE::Wheel::ReadWrite->new(
327             Handle => $socket,
328             Driver => POE::Driver::SysRW->new(),
329             Filter => POE::Filter::Stream->new(),
330             InputEvent => '_socks_proxy_response',
331             ErrorEvent => '_sock_down',
332             );
333              
334 0 0       0 if ( !$self->{socket} ) {
335 0         0 $self->send_event(irc_socketerr =>
336             "Couldn't create ReadWrite wheel for SOCKS socket" );
337 0         0 return;
338             }
339              
340 0         0 my $packet;
341 0 0       0 if ( _ip_is_ipv4( $self->{server} ) ) {
342             # SOCKS 4
343             $packet = pack ('CCn', 4, 1, $self->{port}) .
344 0   0     0 inet_aton($self->{server}) . ($self->{socks_id} || '') . (pack 'x');
345             }
346             else {
347             # SOCKS 4a
348             $packet = pack ('CCn', 4, 1, $self->{port}) .
349             inet_aton('0.0.0.1') . ($self->{socks_id} || '') . (pack 'x') .
350 0   0     0 $self->{server} . (pack 'x');
351             }
352              
353 0         0 $self->{socket}->put( $packet );
354 0         0 return;
355             }
356              
357             # ssl!
358 91 0 33     322 if ($GOT_SSL and $self->{usessl}) {
359 0         0 eval {
360 0         0 my ($ctx);
361              
362 0 0 0     0 if( $self->{sslctx} )
    0          
363             {
364 0         0 $ctx = $self->{sslctx};
365             }
366             elsif( $self->{sslkey} && $self->{sslcert} )
367             {
368 0         0 $ctx = SSLify_ContextCreate( $self->{sslkey}, $self->{sslcert} );
369             }
370             else
371             {
372 0         0 $ctx = undef;
373             }
374              
375 0         0 $socket = Client_SSLify($socket, undef, undef, $ctx);
376             };
377              
378 0 0       0 if ($@) {
379 0         0 chomp $@;
380 0         0 warn "Couldn't use an SSL socket: $@\n";
381 0         0 $self->{usessl} = 0;
382             }
383             }
384              
385 91 50       301 if ( $self->{compress} ) {
386 0         0 $self->_compress_uplink(1);
387 0         0 $self->_compress_downlink(1);
388             }
389              
390             # Create a new ReadWrite wheel for the connected socket.
391             $self->{socket} = POE::Wheel::ReadWrite->new(
392             Handle => $socket,
393             Driver => POE::Driver::SysRW->new(),
394             InputFilter => $self->{srv_filter},
395             OutputFilter => $self->{out_filter},
396 91         709 InputEvent => '_parseline',
397             ErrorEvent => '_sock_down',
398             );
399              
400 91 50       36145 if ($self->{socket}) {
401 91         368 $self->{connected} = 1;
402             }
403             else {
404 0         0 $self->send_event(irc_socketerr => "Couldn't create ReadWrite wheel for IRC socket");
405 0         0 return;
406             }
407              
408             # Post a 'irc_connected' event to each session that cares
409 91         637 $self->send_event(irc_connected => $self->{server} );
410              
411             # CONNECT if we're using a proxy
412 91 50       13490 if ($self->{proxy}) {
413             # The original proxy code, AFAIK, did not actually work
414             # with an HTTP proxy.
415             $self->call(
416             'sl_login',
417 0         0 'CONNECT ' . $self->{server} . ':' . $self->{port} . " HTTP/1.0\n\n",
418             );
419              
420             # KLUDGE: Also, the original proxy code assumes the connection
421             # is instantaneous Since this is not always the case, mess with
422             # the queueing so that the sent text is delayed...
423 0         0 $self->{send_time} = time() + 10;
424             }
425              
426 91         437 $kernel->yield('_send_login');
427 91         7857 return;
428             }
429              
430             sub _socks_proxy_response {
431 0     0   0 my ($kernel, $self, $session, $input) = @_[KERNEL, OBJECT, SESSION, ARG0];
432              
433 0 0       0 if (length $input != 8) {
434 0         0 $self->send_event(
435             'irc_socks_failed',
436             'Mangled response from SOCKS proxy',
437             $input,
438             );
439 0         0 $self->disconnect();
440 0         0 return;
441             }
442              
443 0         0 my @resp = unpack 'CCnN', $input;
444 0 0 0     0 if (@resp != 4 || $resp[0] ne '0' || $resp[1] !~ /^(?:90|91|92|93)$/) {
      0        
445 0         0 $self->send_event(
446             'irc_socks_failed',
447             'Mangled response from SOCKS proxy',
448             $input,
449             );
450 0         0 $self->disconnect();
451 0         0 return;
452             }
453              
454 0 0       0 if ( $resp[1] eq '90' ) {
455 0         0 $kernel->call($session => '_socks_proxy_connect');
456 0         0 $self->{connected} = 1;
457 0         0 $self->send_event( 'irc_connected', $self->{server} );
458 0         0 $kernel->yield('_send_login');
459             }
460             else {
461             $self->send_event(
462             'irc_socks_rejected',
463             $resp[1],
464             $self->{socks_proxy},
465             $self->{socks_port},
466             $self->{socks_id},
467 0         0 );
468 0         0 $self->disconnect();
469             }
470              
471 0         0 return;
472             }
473              
474             sub _socks_proxy_connect {
475 0     0   0 my ($kernel, $self) = @_[KERNEL, OBJECT];
476 0         0 $self->{socket}->event( InputEvent => '_parseline' );
477 0         0 $self->{socket}->set_input_filter( $self->{srv_filter} );
478 0         0 $self->{socket}->set_output_filter( $self->{out_filter} );
479 0         0 return;
480             }
481              
482             sub _send_login {
483 91     91   31377 my ($kernel, $self, $session) = @_[KERNEL, OBJECT, SESSION];
484              
485             # Now that we're connected, attempt to log into the server.
486              
487             # for servers which support CAP, it's customary to start with that
488 91         436 $kernel->call($session, 'sl_login', 'CAP REQ :identify-msg');
489 91         913 $kernel->call($session, 'sl_login', 'CAP REQ :multi-prefix');
490 91         900 $kernel->call($session, 'sl_login', 'CAP LS');
491 91         798 $kernel->call($session, 'sl_login', 'CAP END');
492              
493             # If we were told to use WEBIRC to spoof our host/IP, do so:
494 91 50       962 if (defined $self->{webirc}) {
495             $kernel->call($session => sl_login => 'WEBIRC '
496 0         0 . join " ", @{$self->{webirc}}{qw(pass user ip host)}
  0         0  
497             );
498             }
499              
500 91 100       436 if (defined $self->{password}) {
501 1         6 $kernel->call($session => sl_login => 'PASS ' . $self->{password});
502             }
503 91         598 $kernel->call($session => sl_login => 'NICK ' . $self->{nick});
504             $kernel->call(
505             $session,
506             'sl_login',
507             'USER ' .
508             join(' ', $self->{username},
509             (defined $self->{bitmode} ? $self->{bitmode} : 8),
510             '*',
511             ':' . $self->{ircname}
512 91 50       1449 ),
513             );
514              
515             # If we have queued data waiting, its flush loop has stopped
516             # while we were disconnected. Start that up again.
517 91         859 $kernel->delay(sl_delayed => 0);
518              
519 91         16489 return;
520             }
521              
522             # Set up the component's IRC session.
523             sub syndicator_started {
524 115     115 1 234178 my ($kernel, $session, $sender, $self, $alias)
525             = @_[KERNEL, SESSION, SENDER, OBJECT, ARG0, ARG1 .. $#_];
526              
527             # Send queue is used to hold pending lines so we don't flood off.
528             # The count is used to track the number of lines sent at any time.
529 115         546 $self->{send_queue} = [ ];
530 115         460 $self->{send_time} = 0;
531              
532 115         1974 $self->{ircd_filter} = POE::Filter::IRCD->new(debug => $self->{debug});
533 115         5345 $self->{ircd_compat} = POE::Filter::IRC::Compat->new(debug => $self->{debug});
534              
535             my $srv_filters = [
536             POE::Filter::Line->new(
537             InputRegexp => '\015?\012',
538             OutputLiteral => '\015\012',
539             ),
540             $self->{ircd_filter},
541             $self->{ircd_compat},
542 115         1331 ];
543              
544 115         8755 $self->{srv_filter} = POE::Filter::Stackable->new(Filters => $srv_filters);
545 115         2714 $self->{out_filter} = POE::Filter::Stackable->new(Filters => [
546             POE::Filter::Line->new( OutputLiteral => "\015\012" ),
547             ]);
548              
549             # Plugin 'irc_whois' and 'irc_whowas' support
550 115         7232 $self->plugin_add('Whois_' . $self->session_id(),
551             POE::Component::IRC::Plugin::Whois->new()
552             );
553              
554 115         24994 $self->{isupport} = POE::Component::IRC::Plugin::ISupport->new();
555 115         733 $self->plugin_add('ISupport_' . $self->session_id(), $self->{isupport});
556 115         17373 $self->{dcc} = POE::Component::IRC::Plugin::DCC->new();
557 115         868 $self->plugin_add('DCC_' . $self->session_id(), $self->{dcc});
558              
559 115         15983 return 1;
560             }
561              
562             # The handler for commands which have N arguments, separated by commas.
563             sub commasep {
564 9     9 0 1721 my ($kernel, $self, $state, @args) = @_[KERNEL, OBJECT, STATE, ARG0 .. $#_];
565 9         21 my $args;
566              
567 9 50 66     176 if ($state eq 'whois' and @args > 1 ) {
    50 66        
568 0         0 $args = shift @args;
569 0         0 $args .= ' ' . join ',', @args;
570             }
571             elsif ( $state eq 'part' and @args > 1 ) {
572 0 0       0 my $chantypes = join('', @{ $self->isupport('CHANTYPES') || ['#', '&']});
  0         0  
573 0         0 my $message;
574 0 0 0     0 if ($args[-1] =~ / +/ || $args[-1] !~ /^[$chantypes]/) {
575 0         0 $message = pop @args;
576             }
577 0         0 $args = join(',', @args);
578 0 0       0 $args .= " :$message" if defined $message;
579             }
580             else {
581 9         34 $args = join ',', @args;
582             }
583              
584 9         38 my $pri = $self->{IRC_CMDS}->{$state}->[CMD_PRI];
585 9         23 $state = uc $state;
586 9 50       37 $state .= " $args" if defined $args;
587 9         39 $kernel->yield(sl_prioritized => $pri, $state );
588              
589 9         956 return;
590             }
591              
592             # Get variables in order for openning a connection
593             sub connect {
594 92     92 1 5186849 my ($kernel, $self, $session, $sender, $args)
595             = @_[KERNEL, OBJECT, SESSION, SENDER, ARG0];
596              
597 92 100       430 if ($args) {
598 91         184 my %arg;
599 91 50       386 %arg = @{ $args } if ref $args eq 'ARRAY';
  0         0  
600 91 50       468 %arg = %{ $args } if ref $args eq 'HASH';
  91         509  
601 91         719 $arg{ lc $_ } = delete $arg{$_} for keys %arg;
602 91         2561 $self->_configure( \%arg );
603             }
604              
605 92 50 33     970 if ( $self->{resolver} && $self->{res_addresses}
      33        
606 0         0 && @{ $self->{res_addresses} } ) {
607 0         0 push @{ $self->{res_addresses} }, $self->{server};
  0         0  
608 0         0 $self->{resolved_server} = shift @{ $self->{res_addresses} };
  0         0  
609             }
610              
611             # try and use non-blocking resolver if needed
612 92 50 33     3188 if ( $self->{resolver} && !_ip_get_version( $self->{server} )
      33        
613             && !$self->{nodns} ) {
614             $kernel->yield(
615             '_resolve_addresses',
616             $self->{server},
617 0 0 0     0 ( $self->{useipv6} && $GOT_SOCKET6 ? 'AAAA' : 'A' ),
618             );
619             }
620             else {
621 92         547 $kernel->yield('_do_connect');
622             }
623              
624 92         10138 $self->{INFO}{RealNick} = $self->{nick};
625 92         459 return;
626             }
627              
628             sub _resolve_addresses {
629 0     0   0 my ($kernel, $self, $hostname, $type) = @_[KERNEL, OBJECT, ARG0 .. ARG1];
630              
631             my $response = $self->{resolver}->resolve(
632 0         0 event => '_got_dns_response',
633             host => $hostname,
634             type => $type,
635             context => { },
636             );
637              
638 0 0       0 $kernel->yield(_got_dns_response => $response) if $response;
639 0         0 return;
640             }
641              
642             # open the connection
643             sub _do_connect {
644 92     92   28284 my ($kernel, $self, $session) = @_[KERNEL, OBJECT, SESSION];
645 92         308 my $domain = AF_INET;
646              
647             # Disconnect if we're already logged into a server.
648 92 50       617 $kernel->call($session => 'quit') if $self->{socket};
649              
650 92 50 33     629 if ($self->{socks_proxy} && !$self->{socks_port}) {
651 0         0 $self->{socks_port} = 1080;
652             }
653              
654 92         307 for my $address (qw(socks_proxy proxy server resolved_server use_localaddr)) {
655 460 100 100     1782 next if !$self->{$address} || !_ip_is_ipv6( $self->{$address} );
656 1 50       4 if (!$GOT_SOCKET6) {
657 0         0 warn "IPv6 address specified for '$address' but Socket/Socket6 not found\n";
658 0         0 return;
659             }
660 1         19 $domain = AF_INET6;
661             }
662              
663             $self->{socketfactory} = POE::Wheel::SocketFactory->new(
664             SocketDomain => $domain,
665             SocketType => SOCK_STREAM,
666             SocketProtocol => 'tcp',
667             RemoteAddress => $self->{socks_proxy} || $self->{proxy} || $self->{resolved_server} || $self->{server},
668             RemotePort => $self->{socks_port} || $self->{proxyport} || $self->{port},
669             SuccessEvent => '_sock_up',
670             FailureEvent => '_sock_failed',
671 92 50 33     3110 ($self->{use_localaddr} ? (BindAddress => $self->{use_localaddr}) : ()),
      33        
672             );
673              
674 92         63362 return;
675             }
676              
677             # got response from POE::Component::Client::DNS
678             sub _got_dns_response {
679 0     0   0 my ($kernel, $self, $response) = @_[KERNEL, OBJECT, ARG0];
680              
681 0         0 my $type = uc $response->{type};
682 0         0 my $net_dns_packet = $response->{response};
683 0         0 my $net_dns_errorstring = $response->{error};
684 0         0 $self->{res_addresses} = [ ];
685              
686 0 0       0 if (!defined $net_dns_packet) {
687 0         0 $self->send_event(irc_socketerr => $net_dns_errorstring );
688 0         0 return;
689             }
690              
691 0         0 my @net_dns_answers = $net_dns_packet->answer;
692              
693 0         0 for my $net_dns_answer (@net_dns_answers) {
694 0 0       0 next if $net_dns_answer->type !~ /^A/;
695 0         0 push @{ $self->{res_addresses} }, $net_dns_answer->rdstring;
  0         0  
696             }
697              
698 0 0 0     0 if ( !@{ $self->{res_addresses} } && $type eq 'AAAA') {
  0         0  
699 0         0 $kernel->yield(_resolve_addresses => $self->{server}, 'A');
700 0         0 return;
701             }
702              
703 0 0       0 if ( !@{ $self->{res_addresses} } ) {
  0         0  
704 0         0 $self->send_event(irc_socketerr => 'Unable to resolve ' . $self->{server});
705 0         0 return;
706             }
707              
708 0 0       0 if ( my $address = shift @{ $self->{res_addresses} } ) {
  0         0  
709 0         0 $self->{resolved_server} = $address;
710 0         0 $kernel->yield('_do_connect');
711 0         0 return;
712             }
713              
714 0         0 $self->send_event(irc_socketerr => 'Unable to resolve ' . $self->{server});
715 0         0 return;
716             }
717              
718             # Send a CTCP query or reply, with the same syntax as a PRIVMSG event.
719             sub ctcp {
720 27     27 1 8829 my ($kernel, $state, $self, $to) = @_[KERNEL, STATE, OBJECT, ARG0];
721 27         133 my $message = join ' ', @_[ARG1 .. $#_];
722              
723 27 50 33     215 if (!defined $to || !defined $message) {
724 0         0 warn "The '$state' event requires two arguments\n";
725 0         0 return;
726             }
727              
728             # CTCP-quote the message text.
729 27         73 ($message) = @{$self->{ircd_compat}->put([ $message ])};
  27         204  
730              
731             # Should we send this as a CTCP request or reply?
732 27 100       121 $state = $state eq 'ctcpreply' ? 'notice' : 'privmsg';
733              
734 27         176 $kernel->yield($state, $to, $message);
735 27         2855 return;
736             }
737              
738             # The way /notify is implemented in IRC clients.
739             sub ison {
740 0     0 1 0 my ($kernel, @nicks) = @_[KERNEL, ARG0 .. $#_];
741 0         0 my $tmp = 'ISON';
742              
743 0 0       0 if (!@nicks) {
744 0         0 warn "The 'ison' event requires one or more nicknames\n";
745 0         0 return;
746             }
747              
748             # We can pass as many nicks as we want, as long as it's shorter than
749             # the maximum command length (510). If the list we get is too long,
750             # w'll break it into multiple ISON commands.
751 0         0 while (@nicks) {
752 0         0 my $nick = shift @nicks;
753 0 0       0 if (length($tmp) + length($nick) >= 509) {
754 0         0 $kernel->yield(sl_high => $tmp);
755 0         0 $tmp = 'ISON';
756             }
757 0         0 $tmp .= " $nick";
758             }
759              
760 0         0 $kernel->yield(sl_high => $tmp);
761 0         0 return;
762             }
763              
764             # Tell the IRC server to forcibly remove a user from a channel.
765             sub kick {
766 6     6 1 2908 my ($kernel, $chan, $nick) = @_[KERNEL, ARG0, ARG1];
767 6         33 my $message = join '', @_[ARG2 .. $#_];
768              
769 6 50 33     56 if (!defined $chan || !defined $nick) {
770 0         0 warn "The 'kick' event requires at least two arguments\n";
771 0         0 return;
772             }
773              
774 6 50       31 $nick .= " :$message" if defined $message;
775 6         36 $kernel->yield(sl_high => "KICK $chan $nick");
776 6         748 return;
777             }
778              
779             # Tell the IRC server to forcibly remove a user from a channel. Freenode extension
780             sub remove {
781 0     0 1 0 my ($kernel, $chan, $nick) = @_[KERNEL, ARG0, ARG1];
782 0         0 my $message = join '', @_[ARG2 .. $#_];
783              
784 0 0 0     0 if (!defined $chan || !defined $nick) {
785 0         0 warn "The 'remove' event requires at least two arguments\n";
786 0         0 return;
787             }
788              
789 0 0       0 $nick .= " :$message" if defined $message;
790 0         0 $kernel->yield(sl_high => "REMOVE $chan $nick");
791 0         0 return;
792             }
793              
794             # Interact with NickServ
795             sub nickserv {
796 0     0 1 0 my ($kernel, $self, $state) = @_[KERNEL, OBJECT, STATE];
797 0         0 my $args = join ' ', @_[ARG0 .. $#_];
798              
799 0         0 my $command = 'NICKSERV';
800 0         0 my $version = $self->server_version();
801 0 0 0     0 $command = 'NS' if defined $version && $version =~ /ratbox/i;
802 0 0       0 $command .= " $args" if defined $args;
803              
804 0         0 $kernel->yield(sl_high => $command);
805 0         0 return;
806             }
807              
808             # Set up a new IRC component. Deprecated.
809             sub new {
810 0     0 1 0 my ($package, $alias) = splice @_, 0, 2;
811 0 0       0 croak "$package options should be an even-sized list" if @_ & 1;
812 0         0 my %options = @_;
813              
814 0 0       0 if (!defined $alias) {
815 0         0 croak 'Not enough arguments to POE::Component::IRC::new()';
816             }
817              
818 0         0 carp "Use of ${package}->new() is deprecated, please use spawn()";
819              
820 0         0 my $self = $package->spawn ( alias => $alias, options => \%options );
821 0         0 return $self;
822             }
823              
824             # Set up a new IRC component. New interface.
825             sub spawn {
826 115     115 1 31675092 my ($package) = shift;
827 115 50       774 croak "$package requires an even number of arguments" if @_ & 1;
828 115         647 my %params = @_;
829              
830 115         999 $params{ lc $_ } = delete $params{$_} for keys %params;
831 115 50       710 delete $params{options} if ref $params{options} ne 'HASH';
832              
833 115         420 my $self = bless { }, $package;
834 115         787 $self->_create();
835              
836 115 50       648 if ($ENV{POCOIRC_DEBUG}) {
837 0         0 $params{debug} = 1;
838 0         0 $params{plugin_debug} = 1;
839             }
840              
841 115         356 my $options = delete $params{options};
842 115         302 my $alias = delete $params{alias};
843 115         292 my $plugin_debug = delete $params{plugin_debug};
844              
845             $self->_syndicator_init(
846             prefix => 'irc_',
847             reg_prefix => 'PCI_',
848             types => [SERVER => 'S', USER => 'U'],
849             alias => $alias,
850             register_signal => 'POCOIRC_REGISTER',
851             shutdown_signal => 'POCOIRC_SHUTDOWN',
852             object_states => [
853             $self => delete $self->{OBJECT_STATES_HASHREF},
854             $self => delete $self->{OBJECT_STATES_ARRAYREF},
855 115 100       2434 ],
    50          
856             ($plugin_debug ? (debug => 1) : () ),
857             (ref $options eq 'HASH' ? ( options => $options ) : ()),
858             );
859              
860 115         20820 $params{spawned} = 1;
861 115         2379 $self->_configure(\%params);
862              
863 115 100 33     1348 if (!$params{nodns} && $GOT_CLIENT_DNS && !$self->{resolver}) {
      66        
864 114         842 $self->{resolver} = POE::Component::Client::DNS->spawn(
865             Alias => 'resolver' . $self->session_id()
866             );
867 114         142057 $self->{mydns} = 1;
868             }
869              
870 115         904 return $self;
871             }
872              
873             # The handler for all IRC commands that take no arguments.
874             sub noargs {
875 0     0 0 0 my ($kernel, $state, $arg) = @_[KERNEL, STATE, ARG0];
876 0         0 my $pri = $_[OBJECT]->{IRC_CMDS}->{$state}->[CMD_PRI];
877              
878 0 0       0 if (defined $arg) {
879 0         0 warn "The '$state' event takes no arguments\n";
880 0         0 return;
881             }
882              
883 0         0 $state = uc $state;
884 0         0 $kernel->yield(sl_prioritized => $pri, $state);
885 0         0 return;
886             }
887              
888             # The handler for commands that take one required and two optional arguments.
889             sub oneandtwoopt {
890 0     0 0 0 my ($kernel, $state) = @_[KERNEL, STATE];
891 0         0 my $arg = join '', @_[ARG0 .. $#_];
892 0         0 my $pri = $_[OBJECT]->{IRC_CMDS}->{$state}->[CMD_PRI];
893              
894 0 0       0 $state = 'connect' if $state eq 'sconnect';
895 0         0 $state = uc $state;
896 0 0       0 if (defined $arg) {
897 0 0       0 $arg = ':' . $arg if $arg =~ /\x20/;
898 0         0 $state .= " $arg";
899             }
900              
901 0         0 $kernel->yield(sl_prioritized => $pri, $state);
902 0         0 return;
903             }
904              
905             # The handler for commands that take at least one optional argument.
906             sub oneoptarg {
907 154     154 0 108745 my ($kernel, $state) = @_[KERNEL, STATE];
908 154         849 my $pri = $_[OBJECT]->{IRC_CMDS}->{$state}->[CMD_PRI];
909 154         473 $state = uc $state;
910              
911 154 100       601 if (defined $_[ARG0]) {
912 54         240 my $arg = join '', @_[ARG0 .. $#_];
913 54 100       271 $arg = ':' . $arg if $arg =~ /\x20/;
914 54         156 $state .= " $arg";
915             }
916              
917 154         725 $kernel->yield(sl_prioritized => $pri, $state);
918 154         17984 return;
919             }
920              
921             # The handler for commands which take one required and one optional argument.
922             sub oneortwo {
923 87     87 0 7007880 my ($kernel, $state, $one) = @_[KERNEL, STATE, ARG0];
924 87         415 my $two = join '', @_[ARG1 .. $#_];
925 87         400 my $pri = $_[OBJECT]->{IRC_CMDS}->{$state}->[CMD_PRI];
926              
927 87 50       349 if (!defined $one) {
928 0         0 warn "The '$state' event requires at least one argument\n";
929 0         0 return;
930             }
931              
932 87         362 $state = uc( $state ) . " $one";
933 87 50       317 $state .= " $two" if defined $two;
934 87         493 $kernel->yield(sl_prioritized => $pri, $state);
935 87         8977 return;
936             }
937              
938             # Handler for commands that take exactly one argument.
939             sub onlyonearg {
940 9     9 0 948895 my ($kernel, $state) = @_[KERNEL, STATE];
941 9         45 my $arg = join '', @_[ARG0 .. $#_];
942 9         42 my $pri = $_[OBJECT]->{IRC_CMDS}->{$state}->[CMD_PRI];
943              
944 9 50       35 if (!defined $arg) {
945 0         0 warn "The '$state' event requires one argument\n";
946 0         0 return;
947             }
948              
949 9         28 $state = uc $state;
950 9 50       44 $arg = ':' . $arg if $arg =~ /\x20/;
951 9         22 $state .= " $arg";
952 9         61 $kernel->yield(sl_prioritized => $pri, $state);
953 9         947 return;
954             }
955              
956             # Handler for commands that take exactly two arguments.
957             sub onlytwoargs {
958 1     1 0 250 my ($kernel, $state, $one) = @_[KERNEL, STATE, ARG0];
959 1         5 my ($two) = join '', @_[ARG1 .. $#_];
960 1         6 my $pri = $_[OBJECT]->{IRC_CMDS}->{$state}->[CMD_PRI];
961              
962 1 50 33     8 if (!defined $one || !defined $two) {
963 0         0 warn "The '$state' event requires two arguments\n";
964 0         0 return;
965             }
966              
967 1         3 $state = uc $state;
968 1 50       4 $two = ':' . $two if $two =~ /\x20/;
969 1         3 $state .= " $one $two";
970 1         4 $kernel->yield(sl_prioritized => $pri, $state);
971 1         54 return;
972             }
973              
974             # Handler for privmsg or notice events.
975             sub privandnotice {
976 93     93 0 26068 my ($kernel, $state, $to, $msg) = @_[KERNEL, STATE, ARG0, ARG1];
977 93         450 my $pri = $_[OBJECT]->{IRC_CMDS}->{$state}->[CMD_PRI];
978              
979 93         225 $state =~ s/privmsglo/privmsg/;
980 93         170 $state =~ s/privmsghi/privmsg/;
981 93         254 $state =~ s/noticelo/notice/;
982 93         187 $state =~ s/noticehi/notice/;
983              
984 93 50 33     584 if (!defined $to || !defined $msg) {
985 0         0 warn "The '$state' event requires two arguments\n";
986 0         0 return;
987             }
988              
989 93 100       286 $to = join ',', @$to if ref $to eq 'ARRAY';
990 93         257 $state = uc $state;
991              
992 93         483 $kernel->yield(sl_prioritized => $pri, "$state $to :$msg");
993 93         8707 return;
994             }
995              
996             # Tell the IRC session to go away.
997             sub shutdown {
998 116     116 1 193645 my ($kernel, $self, $sender, $session) = @_[KERNEL, OBJECT, SENDER, SESSION];
999 116 100       729 return if $self->{_shutdown};
1000 115         612 $self->{_shutdown} = $sender->ID();
1001              
1002 115 100       1091 if ($self->logged_in()) {
    50          
1003 2         7 my ($msg, $timeout) = @_[ARG0, ARG1];
1004 2 50       11 $msg = '' if !defined $msg;
1005 2 50       8 $timeout = 5 if !defined $timeout;
1006 2 50       9 $msg = ":$msg" if $msg =~ /\x20/;
1007 2         6 my $cmd = "QUIT $msg";
1008 2         12 $kernel->call($session => sl_high => $cmd);
1009 2         25 $kernel->delay('_quit_timeout', $timeout);
1010 2         244 $self->{_waiting} = 1;
1011             }
1012             elsif ($self->connected()) {
1013 0         0 $self->disconnect();
1014             }
1015             else {
1016 113         2194 $self->_shutdown();
1017             }
1018              
1019 115         3400 return;
1020             }
1021              
1022             sub _quit_timeout {
1023 0     0   0 my ($self) = $_[OBJECT];
1024 0         0 $self->disconnect();
1025 0         0 return;
1026             }
1027              
1028             sub _shutdown {
1029 115     115   356 my ($self) = @_;
1030              
1031 115         1427 $self->_syndicator_destroy($self->{_shutdown});
1032 115         28567 delete $self->{$_} for qw(socketfactory dcc wheelmap);
1033 115 100 66     1641 $self->{resolver}->shutdown() if $self->{resolver} && $self->{mydns};
1034 115         33117 return;
1035             }
1036              
1037             # Send a line of login-priority IRC output. These are things which
1038             # must go first.
1039             sub sl_login {
1040 547     547 0 22315 my ($kernel, $self) = @_[KERNEL, OBJECT];
1041 547         1767 my $arg = join ' ', @_[ARG0 .. $#_];
1042 547         1910 $kernel->yield(sl_prioritized => PRI_LOGIN, $arg );
1043 547         50893 return;
1044             }
1045              
1046             # Send a line of high-priority IRC output. Things like channel/user
1047             # modes, kick messages, and whatever.
1048             sub sl_high {
1049 8     8 0 1329 my ($kernel, $self) = @_[KERNEL, OBJECT];
1050 8         45 my $arg = join ' ', @_[ARG0 .. $#_];
1051 8         45 $kernel->yield(sl_prioritized => PRI_HIGH, $arg );
1052 8         810 return;
1053             }
1054              
1055             # Send a line of normal-priority IRC output to the server. PRIVMSG
1056             # and other random chatter. Uses sl() for compatibility with existing
1057             # code.
1058             sub sl {
1059 5     5 0 1892 my ($kernel, $self) = @_[KERNEL, OBJECT];
1060 5         43 my $arg = join ' ', @_[ARG0 .. $#_];
1061 5         22 $kernel->yield(sl_prioritized => PRI_NORMAL, $arg );
1062 5         483 return;
1063             }
1064              
1065             # Prioritized sl(). This keeps the queue ordered by priority, low to
1066             # high in the UNIX tradition. It also throttles transmission
1067             # following the hybrid ircd's algorithm, so you can't accidentally
1068             # flood yourself off. Thanks to Raistlin for explaining how ircd
1069             # throttles messages.
1070             sub sl_prioritized {
1071 1040     1040 0 184103 my ($kernel, $self, $priority, @args) = @_[KERNEL, OBJECT, ARG0, ARG1];
1072              
1073 1040 50       7323 if (my ($event) = $args[0] =~ /^(\w+)/ ) {
1074             # Let the plugin system process this
1075 1040 50       4723 return 1 if $self->send_user_event($event, \@args) == PCI_EAT_ALL;
1076             }
1077             else {
1078 0         0 warn "Unable to extract the event name from '$args[0]'\n";
1079             }
1080              
1081 1040         187930 my $msg = $args[0];
1082 1040         2239 my $now = time();
1083 1040 100       3999 $self->{send_time} = $now if $self->{send_time} < $now;
1084              
1085             # if we find a newline in the message, take that to be the end of it
1086 1040         3457 $msg =~ s/[\015\012].*//s;
1087              
1088 1040 50       4146 if (bytes::length($msg) > $self->{msg_length} - bytes::length($self->nick_name())) {
1089 0         0 $msg = bytes::substr($msg, 0, $self->{msg_length} - bytes::length($self->nick_name()));
1090             }
1091              
1092 1040 50 66     11632 if (!$self->{flood} && @{ $self->{send_queue} }) {
  14 100 100     128  
      100        
1093 0         0 my $i = @{ $self->{send_queue} };
  0         0  
1094 0   0     0 $i-- while ($i && $priority < $self->{send_queue}->[$i-1]->[MSG_PRI]);
1095 0         0 splice( @{ $self->{send_queue} }, $i, 0, [ $priority, $msg ] );
  0         0  
1096             }
1097             elsif ( !$self->{flood} && $self->{send_time} - $now >= 10
1098             || !defined $self->{socket} ) {
1099 5         13 push( @{$self->{send_queue}}, [ $priority, $msg ] );
  5         22  
1100 5         31 $kernel->delay( sl_delayed => $self->{send_time} - $now - 10 );
1101             }
1102             else {
1103 1035 50       3185 warn ">>> $msg\n" if $self->{debug};
1104 1035 100       2766 $self->send_event(irc_raw_out => $msg) if $self->{raw};
1105 1035         8586 $self->{send_time} += 2 + length($msg) / 120;
1106 1035         4481 $self->{socket}->put($msg);
1107             }
1108              
1109 1040         88066 return;
1110             }
1111              
1112             # Send delayed lines to the ircd. We manage a virtual "send time"
1113             # that progresses into the future based on hybrid ircd's rules every
1114             # time a message is sent. Once we find it ten or more seconds into
1115             # the future, we wait for the realtime clock to catch up.
1116             sub sl_delayed {
1117 96     96 0 5783418 my ($kernel, $self) = @_[KERNEL, OBJECT];
1118              
1119 96 100       484 return if !defined $self->{socket};
1120              
1121 95         229 my $now = time();
1122 95 50       507 $self->{send_time} = $now if $self->{send_time} < $now;
1123              
1124 95   100     331 while (@{ $self->{send_queue} } && ($self->{send_time} - $now < 10)) {
  99         1307  
1125 4         15 my $arg = (shift @{$self->{send_queue}})->[MSG_TEXT];
  4         18  
1126 4 50       22 warn ">>> $arg\n" if $self->{debug};
1127 4 50       21 $self->send_event(irc_raw_out => $arg) if $self->{raw};
1128 4         35 $self->{send_time} += 2 + length($arg) / 120;
1129 4         57 $self->{socket}->put($arg);
1130             }
1131              
1132 95 100       205 if (@{ $self->{send_queue} }) {
  95         432  
1133 2         18 $kernel->delay( sl_delayed => $self->{send_time} - $now - 10 );
1134             }
1135              
1136 95         632 return;
1137             }
1138              
1139             # The handler for commands which have N arguments, separated by spaces.
1140             sub spacesep {
1141 121     121 0 1012233 my ($kernel, $state) = @_[KERNEL, STATE];
1142 121         544 my $args = join ' ', @_[ARG0 .. $#_];
1143 121         430 my $pri = $_[OBJECT]->{IRC_CMDS}->{$state}->[CMD_PRI];
1144              
1145 121         322 $state = uc $state;
1146 121 50       580 $state .= " $args" if defined $args;
1147 121         579 $kernel->yield(sl_prioritized => $pri, $state );
1148 121         13763 return;
1149             }
1150              
1151             # Set or query the current topic on a channel.
1152             sub topic {
1153 6     6 1 901 my ($kernel, $chan, @args) = @_[KERNEL, ARG0..$#_];
1154 6         17 my $topic;
1155 6 100       124 $topic = join '', @args if @args;
1156              
1157 6 100       81 if (defined $topic) {
1158 5         18 $chan .= " :";
1159 5 50       20 $chan .= $topic if length $topic;
1160             }
1161              
1162 6         62 $kernel->yield(sl_prioritized => PRI_NORMAL, "TOPIC $chan");
1163 6         4745 return;
1164             }
1165              
1166             # Asks the IRC server for some random information about particular nicks.
1167             sub userhost {
1168 0     0 1 0 my ($kernel, @nicks) = @_[KERNEL, ARG0 .. $#_];
1169              
1170 0 0       0 if (!@nicks) {
1171 0         0 warn "The 'userhost' event requires at least one nickname\n";
1172 0         0 return;
1173             }
1174              
1175             # According to the RFC, you can only send 5 nicks at a time.
1176 0         0 while (@nicks) {
1177 0         0 $kernel->yield(
1178             'sl_prioritized',
1179             PRI_HIGH,
1180             'USERHOST ' . join(' ', splice(@nicks, 0, 5)),
1181             );
1182             }
1183              
1184 0         0 return;
1185             }
1186              
1187             # Non-event methods
1188              
1189             sub server {
1190 0     0 1 0 my ($self) = @_;
1191 0         0 return $self->{server};
1192             }
1193              
1194             sub port {
1195 0     0 1 0 my ($self) = @_;
1196 0         0 return $self->{port};
1197             }
1198              
1199             sub server_name {
1200 7     7 1 5505 my ($self) = @_;
1201 7         73 return $self->{INFO}{ServerName};
1202             }
1203              
1204             sub server_version {
1205 0     0 1 0 my ($self) = @_;
1206 0         0 return $self->{INFO}{ServerVersion};
1207             }
1208              
1209             sub localaddr {
1210 8     8 1 23 my ($self) = @_;
1211 8         30 return $self->{localaddr};
1212             }
1213              
1214             sub nick_name {
1215 1774     1774 1 60457 my ($self) = @_;
1216 1774         8448 return $self->{INFO}{RealNick};
1217             }
1218              
1219             sub send_queue {
1220 0     0 1 0 my ($self) = @_;
1221              
1222 0 0 0     0 if (defined $self->{send_queue} && ref $self->{send_queue} eq 'ARRAY' ) {
1223 0         0 return scalar @{ $self->{send_queue} };
  0         0  
1224             }
1225 0         0 return;
1226             }
1227              
1228             sub raw_events {
1229 4     4 1 12 my ($self, $value) = @_;
1230 4 50       14 return $self->{raw} if !defined $value;
1231 4         12 $self->{raw} = $value;
1232 4         10 return;
1233             }
1234              
1235             sub connected {
1236 117     117 1 499 my ($self) = @_;
1237 117         512 return $self->{connected};
1238             }
1239              
1240             sub logged_in {
1241 120     120 1 604 my ($self) = @_;
1242 120 100       651 return 1 if $self->{INFO}{LoggedIn};
1243 116         2927 return;
1244             }
1245              
1246             sub _compress_uplink {
1247 91     91   501 my ($self, $value) = @_;
1248              
1249 91 50       510 return if !$GOT_ZLIB;
1250 0 0       0 return $self->{uplink} if !defined $value;
1251              
1252 0 0       0 if ($value) {
1253 0 0       0 $self->{out_filter}->unshift( POE::Filter::Zlib::Stream->new() ) if !$self->{uplink};
1254 0         0 $self->{uplink} = 1;
1255             }
1256             else {
1257 0 0       0 $self->{out_filter}->shift() if $self->{uplink};
1258 0         0 $self->{uplink} = 0;
1259             }
1260              
1261 0         0 return $self->{uplink};
1262             }
1263              
1264             sub _compress_downlink {
1265 91     91   343 my ($self, $value) = @_;
1266              
1267 91 50       379 return if !$GOT_ZLIB;
1268 0 0       0 return $self->{downlink} if !defined $value;
1269              
1270 0 0       0 if ($value) {
1271 0 0       0 $self->{srv_filter}->unshift( POE::Filter::Zlib::Stream->new() ) if !$self->{downlink};
1272 0         0 $self->{downlink} = 1;
1273             }
1274             else {
1275 0 0       0 $self->{srv_filter}->shift() if $self->{uplink};
1276 0         0 $self->{downlink} = 0;
1277             }
1278              
1279 0         0 return $self->{downlink};
1280             }
1281              
1282             sub S_001 {
1283 91     91 0 19800 my ($self, $irc) = splice @_, 0, 2;
1284 91         200 $self->{INFO}{ServerName} = ${ $_[0] };
  91         379  
1285 91         282 $self->{INFO}{LoggedIn} = 1;
1286 91         272 return PCI_EAT_NONE;
1287             }
1288              
1289             sub S_004 {
1290 90     90 0 29251 my ($self, $irc) = splice @_, 0, 2;
1291 90         216 my $args = ${ $_[2] };
  90         246  
1292 90         412 $self->{INFO}{ServerVersion} = $args->[1];
1293 90         292 return PCI_EAT_NONE;
1294             }
1295              
1296             sub S_error {
1297 89     89 0 41844 my ($self, $irc) = splice @_, 0, 2;
1298 89         423 $self->{INFO}{LoggedIn} = 0;
1299 89         284 return PCI_EAT_NONE;
1300             }
1301              
1302             sub S_disconnected {
1303 91     91 0 43394 my ($self, $irc) = splice @_, 0, 2;
1304 91         304 $self->{INFO}{LoggedIn} = 0;
1305              
1306 91 100       396 if ($self->{_waiting}) {
1307 2         11 $poe_kernel->delay('_quit_timeout');
1308 2         207 delete $self->{_waiting};
1309             }
1310              
1311 91 100       335 $self->_shutdown() if $self->{_shutdown};
1312 91         325 return PCI_EAT_NONE;
1313             }
1314              
1315             sub S_shutdown {
1316 115     115 0 251226 my ($self, $irc) = splice @_, 0, 2;
1317 115         438 $self->{INFO}{LoggedIn} = 0;
1318 115         431 return PCI_EAT_NONE;
1319             }
1320              
1321             # Automatically replies to a PING from the server. Do not confuse this
1322             # with CTCP PINGs, which are a wholly different animal that evolved
1323             # much later on the technological timeline.
1324             sub S_ping {
1325 0     0 0 0 my ($self, $irc) = splice @_, 0, 2;
1326 0         0 my $arg = ${ $_[0] };
  0         0  
1327 0         0 $irc->yield(sl_login => "PONG :$arg");
1328 0         0 return PCI_EAT_NONE;
1329             }
1330              
1331             # NICK messages for the purposes of determining our current nickname
1332             sub S_nick {
1333 10     10 0 3939 my ($self, $irc) = splice @_, 0, 2;
1334 10         23 my $nick = ( split /!/, ${ $_[0] } )[0];
  10         45  
1335 10         21 my $new = ${ $_[1] };
  10         23  
1336 10 100       54 $self->{INFO}{RealNick} = $new if ( $nick eq $self->{INFO}{RealNick} );
1337 10         32 return PCI_EAT_NONE;
1338             }
1339              
1340             # tell POE::Filter::IRC::Compat to handle IDENTIFY-MSG
1341             sub S_290 {
1342 0     0 0 0 my ($self, $irc) = splice @_, 0, 2;
1343 0         0 my $text = ${ $_[1] };
  0         0  
1344 0 0       0 $self->{ircd_compat}->identifymsg(1) if $text eq 'IDENTIFY-MSG';
1345 0         0 return PCI_EAT_NONE;
1346             }
1347              
1348             sub S_cap {
1349 3     3 0 1215 my ($self, $irc) = splice @_, 0, 2;
1350 3         7 my $cmd = ${ $_[0] };
  3         10  
1351              
1352 3 100       12 if ($cmd eq 'ACK') {
1353 1 50       3 my $list = ${ $_[1] } eq '*' ? ${ $_[2] } : ${ $_[1] };
  1         5  
  0         0  
  1         3  
1354 1         5 my @enabled = split / /, $list;
1355              
1356 1 50       5 if (grep { $_ =~ /^=?identify-msg$/ } @enabled) {
  1         7  
1357 0         0 $self->{ircd_compat}->identifymsg(1);
1358             }
1359 1 50       2 if (grep { $_ =~ /^-identify-msg$/ } @enabled) {
  1         6  
1360 0         0 $self->{ircd_compat}->identifymsg(0);
1361             }
1362             }
1363 3         11 return PCI_EAT_NONE;
1364             }
1365              
1366             sub S_isupport {
1367 90     90 0 14999 my ($self, $irc) = splice @_, 0, 2;
1368 90         248 my $isupport = ${ $_[0] };
  90         236  
1369 90   50     539 $self->{ircd_compat}->chantypes( $isupport->isupport('CHANTYPES') || [ '#', '&' ] );
1370 90 50       321 $irc->yield(sl_login => 'CAPAB IDENTIFY-MSG') if $isupport->isupport('CAPAB');
1371 90 50       343 $irc->yield(sl_login => 'PROTOCTL NAMESX') if $isupport->isupport('NAMESX');
1372 90 50       383 $irc->yield(sl_login => 'PROTOCTL UHNAMES') if $isupport->isupport('UHNAMES');
1373 90         317 return PCI_EAT_NONE;
1374             }
1375              
1376             # accesses the ISupport plugin
1377             sub isupport {
1378 1672     1672 1 7635 my ($self, @args) = @_;
1379 1672         8855 return $self->{isupport}->isupport(@args);
1380             }
1381              
1382             sub isupport_dump_keys {
1383 0     0 1 0 return $_[0]->{isupport}->isupport_dump_keys();
1384             }
1385              
1386             sub resolver {
1387 2     2 1 2581 return $_[0]->{resolver};
1388             }
1389              
1390             sub _ip_get_version {
1391 92     92   352 my ($ip) = @_;
1392 92 50       417 return if !defined $ip;
1393              
1394             # If the address does not contain any ':', maybe it's IPv4
1395 92 100 66     1012 return 4 if $ip !~ /:/ && _ip_is_ipv4($ip);
1396              
1397             # Is it IPv6 ?
1398 1 50       4 return 6 if _ip_is_ipv6($ip);
1399              
1400 0         0 return;
1401             }
1402              
1403             sub _ip_is_ipv4 {
1404 91     91   2341 my ($ip) = @_;
1405 91 50       637 return if !defined $ip;
1406              
1407             # Check for invalid chars
1408 91 50       941 return if $ip !~ /^[\d\.]+$/;
1409 91 50       429 return if $ip =~ /^\./;
1410 91 50       379 return if $ip =~ /\.$/;
1411              
1412             # Single Numbers are considered to be IPv4
1413 91 50 33     624 return 1 if $ip =~ /^(\d+)$/ && $1 < 256;
1414              
1415             # Count quads
1416 91         283 my $n = ($ip =~ tr/\./\./);
1417              
1418             # IPv4 must have from 1 to 4 quads
1419 91 50 33     607 return if $n <= 0 || $n > 4;
1420              
1421             # Check for empty quads
1422 91 50       469 return if $ip =~ /\.\./;
1423              
1424 91         508 for my $quad (split /\./, $ip) {
1425             # Check for invalid quads
1426 364 50 33     1710 return if $quad < 0 || $quad >= 256;
1427             }
1428 91         904 return 1;
1429             }
1430              
1431             sub _ip_is_ipv6 {
1432 93     93   285 my ($ip) = @_;
1433 93 50       401 return if !defined $ip;
1434              
1435             # Count octets
1436 93         290 my $n = ($ip =~ tr/:/:/);
1437 93 100 66     796 return if ($n <= 0 || $n >= 8);
1438              
1439             # $k is a counter
1440 2         4 my $k;
1441              
1442 2         9 for my $octet (split /:/, $ip) {
1443 6         11 $k++;
1444              
1445             # Empty octet ?
1446 6 100       15 next if $octet eq '';
1447              
1448             # Normal v6 octet ?
1449 2 50       15 next if $octet =~ /^[a-f\d]{1,4}$/i;
1450              
1451             # Last octet - is it IPv4 ?
1452 0 0       0 if ($k == $n + 1) {
1453 0 0       0 next if (ip_is_ipv4($octet));
1454             }
1455              
1456 0         0 return;
1457             }
1458              
1459             # Does the IP address start with : ?
1460 2 50       8 return if $ip =~ m/^:[^:]/;
1461              
1462             # Does the IP address finish with : ?
1463 2 50       7 return if $ip =~ m/[^:]:$/;
1464              
1465             # Does the IP address have more than one '::' pattern ?
1466 2 50       26 return if $ip =~ s/:(?=:)//g > 1;
1467              
1468 2         14 return 1;
1469             }
1470              
1471             1;
1472              
1473             =encoding utf8
1474              
1475             =head1 NAME
1476              
1477             POE::Component::IRC - A fully event-driven IRC client module
1478              
1479             =head1 SYNOPSIS
1480              
1481             # A simple Rot13 'encryption' bot
1482              
1483             use strict;
1484             use warnings;
1485             use POE qw(Component::IRC);
1486              
1487             my $nickname = 'Flibble' . $$;
1488             my $ircname = 'Flibble the Sailor Bot';
1489             my $server = 'irc.perl.org';
1490              
1491             my @channels = ('#Blah', '#Foo', '#Bar');
1492              
1493             # We create a new PoCo-IRC object
1494             my $irc = POE::Component::IRC->spawn(
1495             nick => $nickname,
1496             ircname => $ircname,
1497             server => $server,
1498             ) or die "Oh noooo! $!";
1499              
1500             POE::Session->create(
1501             package_states => [
1502             main => [ qw(_default _start irc_001 irc_public) ],
1503             ],
1504             heap => { irc => $irc },
1505             );
1506              
1507             $poe_kernel->run();
1508              
1509             sub _start {
1510             my $heap = $_[HEAP];
1511              
1512             # retrieve our component's object from the heap where we stashed it
1513             my $irc = $heap->{irc};
1514              
1515             $irc->yield( register => 'all' );
1516             $irc->yield( connect => { } );
1517             return;
1518             }
1519              
1520             sub irc_001 {
1521             my $sender = $_[SENDER];
1522              
1523             # Since this is an irc_* event, we can get the component's object by
1524             # accessing the heap of the sender. Then we register and connect to the
1525             # specified server.
1526             my $irc = $sender->get_heap();
1527              
1528             print "Connected to ", $irc->server_name(), "\n";
1529              
1530             # we join our channels
1531             $irc->yield( join => $_ ) for @channels;
1532             return;
1533             }
1534              
1535             sub irc_public {
1536             my ($sender, $who, $where, $what) = @_[SENDER, ARG0 .. ARG2];
1537             my $nick = ( split /!/, $who )[0];
1538             my $channel = $where->[0];
1539              
1540             if ( my ($rot13) = $what =~ /^rot13 (.+)/ ) {
1541             $rot13 =~ tr[a-zA-Z][n-za-mN-ZA-M];
1542             $irc->yield( privmsg => $channel => "$nick: $rot13" );
1543             }
1544             return;
1545             }
1546              
1547             # We registered for all events, this will produce some debug info.
1548             sub _default {
1549             my ($event, $args) = @_[ARG0 .. $#_];
1550             my @output = ( "$event: " );
1551              
1552             for my $arg (@$args) {
1553             if ( ref $arg eq 'ARRAY' ) {
1554             push( @output, '[' . join(', ', @$arg ) . ']' );
1555             }
1556             else {
1557             push ( @output, "'$arg'" );
1558             }
1559             }
1560             print join ' ', @output, "\n";
1561             return;
1562             }
1563              
1564             =head1 DESCRIPTION
1565              
1566             POE::Component::IRC is a POE component (who'd have guessed?) which
1567             acts as an easily controllable IRC client for your other POE
1568             components and sessions. You create an IRC component and tell it what
1569             events your session cares about and where to connect to, and it sends
1570             back interesting IRC events when they happen. You make the client do
1571             things by sending it events. That's all there is to it. Cool, no?
1572              
1573             [Note that using this module requires some familiarity with the
1574             details of the IRC protocol. I'd advise you to read up on the gory
1575             details of RFC 1459 (L) before you
1576             get started. Keep the list of server numeric codes handy while you
1577             program. Needless to say, you'll also need a good working knowledge of
1578             POE, or this document will be of very little use to you.]
1579              
1580             The POE::Component::IRC distribution has a F folder with a collection of
1581             salient documentation including the pertinent RFCs.
1582              
1583             POE::Component::IRC consists of a POE::Session that manages the IRC connection
1584             and dispatches C prefixed events to interested sessions and
1585             an object that can be used to access additional information using methods.
1586              
1587             Sessions register their interest in receiving C events by sending
1588             L|/register> to the component. One would usually do this in
1589             your C<_start> handler. Your session will continue to receive events until
1590             you L|/unregister>. The component will continue to stay
1591             around until you tell it not to with L|/shutdown>.
1592              
1593             The L demonstrates a fairly basic bot.
1594              
1595             See L for more
1596             examples.
1597              
1598             =head2 Useful subclasses
1599              
1600             Included with POE::Component::IRC are a number of useful subclasses. As they
1601             are subclasses they support all the methods, etc. documented here and have
1602             additional methods and quirks which are documented separately:
1603              
1604             =over 4
1605              
1606             =item * L
1607              
1608             POE::Component::IRC::State provides all the functionality of POE::Component::IRC
1609             but also tracks IRC state entities such as nicks and channels.
1610              
1611             =item * L
1612              
1613             POE::Component::IRC::Qnet is POE::Component::IRC tweaked for use on Quakenet IRC
1614             network.
1615              
1616             =item * L
1617              
1618             POE::Component::IRC::Qnet::State is a tweaked version of POE::Component::IRC::State
1619             for use on the Quakenet IRC network.
1620              
1621             =back
1622              
1623             =head2 The Plugin system
1624              
1625             As of 3.7, PoCo-IRC sports a plugin system. The documentation for it can be
1626             read by looking at L.
1627             That is not a subclass, just a placeholder for documentation!
1628              
1629             A number of useful plugins have made their way into the core distribution:
1630              
1631             =over 4
1632              
1633             =item * L
1634              
1635             Provides DCC support. Loaded by default.
1636              
1637             =item * L
1638              
1639             Keeps you on your favorite channels throughout reconnects and even kicks.
1640              
1641             =item * L
1642              
1643             Glues an irc bot to an IRC network, i.e. deals with maintaining ircd connections.
1644              
1645             =item * L
1646              
1647             Under normal circumstances irc bots do not normal the msgs and public msgs that
1648             they generate themselves. This plugin enables you to handle those events.
1649              
1650             =item * L
1651              
1652             Generates C / C / C
1653             events whenever your bot's name comes up in channel discussion.
1654              
1655             =item * L
1656              
1657             Provides an easy way to handle commands issued to your bot.
1658              
1659             =item * L
1660              
1661             See inside the component. See what events are being sent. Generate irc commands
1662             manually. A TCP based console.
1663              
1664             =item * L
1665              
1666             Follow the tail of an ever-growing file.
1667              
1668             =item * L
1669              
1670             Log public and private messages to disk.
1671              
1672             =item * L
1673              
1674             Identify with NickServ when needed.
1675              
1676             =item * L
1677              
1678             A lightweight IRC proxy/bouncer.
1679              
1680             =item * L
1681              
1682             Automagically generates replies to ctcp version, time and userinfo queries.
1683              
1684             =item * L
1685              
1686             An experimental Plugin Manager plugin.
1687              
1688             =item * L
1689              
1690             Automagically deals with your nickname being in use and reclaiming it.
1691              
1692             =item * L
1693              
1694             Cycles (parts and rejoins) channels if they become empty and opless, in order
1695             to gain ops.
1696              
1697             =back
1698              
1699             =head1 CONSTRUCTORS
1700              
1701             Both constructors return an object. The object is also available within 'irc_'
1702             event handlers by using C<< $_[SENDER]->get_heap() >>. See also
1703             L|/register> and L|/irc_registered>.
1704              
1705             =head2 C
1706              
1707             Takes a number of arguments, all of which are optional. All the options
1708             below may be supplied to the L|/connect> input event as well,
1709             except for B<'alias'>, B<'options'>, B<'NoDNS'>, B<'debug'>, and
1710             B<'plugin_debug'>.
1711              
1712             =over 4
1713              
1714             =item * B<'alias'>, a name (kernel alias) that this instance will be known
1715             by;
1716              
1717             =item * B<'options'>, a hashref containing L
1718             options;
1719              
1720             =item * B<'Server'>, the server name;
1721              
1722             =item * B<'Port'>, the remote port number;
1723              
1724             =item * B<'Password'>, an optional password for restricted servers;
1725              
1726             =item * B<'Nick'>, your client's IRC nickname;
1727              
1728             =item * B<'Username'>, your client's username;
1729              
1730             =item * B<'Ircname'>, some cute comment or something.
1731              
1732             =item * B<'Bitmode'>, an integer representing your initial user modes set
1733             in the USER command. See RFC 2812. If you do not set this, C<8> (+i) will
1734             be used.
1735              
1736             =item * B<'UseSSL'>, set to some true value if you want to connect using
1737             SSL.
1738              
1739             =item * B<'SSLCert'>, set to a SSL Certificate(PAM encoded) to connect using a client cert
1740              
1741             =item * B<'SSLKey'>, set to a SSL Key(PAM encoded) to connect using a client cert
1742              
1743             =item * B<'SSLCtx'>, set to a SSL Context to configure the SSL Connection
1744              
1745             The B<'SSLCert'> and B<'SSLKey'> both need to be specified. The B<'SSLCtx'> takes precedence specified.
1746              
1747             =item * B<'Raw'>, set to some true value to enable the component to send
1748             L|/irc_raw> and L|/irc_raw_out> events.
1749              
1750             =item * B<'LocalAddr'>, which local IP address on a multihomed box to
1751             connect as;
1752              
1753             =item * B<'LocalPort'>, the local TCP port to open your socket on;
1754              
1755             =item * B<'NoDNS'>, set this to 1 to disable DNS lookups using
1756             PoCo-Client-DNS. (See note below).
1757              
1758             =item * B<'Flood'>, when true, it disables the component's flood
1759             protection algorithms, allowing it to send messages to an IRC server at
1760             full speed. Disconnects and k-lines are some common side effects of
1761             flooding IRC servers, so care should be used when enabling this option.
1762             Default is false.
1763              
1764             Two new attributes are B<'Proxy'> and B<'ProxyPort'> for sending your
1765             =item * B<'Proxy'>, IP address or server name of a proxy server to use.
1766              
1767             =item * B<'ProxyPort'>, which tcp port on the proxy to connect to.
1768              
1769             =item * B<'NATAddr'>, what other clients see as your IP address.
1770              
1771             =item * B<'DCCPorts'>, an arrayref containing tcp ports that can be used
1772             for DCC sends.
1773              
1774             =item * B<'Resolver'>, provide a L object for the component to use.
1775              
1776             =item * B<'msg_length'>, the maximum length of IRC messages, in bytes.
1777             Default is 450. The IRC component shortens all messages longer than this
1778             value minus the length of your current nickname. IRC only allows raw
1779             protocol lines messages that are 512 bytes or shorter, including the
1780             trailing "\r\n". This is most relevant to long PRIVMSGs. The IRC component
1781             can't be sure how long your user@host mask will be every time you send a
1782             message, considering that most networks mangle the 'user' part and some
1783             even replace the whole string (think FreeNode cloaks). If you have an
1784             unusually long user@host mask you might want to decrease this value if
1785             you're prone to sending long messages. Conversely, if you have an
1786             unusually short one, you can increase this value if you want to be able to
1787             send as long a message as possible. Be careful though, increase it too
1788             much and the IRC server might disconnect you with a "Request too long"
1789             message when you try to send a message that's too long.
1790              
1791             =item * B<'debug'>, if set to a true value causes the IRC component to
1792             print every message sent to and from the server, as well as print some
1793             warnings when it receives malformed messages. This option will be enabled
1794             if the C environment variable is set to a true value.
1795              
1796             =item * B<'plugin_debug'>, set to some true value to print plugin debug
1797             info, default 0. Plugins are processed inside an eval. When you enable
1798             this option, you will be notified when (and why) a plugin raises an
1799             exception. This option will be enabled if the C environment
1800             variable is set to a true value.
1801              
1802             =item * B<'socks_proxy'>, specify a SOCKS4/SOCKS4a proxy to use.
1803              
1804             =item * B<'socks_port'>, the SOCKS port to use, defaults to 1080 if not
1805             specified.
1806              
1807             =item * B<'socks_id'>, specify a SOCKS user_id. Default is none.
1808              
1809             =item * B<'useipv6'>, enable the use of IPv6 for connections.
1810              
1811             =item * B<'webirc'>, enable the use of WEBIRC to spoof host/IP.
1812             You must have a WEBIRC password set up on the IRC server/network (so will
1813             only work for servers which trust you to spoof the IP & host the connection
1814             is from) - value should be a hashref containing keys C, C,
1815             C and C.
1816              
1817             =back
1818              
1819             C will supply reasonable defaults for any of these attributes
1820             which are missing, so don't feel obliged to write them all out.
1821              
1822             If the component finds that L
1823             is installed it will use that to resolve the server name passed. Disable
1824             this behaviour if you like, by passing: C<< NoDNS => 1 >>.
1825              
1826             IRC traffic through a proxy server. B<'Proxy'>'s value should be the IP
1827             address or server name of the proxy. B<'ProxyPort'>'s value should be the
1828             port on the proxy to connect to. L|/connect> will default
1829             to using the I IRC server's port if you provide a proxy but omit
1830             the proxy's port. These are for HTTP Proxies. See B<'socks_proxy'> for
1831             SOCKS4 and SOCKS4a support.
1832              
1833             For those people who run bots behind firewalls and/or Network Address
1834             Translation there are two additional attributes for DCC. B<'DCCPorts'>,
1835             is an arrayref of ports to use when initiating DCC connections.
1836             B<'NATAddr'>, is the NAT'ed IP address that your bot is hidden behind,
1837             this is sent whenever you do DCC.
1838              
1839             SSL support requires L, as
1840             well as an IRC server that supports SSL connections. If you're missing
1841             POE::Component::SSLify, specifying B<'UseSSL'> will do nothing. The
1842             default is to not try to use SSL.
1843              
1844             B<'Resolver'>, requires a L
1845             object. Useful when spawning multiple poco-irc sessions, saves the
1846             overhead of multiple dns sessions.
1847              
1848             B<'NoDNS'> has different results depending on whether it is set with
1849             L|/spawn> or L|/connect>. Setting it with
1850             C, disables the creation of the POE::Component::Client::DNS
1851             completely. Setting it with L|/connect> on the other hand
1852             allows the PoCo-Client-DNS session to be spawned, but will disable
1853             any dns lookups using it.
1854              
1855             SOCKS4 proxy support is provided by B<'socks_proxy'>, B<'socks_port'> and
1856             B<'socks_id'> parameters. If something goes wrong with the SOCKS connection
1857             you should get a warning on STDERR. This is fairly experimental currently.
1858              
1859             IPv6 support is available for connecting to IPv6 enabled ircds (it won't
1860             work for DCC though). To enable it, specify B<'useipv6'>. Perl >=5.14 or
1861             L (for older Perls) is required. If you that and
1862             L installed and
1863             specify a hostname that resolves to an IPv6 address then IPv6 will be used.
1864             If you specify an ipv6 B<'localaddr'> then IPv6 will be used.
1865              
1866             =head2 C
1867              
1868             This method is deprecated. See the L|/spawn> method instead.
1869             The first argument should be a name (kernel alias) which this new
1870             connection will be known by. Optionally takes more arguments (see
1871             L|/spawn> as name/value pairs. Returns a POE::Component::IRC
1872             object. :)
1873              
1874             B Use of this method will generate a warning. There are currently no
1875             plans to make it die() >;]
1876              
1877             =head1 METHODS
1878              
1879             =head2 Information
1880              
1881             =head3 C
1882              
1883             Takes no arguments. Returns the server host we are currently connected to
1884             (or trying to connect to).
1885              
1886             =head3 C
1887              
1888             Takes no arguments. Returns the server port we are currently connected to
1889             (or trying to connect to).
1890              
1891             =head3 C
1892              
1893             Takes no arguments. Returns the name of the IRC server that the component
1894             is currently connected to.
1895              
1896             =head3 C
1897              
1898             Takes no arguments. Returns the IRC server version.
1899              
1900             =head3 C
1901              
1902             Takes no arguments. Returns a scalar containing the current nickname that the
1903             bot is using.
1904              
1905             =head3 C
1906              
1907             Takes no arguments. Returns the IP address being used.
1908              
1909             =head3 C
1910              
1911             The component provides anti-flood throttling. This method takes no arguments
1912             and returns a scalar representing the number of messages that are queued up
1913             waiting for dispatch to the irc server.
1914              
1915             =head3 C
1916              
1917             Takes no arguments. Returns true or false depending on whether the IRC
1918             component is logged into an IRC network.
1919              
1920             =head3 C
1921              
1922             Takes no arguments. Returns true or false depending on whether the component's
1923             socket is currently connected.
1924              
1925             =head3 C
1926              
1927             Takes no arguments. Terminates the socket connection disgracefully >;o]
1928              
1929             =head3 C
1930              
1931             Takes one argument, a server capability to query. Returns C on failure
1932             or a value representing the applicable capability. A full list of capabilities
1933             is available at L.
1934              
1935             =head3 C
1936              
1937             Takes no arguments, returns a list of the available server capabilities keys,
1938             which can be used with L|/isupport>.
1939              
1940             =head3 C
1941              
1942             Returns a reference to the L
1943             object that is internally created by the component.
1944              
1945             =head2 Events
1946              
1947             =head3 C
1948              
1949             I>
1950              
1951             Takes no arguments. Returns the ID of the component's session. Ideal for posting
1952             events to the component.
1953              
1954             $kernel->post($irc->session_id() => 'mode' => $channel => '+o' => $dude);
1955              
1956             =head3 C
1957              
1958             I>
1959              
1960             Takes no arguments. Returns the session alias that has been set through
1961             L|/spawn>'s B<'alias'> argument.
1962              
1963             =head3 C
1964              
1965             With no arguments, returns true or false depending on whether
1966             L|/irc_raw> and L|/irc_raw_out> events are being generated
1967             or not. Provide a true or false argument to enable or disable this feature
1968             accordingly.
1969              
1970             =head3 C
1971              
1972             I>
1973              
1974             This method provides an alternative object based means of posting events to the
1975             component. First argument is the event to post, following arguments are sent as
1976             arguments to the resultant post.
1977              
1978             $irc->yield(mode => $channel => '+o' => $dude);
1979              
1980             =head3 C
1981              
1982             I>
1983              
1984             This method provides an alternative object based means of calling events to the
1985             component. First argument is the event to call, following arguments are sent as
1986             arguments to the resultant
1987             call.
1988              
1989             $irc->call(mode => $channel => '+o' => $dude);
1990              
1991             =head3 C
1992              
1993             I>
1994              
1995             This method provides a way of posting delayed events to the component. The
1996             first argument is an arrayref consisting of the delayed command to post and
1997             any command arguments. The second argument is the time in seconds that one
1998             wishes to delay the command being posted.
1999              
2000             my $alarm_id = $irc->delay( [ mode => $channel => '+o' => $dude ], 60 );
2001              
2002             Returns an alarm ID that can be used with L|/delay_remove>
2003             to cancel the delayed event. This will be undefined if something went wrong.
2004              
2005             =head3 C
2006              
2007             I>
2008              
2009             This method removes a previously scheduled delayed event from the component.
2010             Takes one argument, the C that was returned by a
2011             L|/delay> method call.
2012              
2013             my $arrayref = $irc->delay_remove( $alarm_id );
2014              
2015             Returns an arrayref that was originally requested to be delayed.
2016              
2017             =head3 C
2018              
2019             I>
2020              
2021             Sends an event through the component's event handling system. These will get
2022             processed by plugins then by registered sessions. First argument is the event
2023             name, followed by any parameters for that event.
2024              
2025             =head3 C
2026              
2027             I>
2028              
2029             This sends an event right after the one that's currently being processed.
2030             Useful if you want to generate some event which is directly related to
2031             another event so you want them to appear together. This method can only be
2032             called when POE::Component::IRC is processing an event, e.g. from one of your
2033             event handlers. Takes the same arguments as L|/send_event>.
2034              
2035             =head3 C
2036              
2037             I>
2038              
2039             This will send an event to be processed immediately. This means that if an
2040             event is currently being processed and there are plugins or sessions which
2041             will receive it after you do, then an event sent with C will
2042             be received by those plugins/sessions I the current event. Takes the
2043             same arguments as L|/send_event>.
2044              
2045             =head2 Plugins
2046              
2047             =head3 C
2048              
2049             I>
2050              
2051             Returns the L
2052             object.
2053              
2054             =head3 C
2055              
2056             I>
2057              
2058             Accepts two arguments:
2059              
2060             The alias for the plugin
2061             The actual plugin object
2062             Any number of extra arguments
2063              
2064             The alias is there for the user to refer to it, as it is possible to have
2065             multiple plugins of the same kind active in one Object::Pluggable object.
2066              
2067             This method goes through the pipeline's C method, which will call
2068             C<< $plugin->plugin_register($pluggable, @args) >>.
2069              
2070             Returns the number of plugins now in the pipeline if plugin was initialized,
2071             C/an empty list if not.
2072              
2073             =head3 C
2074              
2075             I>
2076              
2077             Accepts the following arguments:
2078              
2079             The alias for the plugin or the plugin object itself
2080             Any number of extra arguments
2081              
2082             This method goes through the pipeline's C method, which will call
2083             C<< $plugin->plugin_unregister($pluggable, @args) >>.
2084              
2085             Returns the plugin object if the plugin was removed, C/an empty list
2086             if not.
2087              
2088             =head3 C
2089              
2090             I>
2091              
2092             Accepts the following arguments:
2093              
2094             The alias for the plugin
2095              
2096             This method goes through the pipeline's C method.
2097              
2098             Returns the plugin object if it was found, C/an empty list if not.
2099              
2100             =head3 C
2101              
2102             I>
2103              
2104             Takes no arguments.
2105              
2106             Returns a hashref of plugin objects, keyed on alias, or an empty list if
2107             there are no plugins loaded.
2108              
2109             =head3 C
2110              
2111             I>
2112              
2113             Takes no arguments.
2114              
2115             Returns an arrayref of plugin objects, in the order which they are
2116             encountered in the pipeline.
2117              
2118             =head3 C
2119              
2120             I>
2121              
2122             Accepts the following arguments:
2123              
2124             The plugin object
2125             The type of the hook (the hook types are specified with _pluggable_init()'s 'types')
2126             The event name[s] to watch
2127              
2128             The event names can be as many as possible, or an arrayref. They correspond
2129             to the prefixed events and naturally, arbitrary events too.
2130              
2131             You do not need to supply events with the prefix in front of them, just the
2132             names.
2133              
2134             It is possible to register for all events by specifying 'all' as an event.
2135              
2136             Returns 1 if everything checked out fine, C/an empty list if something
2137             is seriously wrong.
2138              
2139             =head3 C
2140              
2141             I>
2142              
2143             Accepts the following arguments:
2144              
2145             The plugin object
2146             The type of the hook (the hook types are specified with _pluggable_init()'s 'types')
2147             The event name[s] to unwatch
2148              
2149             The event names can be as many as possible, or an arrayref. They correspond
2150             to the prefixed events and naturally, arbitrary events too.
2151              
2152             You do not need to supply events with the prefix in front of them, just the
2153             names.
2154              
2155             It is possible to register for all events by specifying 'all' as an event.
2156              
2157             Returns 1 if all the event name[s] was unregistered, undef if some was not
2158             found.
2159              
2160             =head1 INPUT EVENTS
2161              
2162             How to talk to your new IRC component... here's the events we'll accept.
2163             These are events that are posted to the component, either via
2164             C<< $poe_kernel->post() >> or via the object method L|/yield>.
2165              
2166             So the following would be functionally equivalent:
2167              
2168             sub irc_001 {
2169             my ($kernel,$sender) = @_[KERNEL,SENDER];
2170             my $irc = $sender->get_heap(); # obtain the poco's object
2171              
2172             $irc->yield( privmsg => 'foo' => 'Howdy!' );
2173             $kernel->post( $sender => privmsg => 'foo' => 'Howdy!' );
2174             $kernel->post( $irc->session_id() => privmsg => 'foo' => 'Howdy!' );
2175             $kernel->post( $irc->session_alias() => privmsg => 'foo' => 'Howdy!' );
2176              
2177             return;
2178             }
2179              
2180             =head2 Important Commands
2181              
2182             =head3 C
2183              
2184             I>
2185              
2186             Takes N arguments: a list of event names that your session wants to
2187             listen for, minus the C prefix. So, for instance, if you just
2188             want a bot that keeps track of which people are on a channel, you'll
2189             need to listen for JOINs, PARTs, QUITs, and KICKs to people on the
2190             channel you're in. You'd tell POE::Component::IRC that you want those
2191             events by saying this:
2192              
2193             $kernel->post('my client', 'register', qw(join part quit kick));
2194              
2195             Then, whenever people enter or leave a channel your bot is on (forcibly
2196             or not), your session will receive events with names like
2197             L|/irc_join>, L|/irc_kick>, etc.,
2198             which you can use to update a list of people on the channel.
2199              
2200             Registering for B<'all'> will cause it to send all IRC-related events to
2201             you; this is the easiest way to handle it. See the test script for an
2202             example.
2203              
2204             Registering will generate an L|/irc_registered>
2205             event that your session can trap. C is the components object. Useful
2206             if you want to bolt PoCo-IRC's new features such as Plugins into a bot
2207             coded to the older deprecated API. If you are using the new API, ignore this :)
2208              
2209             Registering with multiple component sessions can be tricky, especially if
2210             one wants to marry up sessions/objects, etc. Check the L
2211             section for an alternative method of registering with multiple poco-ircs.
2212              
2213             Starting with version 4.96, if you spawn the component from inside another POE
2214             session, the component will automatically register that session as wanting
2215             B<'all'> irc events. That session will receive an
2216             L|/irc_registered> event indicating that the component
2217             is up and ready to go.
2218              
2219             =head3 C
2220              
2221             I>
2222              
2223             Takes N arguments: a list of event names which you I want to
2224             receive. If you've previously done a L|/register>
2225             for a particular event which you no longer care about, this event will
2226             tell the IRC connection to stop sending them to you. (If you haven't, it just
2227             ignores you. No big deal.)
2228              
2229             If you have registered with 'all', attempting to unregister individual
2230             events such as 'mode', etc. will not work. This is a 'feature'.
2231              
2232             =head3 C
2233              
2234             Takes one argument: a hash reference of attributes for the new connection,
2235             see L|/spawn> for details. This event tells the IRC client to
2236             connect to a new/different server. If it has a connection already open, it'll
2237             close it gracefully before reconnecting.
2238              
2239             =head3 C and C
2240              
2241             Sends a CTCP query or response to the nick(s) or channel(s) which you
2242             specify. Takes 2 arguments: the nick or channel to send a message to
2243             (use an array reference here to specify multiple recipients), and the
2244             plain text of the message to send (the CTCP quoting will be handled
2245             for you). The "/me" command in popular IRC clients is actually a CTCP action.
2246              
2247             # Doing a /me
2248             $irc->yield(ctcp => $channel => 'ACTION dances.');
2249              
2250             =head3 C
2251              
2252             Tells your IRC client to join a single channel of your choice. Takes
2253             at least one arg: the channel name (required) and the channel key
2254             (optional, for password-protected channels).
2255              
2256             =head3 C
2257              
2258             Tell the IRC server to forcibly evict a user from a particular
2259             channel. Takes at least 2 arguments: a channel name, the nick of the
2260             user to boot, and an optional witty message to show them as they sail
2261             out the door.
2262              
2263             =head3 C
2264              
2265             Tell the IRC server to forcibly evict a user from a particular
2266             channel. Takes at least 2 arguments: a channel name, the nick of the
2267             user to boot, and an optional witty message to show them as they sail
2268             out the door. Similar to KICK but does an enforced PART instead. Not
2269             supported by all servers.
2270              
2271             =head3 C
2272              
2273             Request a mode change on a particular channel or user. Takes at least
2274             one argument: the mode changes to effect, as a single string (e.g.
2275             "#mychan +sm-p+o"), and any number of optional operands to the mode changes
2276             (nicks, hostmasks, channel keys, whatever.) Or just pass them all as one
2277             big string and it'll still work, whatever. I regret that I haven't the
2278             patience now to write a detailed explanation, but serious IRC users know
2279             the details anyhow.
2280              
2281             =head3 C
2282              
2283             Allows you to change your nickname. Takes exactly one argument: the
2284             new username that you'd like to be known as.
2285              
2286             =head3 C
2287              
2288             Talks to NickServ, on networks which have it. Takes any number of
2289             arguments.
2290              
2291             =head3 C
2292              
2293             Sends a NOTICE message to the nick(s) or channel(s) which you
2294             specify. Takes 2 arguments: the nick or channel to send a notice to
2295             (use an array reference here to specify multiple recipients), and the
2296             text of the notice to send.
2297              
2298             =head3 C
2299              
2300             Tell your IRC client to leave the channels which you pass to it. Takes
2301             any number of arguments: channel names to depart from. If the last argument
2302             doesn't begin with a channel name identifier or contains a space character,
2303             it will be treated as a PART message and dealt with accordingly.
2304              
2305             =head3 C
2306              
2307             Sends a public or private message to the nick(s) or channel(s) which
2308             you specify. Takes 2 arguments: the nick or channel to send a message
2309             to (use an array reference here to specify multiple recipients), and
2310             the text of the message to send.
2311              
2312             Have a look at the constants in L if you would
2313             like to use formatting and color codes in your messages.
2314              
2315             $irc->yield('primvsg', '#mychannel', 'Hello there');
2316              
2317             # same, but with a green Hello
2318             use IRC::Utils qw(GREEN NORMAL);
2319             $irc->yield('primvsg', '#mychannel', GREEN.'Hello'.NORMAL.' there');
2320              
2321             =head3 C
2322              
2323             Tells the IRC server to disconnect you. Takes one optional argument:
2324             some clever, witty string that other users in your channels will see
2325             as you leave. You can expect to get an
2326             L|/irc_disconnected> event shortly after sending this.
2327              
2328             =head3 C
2329              
2330             By default, POE::Component::IRC sessions never go away. Even after
2331             they're disconnected, they're still sitting around in the background,
2332             waiting for you to call L|/connect> on them again to
2333             reconnect. (Whether this behavior is the Right Thing is doubtful, but I
2334             don't want to break backwards compatibility at this point.) You can send
2335             the IRC session a C event manually to make it delete itself.
2336              
2337             If you are logged into an IRC server, C first will send a quit
2338             message and wait to be disconnected. It will wait for up to 5 seconds before
2339             forcibly disconnecting from the IRC server. If you provide an argument, that
2340             will be used as the QUIT message. If you provide two arguments, the second
2341             one will be used as the timeout (in seconds).
2342              
2343             Terminating multiple components can be tricky. Check the L
2344             section for a method of shutting down multiple poco-ircs.
2345              
2346             =head3 C
2347              
2348             Retrieves or sets the topic for particular channel. If called with just
2349             the channel name as an argument, it will ask the server to return the
2350             current topic. If called with the channel name and a string, it will
2351             set the channel topic to that string. Supply an empty string to unset a
2352             channel topic.
2353              
2354             =head3 C
2355              
2356             Takes one argument: 0 to turn debugging off or 1 to turn debugging on.
2357             This flips the debugging flag in L,
2358             L, and
2359             POE::Component::IRC. This has the same effect as setting Debug in
2360             L|/spawn> or L|/connect>.
2361              
2362             =head2 Not-So-Important Commands
2363              
2364             =head3 C
2365              
2366             Asks your server who your friendly neighborhood server administrators
2367             are. If you prefer, you can pass it a server name to query, instead of
2368             asking the server you're currently on.
2369              
2370             =head3 C
2371              
2372             When sent with an argument (a message describig where you went), the
2373             server will note that you're now away from your machine or otherwise
2374             preoccupied, and pass your message along to anyone who tries to
2375             communicate with you. When sent without arguments, it tells the server
2376             that you're back and paying attention.
2377              
2378             =head3 C
2379              
2380             Used to query/enable/disable IRC protocol capabilities. Takes any number of
2381             arguments.
2382              
2383             =head3 C
2384              
2385             See the L (loaded by default)
2386             documentation for DCC-related commands.
2387              
2388             =head3 C
2389              
2390             Basically the same as the L|/version> command, except that the
2391             server is permitted to return any information about itself that it thinks is
2392             relevant. There's some nice, specific standards-writing for ya, eh?
2393              
2394             =head3 C
2395              
2396             Invites another user onto an invite-only channel. Takes 2 arguments:
2397             the nick of the user you wish to admit, and the name of the channel to
2398             invite them to.
2399              
2400             =head3 C
2401              
2402             Asks the IRC server which users out of a list of nicknames are
2403             currently online. Takes any number of arguments: a list of nicknames
2404             to query the IRC server about.
2405              
2406             =head3 C
2407              
2408             Asks the server for a list of servers connected to the IRC
2409             network. Takes two optional arguments, which I'm too lazy to document
2410             here, so all you would-be linklooker writers should probably go dig up
2411             the RFC.
2412              
2413             =head3 C
2414              
2415             Asks the server for a list of visible channels and their topics. Takes
2416             any number of optional arguments: names of channels to get topic
2417             information for. If called without any channel names, it'll list every
2418             visible channel on the IRC network. This is usually a really big list,
2419             so don't do this often.
2420              
2421             =head3 C
2422              
2423             Request the server's "Message of the Day", a document which typically
2424             contains stuff like the server's acceptable use policy and admin
2425             contact email addresses, et cetera. Normally you'll automatically
2426             receive this when you log into a server, but if you want it again,
2427             here's how to do it. If you'd like to get the MOTD for a server other
2428             than the one you're logged into, pass it the server's hostname as an
2429             argument; otherwise, no arguments.
2430              
2431             =head3 C
2432              
2433             Asks the server for a list of nicknames on particular channels. Takes
2434             any number of arguments: names of channels to get lists of users
2435             for. If called without any channel names, it'll tell you the nicks of
2436             everyone on the IRC network. This is a really big list, so don't do
2437             this much.
2438              
2439             =head3 C
2440              
2441             Sends a raw line of text to the server. Takes one argument: a string
2442             of a raw IRC command to send to the server. It is more optimal to use
2443             the events this module supplies instead of writing raw IRC commands
2444             yourself.
2445              
2446             =head3 C
2447              
2448             Returns some information about a server. Kinda complicated and not
2449             terribly commonly used, so look it up in the RFC if you're
2450             curious. Takes as many arguments as you please.
2451              
2452             =head3 C
2453              
2454             Asks the server what time it thinks it is, which it will return in a
2455             human-readable form. Takes one optional argument: a server name to
2456             query. If not supplied, defaults to current server.
2457              
2458             =head3 C
2459              
2460             If you pass a server name or nick along with this request, it asks the
2461             server for the list of servers in between you and the thing you
2462             mentioned. If sent with no arguments, it will show you all the servers
2463             which are connected to your current server.
2464              
2465             =head3 C
2466              
2467             Asks the server how many users are logged into it. Defaults to the
2468             server you're currently logged into; however, you can pass a server
2469             name as the first argument to query some other machine instead.
2470              
2471             =head3 C
2472              
2473             Asks the server about the version of ircd that it's running. Takes one
2474             optional argument: a server name to query. If not supplied, defaults
2475             to current server.
2476              
2477             =head3 C
2478              
2479             Lists the logged-on users matching a particular channel name, hostname,
2480             nickname, or what-have-you. Takes one optional argument: a string for
2481             it to search for. Wildcards are allowed; in the absence of this
2482             argument, it will return everyone who's currently logged in (bad
2483             move). Tack an "o" on the end if you want to list only IRCops, as per
2484             the RFC.
2485              
2486             =head3 C
2487              
2488             Queries the IRC server for detailed information about a particular
2489             user. Takes any number of arguments: nicknames or hostmasks to ask for
2490             information about. As of version 3.2, you will receive an
2491             L|/irc_whois> event in addition to the usual numeric
2492             responses. See below for details.
2493              
2494             =head3 C
2495              
2496             Asks the server for information about nickname which is no longer
2497             connected. Takes at least one argument: a nickname to look up (no
2498             wildcards allowed), the optional maximum number of history entries to
2499             return, and the optional server hostname to query. As of version 3.2,
2500             you will receive an L|/irc_whowas> event in addition
2501             to the usual numeric responses. See below for details.
2502              
2503             =head3 C and C
2504              
2505             Included for completeness sake. The component will deal with ponging to
2506             pings automatically. Don't worry about it.
2507              
2508             =head2 Purely Esoteric Commands
2509              
2510             =head3 C
2511              
2512             Tells the IRC server you're connect to, to terminate. Only useful for
2513             IRCops, thank goodness. Takes no arguments.
2514              
2515             =head3 C
2516              
2517             Opers-only command. This one sends a message to all currently
2518             logged-on local-opers (+l). This option is specific to EFNet.
2519              
2520             =head3 C
2521              
2522             In the exceedingly unlikely event that you happen to be an IRC
2523             operator, you can use this command to authenticate with your IRC
2524             server. Takes 2 arguments: your username and your password.
2525              
2526             =head3 C
2527              
2528             Opers-only command. This one sends a message to all currently
2529             logged-on global opers. This option is specific to EFNet.
2530              
2531             =head3 C
2532              
2533             Tells the IRC server you're connected to, to rehash its configuration
2534             files. Only useful for IRCops. Takes no arguments.
2535              
2536             =head3 C
2537              
2538             Tells the IRC server you're connected to, to shut down and restart itself.
2539             Only useful for IRCops, thank goodness. Takes no arguments.
2540              
2541             =head3 C
2542              
2543             Tells one IRC server (which you have operator status on) to connect to
2544             another. This is actually the CONNECT command, but I already had an
2545             event called L|/connect>, so too bad. Takes the args
2546             you'd expect: a server to connect to, an optional port to connect on,
2547             and an optional remote server to connect with, instead of the one you're
2548             currently on.
2549              
2550             =head3 C
2551              
2552             Operator-only command used to disconnect server links. Takes two arguments,
2553             the server to disconnect and a message explaining your action.
2554              
2555             =head3 C
2556              
2557             Don't even ask.
2558              
2559             =head3 C
2560              
2561             Lists the currently connected services on the network that are visible to you.
2562             Takes two optional arguments, a mask for matching service names against, and
2563             a service type.
2564              
2565             =head3 C
2566              
2567             Sends a message to a service. Takes the same arguments as
2568             L|/privmsg>.
2569              
2570             =head3 C
2571              
2572             Asks the IRC server for information about particular nicknames. (The
2573             RFC doesn't define exactly what this is supposed to return.) Takes any
2574             number of arguments: the nicknames to look up.
2575              
2576             =head3 C
2577              
2578             Another opers-only command. This one sends a message to all currently
2579             logged-on opers (and +w users); sort of a mass PA system for the IRC
2580             server administrators. Takes one argument: some clever, witty message
2581             to send.
2582              
2583             =head1 OUTPUT EVENTS
2584              
2585             The events you will receive (or can ask to receive) from your running
2586             IRC component. Note that all incoming event names your session will
2587             receive are prefixed by C, to inhibit event namespace pollution.
2588              
2589             If you wish, you can ask the client to send you every event it
2590             generates. Simply register for the event name "all". This is a lot
2591             easier than writing a huge list of things you specifically want to
2592             listen for.
2593              
2594             FIXME: I'd really like to classify these somewhat ("basic", "oper", "ctcp",
2595             "dcc", "raw" or some such), and I'd welcome suggestions for ways to make
2596             this easier on the user, if you can think of some.
2597              
2598             In your event handlers, C<$_[SENDER]> is the particular component session that
2599             sent you the event. C<< $_[SENDER]->get_heap() >> will retrieve the component's
2600             object. Useful if you want on-the-fly access to the object and its methods.
2601              
2602             =head2 Important Events
2603              
2604             =head3 C
2605              
2606             I>
2607              
2608             Sent once to the requesting session on registration (see
2609             L|/register>). C is a reference tothe component's object.
2610              
2611             =head3 C
2612              
2613             I>
2614              
2615             Sent to all registered sessions when the component has been asked to
2616             L|/shutdown>. C will be the session ID of the requesting
2617             session.
2618              
2619             =head3 C
2620              
2621             The IRC component will send an C event as soon as it
2622             establishes a connection to an IRC server, before attempting to log
2623             in. C is the server name.
2624              
2625             B When you get an C event, this doesn't mean you
2626             can start sending commands to the server yet. Wait until you receive
2627             an L|/All numeric events> event (the server welcome message)
2628             before actually sending anything back to the server.
2629              
2630             =head3 C
2631              
2632             C events are generated upon receipt of CTCP messages, in addition to
2633             the C events mentioned below. They are identical in every way to
2634             these, with one difference: instead of the * being in the method name, it
2635             is prepended to the argument list. For example, if someone types C
2636             Flibble foo bar>, an C event will be sent with B<'foo'> as C,
2637             and the rest as given below.
2638              
2639             It is not recommended that you register for both C and C
2640             events, since they will both be fired and presumably cause duplication.
2641              
2642             =head3 C
2643              
2644             C events are generated upon receipt of CTCP messages.
2645             For instance, receiving a CTCP PING request generates an C
2646             event, CTCP ACTION (produced by typing "/me" in most IRC clients)
2647             generates an C event, blah blah, so on and so forth. C
2648             is the nick!hostmask of the sender. C is the channel/recipient
2649             name(s). C is the text of the CTCP message. On servers supporting the
2650             IDENTIFY-MSG feature (e.g. FreeNode), CTCP ACTIONs will have C, which
2651             will be C<1> if the sender has identified with NickServ, C<0> otherwise.
2652              
2653             Note that DCCs are handled separately -- see the
2654             L.
2655              
2656             =head3 C
2657              
2658             C messages are just like C
2659             messages, described above, except that they're generated when a response
2660             to one of your CTCP queries comes back. They have the same arguments and
2661             such as C events.
2662              
2663             =head3 C
2664              
2665             The counterpart to L|/irc_connected>, sent whenever
2666             a socket connection to an IRC server closes down (whether intentionally or
2667             unintentionally). C is the server name.
2668              
2669             =head3 C
2670              
2671             You get this whenever the server sends you an ERROR message. Expect
2672             this to usually be accompanied by the sudden dropping of your
2673             connection. C is the server's explanation of the error.
2674              
2675             =head3 C
2676              
2677             Sent whenever someone joins a channel that you're on. C is the
2678             person's nick!hostmask. C is the channel name.
2679              
2680             =head3 C
2681              
2682             Sent whenever someone offers you an invitation to another channel. C
2683             is the person's nick!hostmask. C is the name of the channel they want
2684             you to join.
2685              
2686             =head3 C
2687              
2688             Sent whenever someone gets booted off a channel that you're on. C
2689             is the kicker's nick!hostmask. C is the channel name. C is the
2690             nick of the unfortunate kickee. C is the explanation string for the
2691             kick.
2692              
2693             =head3 C
2694              
2695             Sent whenever someone changes a channel mode in your presence, or when
2696             you change your own user mode. C is the nick!hostmask of that
2697             someone. C is the channel it affects (or your nick, if it's a user
2698             mode change). C is the mode string (i.e., "+o-b"). The rest of the
2699             args (C) are the operands to the mode string (nicks,
2700             hostmasks, channel keys, whatever).
2701              
2702             =head3 C
2703              
2704             Sent whenever you receive a PRIVMSG command that was addressed to you
2705             privately. C is the nick!hostmask of the sender. C is an array
2706             reference containing the nick(s) of the recipients. C is the text
2707             of the message. On servers supporting the IDENTIFY-MSG feature (e.g.
2708             FreeNode), there will be an additional argument, C, which will be
2709             C<1> if the sender has identified with NickServ, C<0> otherwise.
2710              
2711             =head3 C
2712              
2713             Sent whenever you, or someone around you, changes nicks. C is the
2714             nick!hostmask of the changer. C is the new nick that they changed
2715             to.
2716              
2717             =head3 C
2718              
2719             Sent whenever you receive a NOTICE command. C is the nick!hostmask
2720             of the sender. C is an array reference containing the nick(s) or
2721             channel name(s) of the recipients. C is the text of the NOTICE
2722             message.
2723              
2724             =head3 C
2725              
2726             Sent whenever someone leaves a channel that you're on. C is the
2727             person's nick!hostmask. C is the channel name. C is the part
2728             message.
2729              
2730             =head3 C
2731              
2732             Sent whenever you receive a PRIVMSG command that was sent to a channel.
2733             C is the nick!hostmask of the sender. C is an array
2734             reference containing the channel name(s) of the recipients. C is the
2735             text of the message. On servers supporting the IDENTIFY-MSG feature (e.g.
2736             FreeNode), there will be an additional argument, C, which will be
2737             C<1> if the sender has identified with NickServ, C<0> otherwise.
2738              
2739             =head3 C
2740              
2741             Sent whenever someone on a channel with you quits IRC (or gets
2742             KILLed). C is the nick!hostmask of the person in question. C is
2743             the clever, witty message they left behind on the way out.
2744              
2745             =head3 C
2746              
2747             Sent when a connection couldn't be established to the IRC server. C
2748             is probably some vague and/or misleading reason for what failed.
2749              
2750             =head3 C
2751              
2752             Sent when a channel topic is set or unset. C is the nick!hostmask of the
2753             sender. C is the channel affected. C will be either: a string if the
2754             topic is being set; or a zero-length string (i.e. '') if the topic is being
2755             unset. Note: replies to queries about what a channel topic *is*
2756             (i.e. TOPIC #channel), are returned as numerics, not with this event.
2757              
2758             =head3 C
2759              
2760             Sent in response to a WHOIS query. C is a hashref, with the following
2761             keys:
2762              
2763             =over 4
2764              
2765             =item * B<'nick'>, the users nickname;
2766              
2767             =item * B<'user'>, the users username;
2768              
2769             =item * B<'host'>, their hostname;
2770              
2771             =item * B<'real'>, their real name;
2772              
2773             =item * B<'idle'>, their idle time in seconds;
2774              
2775             =item * B<'signon'>, the epoch time they signed on (will be undef if ircd
2776             does not support this);
2777              
2778             =item * B<'channels'>, an arrayref listing visible channels they are on,
2779             the channel is prefixed with '@','+','%' depending on whether they have
2780             +o +v or +h;
2781              
2782             =item * B<'server'>, their server (might not be useful on some networks);
2783              
2784             =item * B<'oper'>, whether they are an IRCop, contains the IRC operator
2785             string if they are, undef if they aren't.
2786              
2787             =item * B<'actually'>, some ircds report the user's actual ip address,
2788             that'll be here;
2789              
2790             =item * B<'identified'>. if the user has identified with NICKSERV
2791             (ircu, seven, Plexus)
2792              
2793             =item * B<'modes'>, a string describing the user's modes (Rizon)
2794              
2795             =back
2796              
2797             =head3 C
2798              
2799             Similar to the above, except some keys will be missing.
2800              
2801             =head3 C
2802              
2803             Enabled by passing C<< Raw => 1 >> to L|/spawn> or
2804             L|/connect>, or by calling L|/raw_events> with
2805             a true argument. C is the raw IRC string received by the component from
2806             the IRC server, before it has been mangled by filters and such like.
2807              
2808             =head3 C
2809              
2810             Enabled by passing C<< Raw => 1 >> to L|/spawn> or
2811             L|/connect>, or by calling L|/raw_events> with
2812             a true argument. C is the raw IRC string sent by the component to the
2813             the IRC server.
2814              
2815             =head3 C
2816              
2817             Emitted by the first event after an L|/All numeric events>, to
2818             indicate that isupport information has been gathered. C is the
2819             L
2820             object.
2821              
2822             =head3 C
2823              
2824             Emitted whenever we fail to connect successfully to a SOCKS server or the
2825             SOCKS server is not actually a SOCKS server. C will be some vague reason
2826             as to what went wrong. Hopefully.
2827              
2828             =head3 C
2829              
2830             Emitted whenever a SOCKS connection is rejected by a SOCKS server. C is
2831             the SOCKS code, C the SOCKS server address, C the SOCKS port and
2832             C the SOCKS user id (if defined).
2833              
2834             =head3 C
2835              
2836             I>
2837              
2838             Emitted whenever a new plugin is added to the pipeline. C is the
2839             plugin alias. C is the plugin object.
2840              
2841             =head3 C
2842              
2843             I>
2844              
2845             Emitted whenever a plugin is removed from the pipeline. C is the
2846             plugin alias. C is the plugin object.
2847              
2848             =head3 C
2849              
2850             I>
2851              
2852             Emitted when an error occurs while executing a plugin handler. C is
2853             the error message. C is the plugin alias. C is the plugin object.
2854              
2855             =head2 Somewhat Less Important Events
2856              
2857             =head3 C
2858              
2859             A reply from the server regarding protocol capabilities. C is the
2860             CAP subcommand (e.g. 'LS'). C is the result of the subcommand, unless
2861             this is a multi-part reply, in which case C is '*' and C contains
2862             the result.
2863              
2864             =head3 C
2865              
2866             See the L (loaded by default)
2867             documentation for DCC-related events.
2868              
2869             =head3 C
2870              
2871             An event sent whenever the server sends a PING query to the
2872             client. (Don't confuse this with a CTCP PING, which is another beast
2873             entirely. If unclear, read the RFC.) Note that POE::Component::IRC will
2874             automatically take care of sending the PONG response back to the
2875             server for you, although you can still register to catch the event for
2876             informational purposes.
2877              
2878             =head3 C
2879              
2880             A weird, non-RFC-compliant message from an IRC server. Usually sent during
2881             to you during an authentication phase right after you connect, while the
2882             server does a hostname lookup or similar tasks. C is the text of the
2883             server's message. C is the target, which could be B<'*'> or B<'AUTH'>
2884             or whatever. Servers vary as to whether these notices include a server name
2885             as the sender, or no sender at all. C is the sender, if any.
2886              
2887             =head3 C
2888              
2889             I>
2890              
2891             Emitted on a successful addition of a delayed event using the
2892             L|/delay> method. C will be the alarm_id which can be used
2893             later with L|/delay_remove>. Subsequent parameters are
2894             the arguments that were passed to L|/delay>.
2895              
2896             =head3 C
2897              
2898             I>
2899              
2900             Emitted when a delayed command is successfully removed. C will be the
2901             alarm_id that was removed. Subsequent parameters are the arguments that were
2902             passed to L|/delay>.
2903              
2904             =head2 All numeric events
2905              
2906             Most messages from IRC servers are identified only by three-digit
2907             numeric codes with undescriptive constant names like RPL_UMODEIS and
2908             ERR_NOTOPLEVEL. (Actually, the list of codes in the RFC is kind of
2909             out-of-date... the list in the back of Net::IRC::Event.pm is more
2910             complete, and different IRC networks have different and incompatible
2911             lists. Ack!) As an example, say you wanted to handle event 376
2912             (RPL_ENDOFMOTD, which signals the end of the MOTD message). You'd
2913             register for '376', and listen for C events. Simple, no? C
2914             is the name of the server which sent the message. C is the text of
2915             the message. C is an array reference of the parsed message, so there
2916             is no need to parse C yourself.
2917              
2918             =head1 SIGNALS
2919              
2920             The component will handle a number of custom signals that you may send using
2921             L's C method.
2922              
2923             =head2 C
2924              
2925             I>
2926              
2927             Registering with multiple PoCo-IRC components has been a pita. Well, no more,
2928             using the power of L signals.
2929              
2930             If the component receives a C signal it'll register the
2931             requesting session and trigger an L|/irc_registered>
2932             event. From that event one can get all the information necessary such as the
2933             poco-irc object and the SENDER session to do whatever one needs to build a
2934             poco-irc dispatch table.
2935              
2936             The way the signal handler in PoCo-IRC is written also supports sending the
2937             C to multiple sessions simultaneously, by sending the signal
2938             to the POE Kernel itself.
2939              
2940             Pass the signal your session, session ID or alias, and the IRC events (as
2941             specified to L|/register>).
2942              
2943             To register with multiple PoCo-IRCs one can do the following in your session's
2944             _start handler:
2945              
2946             sub _start {
2947             my ($kernel, $session) = @_[KERNEL, SESSION];
2948              
2949             # Registering with multiple pocoircs for 'all' IRC events
2950             $kernel->signal($kernel, 'POCOIRC_REGISTER', $session->ID(), 'all');
2951              
2952             return:
2953             }
2954              
2955             Each poco-irc will send your session an
2956             L|/irc_registered> event:
2957              
2958             sub irc_registered {
2959             my ($kernel, $sender, $heap, $irc_object) = @_[KERNEL, SENDER, HEAP, ARG0];
2960              
2961             # Get the poco-irc session ID
2962             my $sender_id = $sender->ID();
2963              
2964             # Or it's alias
2965             my $poco_alias = $irc_object->session_alias();
2966              
2967             # Store it in our heap maybe
2968             $heap->{irc_objects}->{ $sender_id } = $irc_object;
2969              
2970             # Make the poco connect
2971             $irc_object->yield(connect => { });
2972              
2973             return;
2974             }
2975              
2976             =head2 C
2977              
2978             I>
2979              
2980             Telling multiple poco-ircs to shutdown was a pita as well. The same principle as
2981             with registering applies to shutdown too.
2982              
2983             Send a C to the POE Kernel to terminate all the active
2984             poco-ircs simultaneously.
2985              
2986             $poe_kernel->signal($poe_kernel, 'POCOIRC_SHUTDOWN');
2987              
2988             Any additional parameters passed to the signal will become your quit messages
2989             on each IRC network.
2990              
2991             =head1 ENCODING
2992              
2993             This can be an issue. Take a look at L
2994             on it.
2995              
2996             =head1 BUGS
2997              
2998             A few have turned up in the past and they are sure to again. Please use
2999             L to report any. Alternatively, email the current
3000             maintainer.
3001              
3002             =head1 DEVELOPMENT
3003              
3004             You can find the latest source on github:
3005             L
3006              
3007             The project's developers usually hang out in the C<#poe> IRC channel on
3008             irc.perl.org. Do drop us a line.
3009              
3010             =head1 MAINTAINERS
3011              
3012             Chris C Williams
3013              
3014             Hinrik Ern SigurEsson
3015              
3016             =head1 AUTHOR
3017              
3018             Dennis Taylor.
3019              
3020             =head1 LICENCE
3021              
3022             Copyright (c) Dennis Taylor, Chris Williams and Hinrik Ern SigurEsson
3023              
3024             This module may be used, modified, and distributed under the same
3025             terms as Perl itself. Please see the license that came with your Perl
3026             distribution for details.
3027              
3028             =head1 MAD PROPS
3029              
3030             The maddest of mad props go out to Rocco "dngor" Caputo
3031             , for inventing something as mind-bogglingly
3032             cool as POE, and to Kevin "oznoid" Lenzo Elenzo@cs.cmu.eduE,
3033             for being the attentive parent of our precocious little infobot on
3034             #perl.
3035              
3036             Further props to a few of the studly bughunters who made this module not
3037             suck: Abys , Addi , ResDev
3038             , and Roderick . Woohoo!
3039              
3040             Kudos to Apocalypse, , for the plugin system and to
3041             Jeff 'japhy' Pinyan, , for Pipeline.
3042              
3043             Thanks to the merry band of POE pixies from #PoE @ irc.perl.org,
3044             including ( but not limited to ), ketas, ct, dec, integral, webfox,
3045             immute, perigrin, paulv, alias.
3046              
3047             IP functions are shamelessly 'borrowed' from L by Manuel
3048             Valente
3049              
3050             Check out the Changes file for further contributors.
3051              
3052             =head1 SEE ALSO
3053              
3054             RFC 1459 L
3055              
3056             L,
3057              
3058             L,
3059              
3060             L,
3061              
3062             Some good examples reside in the POE cookbook which has a whole section
3063             devoted to IRC programming L.
3064              
3065             The examples/ folder of this distribution.
3066              
3067             =cut