1 | package Net::IRC3; |
1 | package Net::IRC3; |
2 | use strict; |
2 | use strict; |
3 | use AnyEvent; |
3 | use AnyEvent; |
4 | use IO::Socket::INET; |
4 | use IO::Socket::INET; |
5 | |
5 | |
|
|
6 | use Exporter; |
|
|
7 | our @ISA = qw/Exporter/; |
|
|
8 | our @EXPORT_OK = |
|
|
9 | qw(mk_msg parse_irc_msg split_prefix prefix_nick |
|
|
10 | prefix_user prefix_host); |
|
|
11 | |
|
|
12 | require Net::IRC3::Connection; |
|
|
13 | |
6 | =head1 NAME |
14 | =head1 NAME |
7 | |
15 | |
8 | Net::IRC3 - An IRC Protocol module which is event system independend |
16 | Net::IRC3 - An IRC Protocol module which is event system independend |
9 | |
17 | |
10 | =head1 VERSION |
18 | =head1 VERSION |
… | |
… | |
59 | } |
67 | } |
60 | |
68 | |
61 | =item B<connect_server ($host, $port)> |
69 | =item B<connect_server ($host, $port)> |
62 | |
70 | |
63 | Tries to open a socket to the host C<$host> and the port C<$port>. |
71 | Tries to open a socket to the host C<$host> and the port C<$port>. |
64 | If successfull it will return a Net::IRC3::Connection object. |
72 | If successfull it will return a L<Net::IRC3::Connection> object. |
65 | If an error occured it will die (use eval to catch the exception). |
73 | If an error occured it will die (use eval to catch the exception). |
66 | |
74 | |
67 | =cut |
75 | =cut |
68 | |
76 | |
69 | sub connect_server { |
77 | sub connect_server { |
… | |
… | |
108 | =head1 FUNCTIONS |
116 | =head1 FUNCTIONS |
109 | |
117 | |
110 | These are some utility functions that might come in handy when |
118 | These are some utility functions that might come in handy when |
111 | handling the IRC protocol. |
119 | handling the IRC protocol. |
112 | |
120 | |
|
|
121 | You can export these with eg.: |
|
|
122 | |
|
|
123 | use Net::IRC3 qw/parse_irc_msg/; |
|
|
124 | |
113 | =over 4 |
125 | =over 4 |
114 | |
126 | |
115 | =item B<parse_irc_msg ($ircline)> |
127 | =item B<parse_irc_msg ($ircline)> |
116 | |
128 | |
117 | This method parses the C<$ircline>, which is one line of the IRC protocol |
129 | This method parses the C<$ircline>, which is one line of the IRC protocol |
… | |
… | |
194 | |
206 | |
195 | The prefix and the trailing string will be omitted if they are C<undef>. |
207 | The prefix and the trailing string will be omitted if they are C<undef>. |
196 | |
208 | |
197 | EXAMPLES: |
209 | EXAMPLES: |
198 | |
210 | |
199 | $con->mk_msg (undef, "PRIVMSG", "you suck!", "magnus"); |
211 | mk_msg (undef, "PRIVMSG", "you suck!", "magnus"); |
200 | # will return: "PRIVMSG magnus :you suck!\015\012" |
212 | # will return: "PRIVMSG magnus :you suck!\015\012" |
201 | |
213 | |
202 | $con->mk_msg (undef, "JOIN", undef, "#test"); |
214 | mk_msg (undef, "JOIN", undef, "#test"); |
203 | # will return: "JOIN #magnus\015\012" |
215 | # will return: "JOIN #magnus\015\012" |
204 | |
216 | |
205 | =cut |
217 | =cut |
206 | |
218 | |
207 | sub mk_msg { |
219 | sub mk_msg { |
… | |
… | |
279 | sub prefix_host { |
291 | sub prefix_host { |
280 | my ($self, $prfx) = @_; |
292 | my ($self, $prfx) = @_; |
281 | return (split_prefix ($prfx))[2]; |
293 | return (split_prefix ($prfx))[2]; |
282 | } |
294 | } |
283 | |
295 | |
284 | =head1 Net::IRC3::Connection |
|
|
285 | |
|
|
286 | The connection class. Here the actual interesting stuff can be done, |
|
|
287 | such as sending and receiving IRC messages. |
|
|
288 | |
|
|
289 | =head2 METHODS |
|
|
290 | |
|
|
291 | =over 4 |
|
|
292 | |
|
|
293 | =cut |
|
|
294 | |
|
|
295 | package Net::IRC3::Connection; |
|
|
296 | |
|
|
297 | use strict; |
|
|
298 | use AnyEvent; |
|
|
299 | use IO::Socket::INET; |
|
|
300 | |
|
|
301 | sub new |
|
|
302 | { |
|
|
303 | my $this = shift; |
|
|
304 | my $class = ref($this) || $this; |
|
|
305 | |
|
|
306 | my $self = { |
|
|
307 | pirc => $_[0], |
|
|
308 | s => $_[1], |
|
|
309 | h => $_[2], |
|
|
310 | p => $_[3], |
|
|
311 | cbs => {}, |
|
|
312 | heap => {} |
|
|
313 | }; |
|
|
314 | |
|
|
315 | bless $self, $class; |
|
|
316 | |
|
|
317 | return $self; |
|
|
318 | } |
|
|
319 | |
|
|
320 | =item B<disconnect_server ($reason)> |
|
|
321 | |
|
|
322 | Unregisters the connection in the main Net::IRC3 object, closes |
|
|
323 | the sockets and send a 'disconnect' event with C<$reason> as argument. |
|
|
324 | |
|
|
325 | =cut |
|
|
326 | |
|
|
327 | sub disconnect_server { |
|
|
328 | my ($self, $reason) = @_; |
|
|
329 | |
|
|
330 | $self->event (disconnect => $reason); |
|
|
331 | |
|
|
332 | delete $self->{rw}; |
|
|
333 | delete $self->{ww}; |
|
|
334 | delete $self->{pirc}->{connections}->{$self->{h} . ":" . $self->{p}}; |
|
|
335 | |
|
|
336 | eval { $self->{s}->close } |
|
|
337 | } |
|
|
338 | |
|
|
339 | =item B<heap ()> |
|
|
340 | |
|
|
341 | Returns a hash reference that is local to this connection object |
|
|
342 | that lets you store any information you want. |
|
|
343 | |
|
|
344 | =cut |
|
|
345 | |
|
|
346 | sub heap { |
|
|
347 | my ($self) = @_; |
|
|
348 | return $self->{heap}; |
|
|
349 | } |
|
|
350 | |
|
|
351 | =item B<send_msg (@ircmsg)> |
|
|
352 | |
|
|
353 | This function sends a message to the server. C<@ircmsg> is the argumentlist |
|
|
354 | for C<mk_msg>. |
|
|
355 | |
|
|
356 | =cut |
|
|
357 | |
|
|
358 | sub send_msg { |
|
|
359 | my ($self, @msg) = @_; |
|
|
360 | my $data = mk_msg (@msg); |
|
|
361 | |
|
|
362 | my ($host, $port) = ($self->{h}, $self->{p}); |
|
|
363 | $self->{outbuf} .= $data; |
|
|
364 | |
|
|
365 | unless (defined $self->{ww}) { |
|
|
366 | my $sock = $self->{s}; |
|
|
367 | $self->{ww} = |
|
|
368 | AnyEvent->io (poll => 'w', fh => $sock, cb => sub { |
|
|
369 | my $l = syswrite $sock, $self->{outbuf}; |
|
|
370 | |
|
|
371 | substr $self->{outbuf}, 0, $l, ""; |
|
|
372 | |
|
|
373 | if (length ($self->{outbuf}) == 0) { delete $self->{ww} } |
|
|
374 | |
|
|
375 | unless ($l) { |
|
|
376 | # XXX: is this behaviour correct or ok? |
|
|
377 | $self->disconnect_server ("Error while writing to IRC server '$host:$port': $!"); |
|
|
378 | return; |
|
|
379 | } |
|
|
380 | }); |
|
|
381 | } |
|
|
382 | } |
|
|
383 | |
|
|
384 | =item B<reg_cb ($cmd, $cb)> |
|
|
385 | |
|
|
386 | This registers a callback in the connection class. |
|
|
387 | These callbacks will be called by internal events and |
|
|
388 | by IRC protocol commands. |
|
|
389 | |
|
|
390 | The first argument to the callbacks is always the connection object |
|
|
391 | itself. |
|
|
392 | |
|
|
393 | If a callback returns a false value, it will be unregistered. |
|
|
394 | |
|
|
395 | NOTE: I<A callback has to return true to stay alive> |
|
|
396 | |
|
|
397 | If C<$cmd> starts with 'irc_' the callback C<$cb> will be registered |
|
|
398 | for a IRC protocol command. The command is the suffix of C<$cmd> then. |
|
|
399 | The second argument to the callback is the message hash reference |
|
|
400 | that has the layout that is returned by C<parse_irc_msg>. |
|
|
401 | |
|
|
402 | EXAMPLE: |
|
|
403 | |
|
|
404 | $con->reg_cb (irc_privmsg => \&privmsg_handler); |
|
|
405 | # privmsg_handler will be called if an IRC message |
|
|
406 | # with the command 'PRIVMSG' arrives. |
|
|
407 | |
|
|
408 | If C<$cmd> is not prefixed with a 'irc_' it will be called when an event |
|
|
409 | with the name C<$cmd> is emitted. The arguments to the callback depend |
|
|
410 | on the event that is emitted (but remember: the first argument will always be the |
|
|
411 | connection object) |
|
|
412 | |
|
|
413 | Following events are emitted by this module and shouldn't be emitted |
|
|
414 | from a module user call to C<event>. |
|
|
415 | |
|
|
416 | =over 4 |
|
|
417 | |
|
|
418 | =item B<disconnect $reason> |
|
|
419 | |
|
|
420 | This event will be generated if the connection is somehow terminated. |
|
|
421 | It will also be emitted when C<disconnect_server> is called. |
|
|
422 | The second argument to the callback is C<$reason>, a string that contains |
|
|
423 | a clue about why the connection terminated. |
|
|
424 | |
|
|
425 | =back |
296 | =back |
426 | |
297 | |
427 | =cut |
298 | =head1 EXAMPLES |
428 | |
299 | |
429 | sub reg_cb { |
300 | See the samples/ directory for some examples on how to use Net::IRC3. |
430 | my ($self, $cmd, $cb) = @_; |
|
|
431 | |
|
|
432 | if ($cmd =~ m/^irc_(\S+)/i) { |
|
|
433 | push @{$self->{cbs}->{lc $1}}, $cb; |
|
|
434 | |
|
|
435 | } else { |
|
|
436 | push @{$self->{events}->{$cmd}}, $cb; |
|
|
437 | } |
|
|
438 | |
|
|
439 | 1; |
|
|
440 | } |
|
|
441 | |
|
|
442 | =item B<event ($event, @args)> |
|
|
443 | |
|
|
444 | This function emits an event with the name C<$event> and the arguments C<@args>. |
|
|
445 | The registerd callback that has been registered with C<reg_cb> will be called |
|
|
446 | with the first argument being the connection object and the rest of the arguments |
|
|
447 | being C<@args>. |
|
|
448 | |
|
|
449 | EXAMPLE |
|
|
450 | |
|
|
451 | $con->reg_cb (test_event => sub { print "Yay, i love $_[1]!!\n"); |
|
|
452 | $con->event (test_event => "IRC"); |
|
|
453 | |
|
|
454 | # will print "Yay, i love IRC!!\n" |
|
|
455 | |
|
|
456 | =cut |
|
|
457 | |
|
|
458 | sub event { |
|
|
459 | my ($self, $ev, @arg) = @_; |
|
|
460 | |
|
|
461 | my $nxt = []; |
|
|
462 | |
|
|
463 | for (@{$self->{events}->{lc $ev}}) { |
|
|
464 | $_->($self, @arg) and push @$nxt, $_; |
|
|
465 | } |
|
|
466 | |
|
|
467 | $self->{events}->{lc $ev} = $nxt; |
|
|
468 | } |
|
|
469 | |
|
|
470 | # internal function, called by the read callbacks above. |
|
|
471 | sub feed_irc_data { |
|
|
472 | my ($self, $data) = @_; |
|
|
473 | |
|
|
474 | $self->{buffer} .= $data; |
|
|
475 | |
|
|
476 | my @msg; |
|
|
477 | while ($self->{buffer} =~ s/^([^\015\012]*)\015?\012//) { |
|
|
478 | push @msg, $1; |
|
|
479 | } |
|
|
480 | |
|
|
481 | for (@msg) { |
|
|
482 | my $m = parse_irc_msg ($_); |
|
|
483 | |
|
|
484 | my $nxt = []; |
|
|
485 | |
|
|
486 | for (@{$self->{cbs}->{lc $m->{command}}}) { |
|
|
487 | $_->($self, $m) and push @$nxt, $_; |
|
|
488 | } |
|
|
489 | |
|
|
490 | $self->{cbs}->{lc $m->{command}} = $nxt; |
|
|
491 | |
|
|
492 | $nxt = []; |
|
|
493 | |
|
|
494 | for (@{$self->{cbs}->{'*'}}) { |
|
|
495 | $_->($self, $m) and push @$nxt, $_; |
|
|
496 | } |
|
|
497 | |
|
|
498 | $self->{cbs}->{'*'} = $nxt; |
|
|
499 | } |
|
|
500 | } |
|
|
501 | |
|
|
502 | |
|
|
503 | =back |
|
|
504 | |
301 | |
505 | =head1 AUTHOR |
302 | =head1 AUTHOR |
506 | |
303 | |
507 | Robin Redeker, C<< <elmex@ta-sa.org> >> |
304 | Robin Redeker, C<< <elmex@ta-sa.org> >> |
508 | |
305 | |
509 | =head1 SEE ALSO |
306 | =head1 SEE ALSO |
|
|
307 | |
|
|
308 | L<Net::IRC3::Connection> |
|
|
309 | |
|
|
310 | L<Net::IRC3::Client> |
510 | |
311 | |
511 | RFC 2812 - Internet Relay Chat: Client Protocol |
312 | RFC 2812 - Internet Relay Chat: Client Protocol |
512 | |
313 | |
513 | =head1 BUGS |
314 | =head1 BUGS |
514 | |
315 | |