ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Net-IRC3/lib/Net/IRC3/Client/Connection.pm
Revision: 1.11
Committed: Wed Jan 3 03:41:54 2007 UTC (19 years, 9 months ago) by elmex
Branch: MAIN
Changes since 1.10: +2 -0 lines
Log Message:
clearing the send_chan and send_srv queues is the only correct thing to do
after sending a message.

File Contents

# User Rev Content
1 elmex 1.1 package Net::IRC3::Client::Connection;
2 elmex 1.4 use base "Net::IRC3::Connection";
3     use Net::IRC3::Util qw/prefix_nick/;
4 elmex 1.1
5 elmex 1.4 our $DEBUG;
6 elmex 1.1
7     =head1 NAME
8    
9     Net::IRC3::Client::Connection - A highlevel IRC connection
10    
11     =head1 SYNOPSIS
12    
13 elmex 1.5 use AnyEvent;
14     use Net::IRC3::Client::Connection;
15 elmex 1.1
16 elmex 1.5 my $c = AnyEvent->condvar;
17 elmex 1.1
18 elmex 1.5 my $timer;
19     my $con = new Net::IRC3::Client::Connection;
20 elmex 1.1
21 elmex 1.5 $con->reg_cb (registered => sub { print "I'm in!\n"; 0 });
22     $con->reg_cb (disconnect => sub { print "I'm out!\n"; 0 });
23     $con->reg_cb (
24     sent => sub {
25     if ($_[2] eq 'PRIVMSG') {
26     print "Sent message!\n";
27     $timer = AnyEvent->timer (after => 1, cb => sub { $c->broadcast });
28     }
29     1
30     }
31     );
32    
33     $con->send_srv (PRIVMSG => "Hello there i'm the cool Net::IRC3 test script!", 'elmex');
34    
35     $con->connect ("localhost", 6667);
36     $con->register (qw/testbot testbot testbot/);
37 elmex 1.1
38 elmex 1.5 $c->wait;
39     undef $timer;
40    
41     $con->disconnect;
42 elmex 1.1
43     =head1 DESCRIPTION
44    
45 elmex 1.5 L<Net::IRC3::Client::Connection> is a highlevel client connection,
46     that manages all the stuff that noone wants to implement again and again
47     when handling with IRC. For example it PONGs the server or keeps track
48     of the users on a channel.
49 elmex 1.1
50 elmex 1.2 =head1 EVENTS
51    
52     The following events are emitted by L<Net::IRC3::Client::Connection>.
53     Use C<reg_cb> as described in L<Net::IRC3::Connection> to register to such an
54     event.
55 elmex 1.1
56     =over 4
57    
58 elmex 1.3 =item B<registered>
59    
60     Emitted when the connection got successfully registered.
61    
62 elmex 1.2 =item B<channel_add $channel @nicks>
63    
64     Emitted when C<@nicks> are added to the channel C<$channel>,
65     this happens for example when someone JOINs a channel or when you
66     get a RPL_NAMREPLY (see RFC2812).
67    
68     =item B<channel_remove $channel @nicks>
69    
70     Emitted when C<@nicks> are removed from the channel C<$channel>,
71     happens for example when they PART, QUIT or get KICKed.
72    
73     =item B<join $nick $channel $is_myself>
74    
75     Emitted when C<$nick> enters the channel C<$channel> by JOINing.
76     C<$is_myself> is true if youself are the one who JOINs.
77    
78     =item B<part $nick $channel $is_myself $msg>
79    
80     Emitted when C<$nick> PARTs the channel C<$channel>.
81     C<$is_myself> is true if youself are the one who PARTs.
82     C<$msg> is the PART message.
83 elmex 1.1
84 elmex 1.3 =item B<quit $nick $msg>
85    
86     Emitted when the nickname C<$nick> QUITs with the message C<$msg>.
87    
88     =item B<publicmsg $channel $ircmsg>
89    
90     Emitted for NOTICE and PRIVMSG where the target C<$channel> is a channel.
91     C<$ircmsg> is the original IRC message hash like it is returned by C<parse_irc_msg>.
92    
93     =item B<privatemsg $nick $ircmsg>
94    
95     Emitted for NOTICE and PRIVMSG where the target C<$nick> (most of the time you) is a nick.
96     C<$ircmsg> is the original IRC message hash like it is returned by C<parse_irc_msg>.
97    
98 elmex 1.2 =back
99    
100     =head1 METHODS
101    
102     =over 4
103 elmex 1.1
104     =cut
105    
106 elmex 1.2 sub new {
107     my $this = shift;
108     my $class = ref($this) || $this;
109     my $self = $class->SUPER::new (@_);
110 elmex 1.1 $self->reg_cb (irc_001 => \&welcome_cb);
111     $self->reg_cb (irc_join => \&join_cb);
112     $self->reg_cb (irc_part => \&part_cb);
113 elmex 1.2 $self->reg_cb (irc_kick => \&kick_cb);
114     $self->reg_cb (irc_quit => \&quit_cb);
115 elmex 1.1 $self->reg_cb (irc_353 => \&namereply_cb);
116     $self->reg_cb (irc_366 => \&endofnames_cb);
117     $self->reg_cb (irc_ping => \&ping_cb);
118    
119     $self->reg_cb (irc_privmsg => \&privmsg_cb);
120     $self->reg_cb (irc_notice => \&privmsg_cb);
121    
122     $self->reg_cb ('irc_*' => \&debug_cb)
123     if $DEBUG;
124     $self->reg_cb ('irc_*' => \&anymsg_cb);
125    
126 elmex 1.2 $self->reg_cb (channel_remove => \&channel_remove_event);
127     $self->reg_cb (channel_add => \&channel_add_event);
128    
129     return $self;
130     }
131    
132     =item B<register ($nick, $user, $real)>
133    
134     Sends the IRC registration commands NICK and USER.
135    
136     =cut
137    
138     sub register {
139     my ($self, $nick, $user, $real) = @_;
140    
141 elmex 1.1 $self->send_msg (undef, "NICK", undef, $nick);
142     $self->send_msg (undef, "USER", $real || $nick, $user || $nick, "*", "0");
143    
144     $self->{nick} = $nick;
145     $self->{user} = $user;
146     $self->{real} = $real;
147     }
148    
149     =item B<nick ()>
150    
151     Returns the current nickname, under which this connection
152     is registered at the IRC server. It might be different from the
153     one that was passed to C<register> as a nick-collision might happened
154     on login.
155    
156     =cut
157    
158     sub nick { $_[0]->{nick} }
159    
160     =item B<channel_list ()>
161    
162 elmex 1.2 This returns a hash reference. The keys are the currently joined channels. The values
163     are hash references which contain the joined nicks as key.
164 elmex 1.1
165     =cut
166    
167     sub channel_list {
168     my ($self) = @_;
169 elmex 1.9 return $self->{channels} || {};
170 elmex 1.1 }
171    
172 elmex 1.5 =item B<send_srv ($command, $trailing, @params)>
173 elmex 1.1
174 elmex 1.5 This function sends an IRC message that is constructed by C<mk_msg (undef, $command, $trailing, @params)> (see L<Net::IRC3::Util>).
175 elmex 1.1 If the connection isn't yet registered (for example if the connection is slow) and hasn't got a
176     welcome (IRC command 001) from the server yet, the IRC message is queued until it gets a welcome.
177    
178     =cut
179    
180     sub send_srv {
181     my ($self, @msg) = @_;
182    
183     if ($self->{connected}) {
184     $self->send_msg (undef, @msg);
185    
186     } else {
187     push @{$self->{con_queue}}, \@msg;
188     }
189     }
190    
191     =item B<clear_srv_queue>
192    
193     Clears the server send queue.
194    
195     =cut
196    
197     sub clear_srv_queue {
198     my ($self) = @_;
199     $self->{con_queue} = [];
200     }
201    
202    
203 elmex 1.5 =item B<send_chan ($channel, $command, $trailing, @params))>
204    
205     This function sends a message (constructed by C<mk_msg (undef, $command, $trailing, @params)>
206     to the server, like C<send_srv> only that it will queue the messages if it hasn't joined the
207     channel C<$channel> yet. The queued messages will be send once the connection successfully
208     JOINed the C<$channel>.
209 elmex 1.1
210     =cut
211    
212     sub send_chan {
213     my ($self, $chan, @msg) = @_;
214    
215 elmex 1.2 if ($self->{channels}->{lc $chan}) {
216 elmex 1.1 $self->send_msg (undef, @msg);
217    
218     } else {
219     push @{$self->{chan_queue}->{lc $chan}}, \@msg;
220     }
221     }
222    
223     =item B<clear_chan_queue ($channel)>
224    
225     Clears the channel queue of the channel C<$channel>.
226    
227     =cut
228    
229     sub clear_chan_queue {
230     my ($self, $chan) = @_;
231     $self->{chan_queue}->{lc $chan} = [];
232     }
233    
234     ################################################################################
235 elmex 1.2 # Private utility functions
236     ################################################################################
237    
238     sub _was_me {
239     my ($self, $msg) = @_;
240 elmex 1.4 lc prefix_nick ($msg) eq lc $self->nick ()
241 elmex 1.2 }
242    
243     ################################################################################
244 elmex 1.1 # Callbacks
245     ################################################################################
246    
247 elmex 1.2 sub channel_remove_event {
248     my ($self, $chan, @nicks) = @_;
249    
250     $chan = lc $chan;
251     for my $nick (@nicks) {
252     $nick = lc $nick;
253    
254     if ($nick eq lc $self->nick ()) {
255     delete $self->{chan_queue}->{$chan};
256     delete $self->{channels}->{$chan};
257     last;
258     } else {
259     delete $self->{channels}->{$chan}->{$nick};
260     }
261     }
262    
263     1;
264     }
265    
266     sub channel_add_event {
267     my ($self, $chan, @nicks) = @_;
268     $chan = lc $chan;
269    
270     for my $nick (@nicks) {
271     $nick = lc $nick;
272    
273     if ($nick eq lc $self->nick ()) {
274     for (@{$self->{chan_queue}->{$chan}}) {
275     $self->send_msg (undef, @$_);
276     }
277 elmex 1.11 $self->clear_chan_queue ($chan);
278 elmex 1.2 }
279    
280     $self->{channels}->{$chan}->{$nick} = 1;
281     }
282    
283    
284     1;
285     }
286    
287 elmex 1.1 sub anymsg_cb {
288     my ($self, $msg) = @_;
289    
290     my $cmd = lc $msg->{command};
291    
292     if ( $cmd ne "privmsg"
293     and $cmd ne "notice"
294     and $cmd ne "part"
295     and $cmd ne "join"
296     )
297     {
298     $self->event (statmsg => $msg);
299     }
300    
301     1;
302     }
303    
304     sub privmsg_cb {
305     my ($self, $msg) = @_;
306    
307 elmex 1.3 my $targ = $msg->{params}->[0];
308     if ($targ =~ m/^(?:[#+&]|![A-Z0-9]{5})/) {
309     $self->event (publicmsg => $targ, $msg);
310 elmex 1.1
311     } else {
312 elmex 1.3 $self->event (privatemsg => $targ, $msg);
313 elmex 1.1 }
314    
315     1;
316     }
317    
318     sub welcome_cb {
319     my ($self, $msg) = @_;
320    
321     $self->{connected} = 1;
322    
323 elmex 1.2 $self->event ('registered');
324    
325 elmex 1.1 for (@{$self->{con_queue}}) {
326     $self->send_msg (undef, @$_);
327     }
328 elmex 1.11 $self->clear_srv_queue ();
329 elmex 1.1
330     1;
331     }
332    
333     sub ping_cb {
334     my ($self, $msg) = @_;
335 elmex 1.8 $self->send_msg (undef, "PONG", $msg->{params}->[0]);
336 elmex 1.2
337     1;
338 elmex 1.1 }
339    
340     sub namereply_cb {
341     my ($self, $msg) = @_;
342 elmex 1.2 my @nicks = split / /, $msg->{trailing};
343     push @{$self->{_tmp_namereply}}, @nicks;
344 elmex 1.10
345     1;
346 elmex 1.1 }
347    
348     sub endofnames_cb {
349     my ($self, $msg) = @_;
350 elmex 1.2 my $chan = lc $msg->{params}->[1];
351 elmex 1.4 $self->event (channel_add => $chan, map { s/^[@\+]//; $_ } @{delete $self->{_tmp_namereply}});
352 elmex 1.10
353     1;
354 elmex 1.1 }
355    
356     sub join_cb {
357     my ($self, $msg) = @_;
358 elmex 1.2 my $chan = $msg->{params}->[0];
359 elmex 1.4 my $nick = prefix_nick ($msg);
360 elmex 1.1
361 elmex 1.2 $self->event (join => $nick, $chan, $self->_was_me ($msg));
362     $self->event (channel_add => $chan, $nick);
363 elmex 1.1
364 elmex 1.2 1;
365     }
366    
367     sub part_cb {
368     my ($self, $msg) = @_;
369     my $chan = $msg->{params}->[0];
370 elmex 1.4 my $nick = prefix_nick ($msg);
371 elmex 1.1
372 elmex 1.2 $self->event (part => $nick, $chan, $self->_was_me ($msg), $msg->{params}->[1]);
373     $self->event (channel_remove => $chan, $nick);
374 elmex 1.1
375 elmex 1.2 1;
376     }
377 elmex 1.1
378 elmex 1.2 sub kick_cb {
379     my ($self, $msg) = @_;
380     my $chan = $msg->{params}->[0];
381     my $kicked_nick = $msg->{params}->[1];
382 elmex 1.1
383 elmex 1.2 $self->event (channel_remove => $chan, $kicked_nick);
384 elmex 1.1
385     1;
386     }
387    
388 elmex 1.2 sub quit_cb {
389 elmex 1.1 my ($self, $msg) = @_;
390 elmex 1.4 my $nick = prefix_nick ($msg);
391 elmex 1.1
392 elmex 1.2 $self->event (quit => $nick, $msg->{params}->[1]);
393 elmex 1.1
394 elmex 1.2 for (keys %{$self->{channels}}) {
395     $self->event (channel_remove => $_, $nick);
396 elmex 1.1 }
397 elmex 1.10
398     1;
399 elmex 1.1 }
400    
401     sub debug_cb {
402     my ($self, $msg) = @_;
403     print "$self->{h}:$self->{p} > ";
404     my $par = delete $msg->{params};
405     print (join " ", map { $_ => $msg->{$_} } sort keys %$msg);
406     print " params:";
407     print (join ",", @$par);
408     print "\n";
409 elmex 1.10
410     1;
411 elmex 1.1 }
412    
413     =back
414    
415     =head1 EXAMPLES
416    
417     See samples/netirc3cl and other samples in samples/ for some examples on how to use Net::IRC3::Client::Connection.
418    
419     =head1 AUTHOR
420    
421     Robin Redeker, C<< <elmex@ta-sa.org> >>
422    
423     =head1 SEE ALSO
424    
425 elmex 1.7 L<Net::IRC3::Connection>
426 elmex 1.1
427     RFC 2812 - Internet Relay Chat: Client Protocol
428    
429     =head1 COPYRIGHT & LICENSE
430    
431 elmex 1.6 Copyright 2006 Robin Redeker, all rights reserved.
432 elmex 1.1
433     This program is free software; you can redistribute it and/or modify it
434     under the same terms as Perl itself.
435    
436     =cut
437    
438     1;