line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package AnyEvent::IRC::Client; |
2
|
1
|
|
|
1
|
|
2019
|
use common::sense; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
7
|
|
3
|
|
|
|
|
|
|
|
4
|
1
|
|
|
1
|
|
54
|
use Scalar::Util qw/weaken/; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
58
|
|
5
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
14
|
use Encode; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
82
|
|
7
|
1
|
|
|
1
|
|
5
|
use AnyEvent::Socket; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
181
|
|
8
|
1
|
|
|
1
|
|
14
|
use AnyEvent::Handle; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
27
|
|
9
|
|
|
|
|
|
|
use AnyEvent::IRC::Util |
10
|
1
|
|
|
|
|
86
|
qw/prefix_nick decode_ctcp split_prefix |
11
|
|
|
|
|
|
|
is_nick_prefix join_prefix encode_ctcp |
12
|
1
|
|
|
1
|
|
6
|
split_unicode_string mk_msg/; |
|
1
|
|
|
|
|
1
|
|
13
|
|
|
|
|
|
|
|
14
|
1
|
|
|
1
|
|
5
|
use base AnyEvent::IRC::Connection::; |
|
1
|
|
|
|
|
7
|
|
|
1
|
|
|
|
|
10819
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 NAME |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
AnyEvent::IRC::Client - A highlevel IRC connection |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=head1 SYNOPSIS |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
use AnyEvent; |
23
|
|
|
|
|
|
|
use AnyEvent::IRC::Client; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
my $c = AnyEvent->condvar; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
my $timer; |
28
|
|
|
|
|
|
|
my $con = new AnyEvent::IRC::Client; |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
$con->reg_cb (connect => sub { |
31
|
|
|
|
|
|
|
my ($con, $err) = @_; |
32
|
|
|
|
|
|
|
if (defined $err) { |
33
|
|
|
|
|
|
|
warn "connect error: $err\n"; |
34
|
|
|
|
|
|
|
return; |
35
|
|
|
|
|
|
|
} |
36
|
|
|
|
|
|
|
}); |
37
|
|
|
|
|
|
|
$con->reg_cb (registered => sub { print "I'm in!\n"; }); |
38
|
|
|
|
|
|
|
$con->reg_cb (disconnect => sub { print "I'm out!\n"; $c->broadcast }); |
39
|
|
|
|
|
|
|
$con->reg_cb ( |
40
|
|
|
|
|
|
|
sent => sub { |
41
|
|
|
|
|
|
|
my ($con) = @_; |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
if ($_[2] eq 'PRIVMSG') { |
44
|
|
|
|
|
|
|
print "Sent message!\n"; |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
$timer = AnyEvent->timer ( |
47
|
|
|
|
|
|
|
after => 1, |
48
|
|
|
|
|
|
|
cb => sub { |
49
|
|
|
|
|
|
|
undef $timer; |
50
|
|
|
|
|
|
|
$con->disconnect ('done') |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
); |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
); |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
$con->send_srv ( |
58
|
|
|
|
|
|
|
PRIVMSG => 'elmex', |
59
|
|
|
|
|
|
|
"Hello there I'm the cool AnyEvent::IRC test script!" |
60
|
|
|
|
|
|
|
); |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
$con->connect ("localhost", 6667, { nick => 'testbot' }); |
63
|
|
|
|
|
|
|
$c->wait; |
64
|
|
|
|
|
|
|
$con->disconnect; |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=head1 DESCRIPTION |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
L<AnyEvent::IRC::Client> is a (nearly) highlevel client connection, |
69
|
|
|
|
|
|
|
that manages all the stuff that noone wants to implement again and again |
70
|
|
|
|
|
|
|
when handling with IRC. For example it PONGs the server or keeps track |
71
|
|
|
|
|
|
|
of the users on a channel. |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
This module also implements the ISUPPORT (command 005) extension of the IRC protocol |
74
|
|
|
|
|
|
|
(see http://www.irc.org/tech_docs/005.html) and will enable the NAMESX and UHNAMES |
75
|
|
|
|
|
|
|
extensions when supported by the server. |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
Also CTCP support is implemented, all CTCP messages will be decoded and events |
78
|
|
|
|
|
|
|
for them will be generated. You can configure auto-replies to certain CTCP commands |
79
|
|
|
|
|
|
|
with the C<ctcp_auto_reply> method, or you can generate the replies yourself. |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=head2 A NOTE TO CASE MANAGEMENT |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
The case insensitivity of channel names and nicknames can lead to headaches |
84
|
|
|
|
|
|
|
when dealing with IRC in an automated client which tracks channels and nicknames. |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
I tried to preserve the case in all channel and nicknames |
87
|
|
|
|
|
|
|
AnyEvent::IRC::Client passes to his user. But in the internal |
88
|
|
|
|
|
|
|
structures I'm using lower case for the channel names. |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
The returned hash from C<channel_list> for example has the lower case of the |
91
|
|
|
|
|
|
|
joined channels as keys. |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
But I tried to preserve the case in all events that are emitted. |
94
|
|
|
|
|
|
|
Please keep this in mind when handling the events. |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
For example a user might joins #TeSt and parts #test later. |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=head1 EVENTS |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
The following events are emitted by L<AnyEvent::IRC::Client>. |
101
|
|
|
|
|
|
|
Use C<reg_cb> as described in L<Object::Event> to register to such an event. |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=over 4 |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
=item registered |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
Emitted when the connection got successfully registered and the end of the MOTD |
108
|
|
|
|
|
|
|
(IRC command 376 or 422 (No MOTD file found)) was seen, so you can start sending |
109
|
|
|
|
|
|
|
commands and all ISUPPORT/PROTOCTL handshaking has been done. |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=item channel_add => $msg, $channel, @nicks |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
Emitted when C<@nicks> are added to the channel C<$channel>, |
114
|
|
|
|
|
|
|
this happens for example when someone JOINs a channel or when you |
115
|
|
|
|
|
|
|
get a RPL_NAMREPLY (see RFC1459). |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
C<$msg> is the IRC message hash that as returned by C<parse_irc_msg>. |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
=item channel_remove => $msg, $channel, @nicks |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
Emitted when C<@nicks> are removed from the channel C<$channel>, |
123
|
|
|
|
|
|
|
happens for example when they PART, QUIT or get KICKed. |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
C<$msg> is the IRC message hash that as returned by C<parse_irc_msg> |
126
|
|
|
|
|
|
|
or undef if the reason for the removal was a disconnect on our end. |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=item channel_change => $msg, $channel, $old_nick, $new_nick, $is_myself |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
Emitted when a nickname on a channel changes. This is emitted when a NICK |
131
|
|
|
|
|
|
|
change occurs from C<$old_nick> to C<$new_nick> give the application a chance |
132
|
|
|
|
|
|
|
to quickly analyze what channels were affected. C<$is_myself> is true when |
133
|
|
|
|
|
|
|
yourself was the one who changed the nick. |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=item channel_nickmode_update => $channel, $dest |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
This event is emitted when the (user) mode (eg. op status) of an occupant of |
138
|
|
|
|
|
|
|
a channel changes. C<$dest> is the nickname on the C<$channel> who's mode was |
139
|
|
|
|
|
|
|
updated. |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=item channel_topic => $channel, $topic, $who |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
This is emitted when the topic for a channel is discovered. C<$channel> |
144
|
|
|
|
|
|
|
is the channel for which C<$topic> is the current topic now. |
145
|
|
|
|
|
|
|
Which is set by C<$who>. C<$who> might be undefined when it's not known |
146
|
|
|
|
|
|
|
who set the channel topic. |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=item ident_change => $nick, $ident |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
Whenever the user and host of C<$nick> has been determined or a change |
151
|
|
|
|
|
|
|
happened this event is emitted. |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=item join => $nick, $channel, $is_myself |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
Emitted when C<$nick> enters the channel C<$channel> by JOINing. |
156
|
|
|
|
|
|
|
C<$is_myself> is true if yourself are the one who JOINs. |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=item part => $nick, $channel, $is_myself, $msg |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
Emitted when C<$nick> PARTs the channel C<$channel>. |
161
|
|
|
|
|
|
|
C<$is_myself> is true if yourself are the one who PARTs. |
162
|
|
|
|
|
|
|
C<$msg> is the PART message. |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
=item kick => $kicked_nick, $channel, $is_myself, $msg, $kicker_nick |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
Emitted when C<$kicked_nick> is KICKed from the channel C<$channel> by |
167
|
|
|
|
|
|
|
C<$kicker_nick>. C<$is_myself> is true if yourself are the one who got KICKed. |
168
|
|
|
|
|
|
|
C<$msg> is the KICK message. |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
=item nick_change => $old_nick, $new_nick, $is_myself |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
Emitted when C<$old_nick> is renamed to C<$new_nick>. |
173
|
|
|
|
|
|
|
C<$is_myself> is true when yourself was the one who changed the nick. |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=item away_status_change => $bool |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
Emitted whenever a presence/away status change for you was detected. |
178
|
|
|
|
|
|
|
C<$bool> is true if you are now away, or false/undef if you are not |
179
|
|
|
|
|
|
|
away anymore. |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
You can change your away status by emitting the C<AWAY> IRC command: |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
$cl->send_srv (AWAY => "I'm not here right now"); |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
Or reset it: |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
$cl->send_srv ('AWAY'); |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
=item ctcp => $src, $target, $tag, $msg, $type |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
Emitted when a CTCP message was found in either a NOTICE or PRIVMSG |
192
|
|
|
|
|
|
|
message. C<$tag> is the CTCP message tag. (eg. "PING", "VERSION", ...). |
193
|
|
|
|
|
|
|
C<$msg> is the CTCP message and C<$type> is either "NOTICE" or "PRIVMSG". |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
C<$src> is the source nick the message came from. |
196
|
|
|
|
|
|
|
C<$target> is the target nickname (yours) or the channel the ctcp was sent |
197
|
|
|
|
|
|
|
on. |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=item "ctcp_$tag", => $src, $target, $msg, $type |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
Emitted when a CTCP message was found in either a NOTICE or PRIVMSG |
202
|
|
|
|
|
|
|
message. C<$tag> is the CTCP message tag (in lower case). (eg. "ping", "version", ...). |
203
|
|
|
|
|
|
|
C<$msg> is the CTCP message and C<$type> is either "NOTICE" or "PRIVMSG". |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
C<$src> is the source nick the message came from. |
206
|
|
|
|
|
|
|
C<$target> is the target nickname (yours) or the channel the ctcp was sent |
207
|
|
|
|
|
|
|
on. |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
=item dcc_ready => $id, $dest, $type, $local_ip, $local_port |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
Whenever a locally initiated DCC request is made this event is emitted |
212
|
|
|
|
|
|
|
after the listening socket has been setup. |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
C<$id> is the DCC connection ID. |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
C<$dest> and C<$type> are the destination and type of the DCC request. |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
C<$local_ip> is the C<$local_ip> argument passed to C<start_dcc> or |
219
|
|
|
|
|
|
|
the IP the socket is bound to. |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
C<$local_port> is the TCP port is the socket is listening on. |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=item dcc_request => $id, $src, $type, $arg, $addr, $port |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
Whenever we receive a DCC offer from someone else this event is emitted. |
226
|
|
|
|
|
|
|
C<$id> is the DCC connection ID, C<$src> is his nickname, C<$type> is the DCC |
227
|
|
|
|
|
|
|
type in lower cases (eg. 'chat'). C<$arg> is the DCC type argument. C<$addr> |
228
|
|
|
|
|
|
|
is the IP address we can reach him at in ASCII encoded human readable form (eg. |
229
|
|
|
|
|
|
|
something like "127.0.0.1"). And C<$port> is the TCP port we have to connect |
230
|
|
|
|
|
|
|
to. |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
To answer to his request you can just call C<dcc_accept> with the C<$id>. |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=item dcc_accepted => $id, $type, $hdl |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
When the locally listening DCC socket has received a connection this event is emitted. |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
C<$id> and C<$type> are the DCC connection ID and type of the DCC request. |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
C<$hdl> is a pre-configured L<AnyEvent::Handle> object, which you only |
241
|
|
|
|
|
|
|
need to care about in case you want to implement your own DCC protocol. |
242
|
|
|
|
|
|
|
(This event has the on_error and on_eof events pre-configured to cleanup |
243
|
|
|
|
|
|
|
the data structures in this connection). |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
=item dcc_connected => $id, $type, $hdl |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
Whenever we accepted a DCC offer and connected by using C<dcc_accept> this |
248
|
|
|
|
|
|
|
event is emitted. C<$id> is the DCC connection ID. C<$type> is the dcc type in |
249
|
|
|
|
|
|
|
lower case. C<$hdl> is the L<AnyEvent::Handle> object of the connection (see |
250
|
|
|
|
|
|
|
also C<dcc_accepted> above). |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
=item dcc_close => $id, $type, $reason |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
This event is emitted whenever a DCC connection is terminated. |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
C<$id> and C<$type> are the DCC connection ID and type of the DCC request. |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
C<$reason> is a human readable string indicating the reason for the end of |
259
|
|
|
|
|
|
|
the DCC request. |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
=item dcc_chat_msg => $id, $msg |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
This event is emitted for a DCC CHAT message. C<$id> is the DCC connection |
264
|
|
|
|
|
|
|
ID we received the message on. And C<$msg> is the message he sent us. |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=item quit => $nick, $msg |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
Emitted when the nickname C<$nick> QUITs with the message C<$msg>. |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=item publicmsg => $channel, $ircmsg |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
Emitted for NOTICE and PRIVMSG where the target C<$channel> is a channel. |
273
|
|
|
|
|
|
|
C<$ircmsg> is the original IRC message hash like it is returned by C<parse_irc_msg>. |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
The last parameter of the C<$ircmsg> will have all CTCP messages stripped off. |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
=item privatemsg => $nick, $ircmsg |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
Emitted for NOTICE and PRIVMSG where the target C<$nick> (most of the time you) is a nick. |
280
|
|
|
|
|
|
|
C<$ircmsg> is the original IRC message hash like it is returned by C<parse_irc_msg>. |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
The last parameter of the C<$ircmsg> will have all CTCP messages stripped off. |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=item error => $code, $message, $ircmsg |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
Emitted when any error occurs. C<$code> is the 3 digit error id string from RFC |
287
|
|
|
|
|
|
|
1459 or the string 'ERROR'. C<$message> is a description of the error. |
288
|
|
|
|
|
|
|
C<$ircmsg> is the complete error irc message. |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
You may use AnyEvent::IRC::Util::rfc_code_to_name to convert C<$code> to the error |
291
|
|
|
|
|
|
|
name from the RFC 2812. eg.: |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
rfc_code_to_name ('471') => 'ERR_CHANNELISFULL' |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
NOTE: This event is also emitted when a 'ERROR' message is received. |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
=item debug_send => $command, @params |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
Is emitted everytime some command is sent. |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
=item debug_recv => $ircmsg |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
Is emitted everytime some command was received. |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
=back |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
=head1 METHODS |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
=over 4 |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
=item $cl = AnyEvent::IRC::Client->new (%args) |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
This is the constructor of a L<AnyEvent::IRC::Client> object, |
314
|
|
|
|
|
|
|
which stands logically for a client connected to ONE IRC server. |
315
|
|
|
|
|
|
|
You can reuse it and call C<connect> once it disconnected. |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
B<NOTE:> You are free to use the hash member C<heap> to store any associated |
318
|
|
|
|
|
|
|
data with this object. For example retry timers or anything else. |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
C<%args> may contain these options: |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=over 4 |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
=item send_initial_whois => $bool |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
If this option is enabled an initial C<WHOIS> command is sent to your own |
327
|
|
|
|
|
|
|
NICKNAME to determine your own I<ident>. See also the method C<nick_ident>. |
328
|
|
|
|
|
|
|
This is necessary to ensure that the information about your own nickname |
329
|
|
|
|
|
|
|
is available as early as possible for the C<send_long_message> method. |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
C<$bool> is C<false> by default. |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
=back |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
=cut |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
my %LOWER_CASEMAP = ( |
338
|
|
|
|
|
|
|
rfc1459 => sub { tr/A-Z[]\\\^/a-z{}|~/ }, |
339
|
|
|
|
|
|
|
'strict-rfc1459' => sub { tr/A-Z[]\\/a-z{}|/ }, |
340
|
|
|
|
|
|
|
ascii => sub { tr/A-Z/a-z/ }, |
341
|
|
|
|
|
|
|
); |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
sub new { |
344
|
0
|
|
|
0
|
1
|
|
my $this = shift; |
345
|
0
|
|
0
|
|
|
|
my $class = ref($this) || $this; |
346
|
0
|
|
|
|
|
|
my $self = $class->SUPER::new (@_); |
347
|
|
|
|
|
|
|
|
348
|
0
|
|
|
|
|
|
$self->reg_cb (irc_001 => \&welcome_cb); |
349
|
0
|
|
|
|
|
|
$self->reg_cb (irc_376 => \&welcome_cb); |
350
|
0
|
|
|
|
|
|
$self->reg_cb (irc_422 => \&welcome_cb); |
351
|
0
|
|
|
|
|
|
$self->reg_cb (irc_005 => \&isupport_cb); |
352
|
0
|
|
|
|
|
|
$self->reg_cb (irc_join => \&join_cb); |
353
|
0
|
|
|
|
|
|
$self->reg_cb (irc_nick => \&nick_cb); |
354
|
0
|
|
|
|
|
|
$self->reg_cb (irc_part => \&part_cb); |
355
|
0
|
|
|
|
|
|
$self->reg_cb (irc_kick => \&kick_cb); |
356
|
0
|
|
|
|
|
|
$self->reg_cb (irc_quit => \&quit_cb); |
357
|
0
|
|
|
|
|
|
$self->reg_cb (irc_mode => \&mode_cb); |
358
|
0
|
|
|
|
|
|
$self->reg_cb (irc_353 => \&namereply_cb); |
359
|
0
|
|
|
|
|
|
$self->reg_cb (irc_366 => \&endofnames_cb); |
360
|
0
|
|
|
|
|
|
$self->reg_cb (irc_352 => \&whoreply_cb); |
361
|
0
|
|
|
|
|
|
$self->reg_cb (irc_311 => \&whoisuser_cb); |
362
|
0
|
|
|
|
|
|
$self->reg_cb (irc_305 => \&away_change_cb); |
363
|
0
|
|
|
|
|
|
$self->reg_cb (irc_306 => \&away_change_cb); |
364
|
0
|
|
|
|
|
|
$self->reg_cb (irc_ping => \&ping_cb); |
365
|
0
|
|
|
|
|
|
$self->reg_cb (irc_pong => \&pong_cb); |
366
|
|
|
|
|
|
|
|
367
|
0
|
|
|
|
|
|
$self->reg_cb (irc_privmsg => \&privmsg_cb); |
368
|
0
|
|
|
|
|
|
$self->reg_cb (irc_notice => \&privmsg_cb); |
369
|
|
|
|
|
|
|
|
370
|
0
|
|
|
|
|
|
$self->reg_cb ('irc_*' => \&debug_cb); |
371
|
0
|
|
|
|
|
|
$self->reg_cb ('irc_*' => \&anymsg_cb); |
372
|
0
|
|
|
|
|
|
$self->reg_cb ('irc_*' => \&update_ident_cb); |
373
|
|
|
|
|
|
|
|
374
|
0
|
|
|
|
|
|
$self->reg_cb (disconnect => \&disconnect_cb); |
375
|
|
|
|
|
|
|
|
376
|
0
|
|
|
|
|
|
$self->reg_cb (irc_332 => \&rpl_topic_cb); |
377
|
0
|
|
|
|
|
|
$self->reg_cb (irc_topic => \&topic_change_cb); |
378
|
|
|
|
|
|
|
|
379
|
0
|
|
|
|
|
|
$self->reg_cb (ctcp => \&ctcp_auto_reply_cb); |
380
|
|
|
|
|
|
|
|
381
|
0
|
|
|
|
|
|
$self->reg_cb (registered => \®istered_cb); |
382
|
|
|
|
|
|
|
|
383
|
0
|
|
|
|
|
|
$self->reg_cb (nick_change => \&update_ident_nick_change_cb); |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
$self->{def_nick_change} = $self->{nick_change} = |
386
|
|
|
|
|
|
|
sub { |
387
|
0
|
|
|
0
|
|
|
my ($old_nick) = @_; |
388
|
0
|
|
|
|
|
|
"${old_nick}_" |
389
|
0
|
|
|
|
|
|
}; |
390
|
|
|
|
|
|
|
|
391
|
0
|
|
|
|
|
|
$self->_setup_internal_dcc_handlers; |
392
|
|
|
|
|
|
|
|
393
|
0
|
|
|
|
|
|
$self->cleanup; |
394
|
|
|
|
|
|
|
|
395
|
0
|
|
|
|
|
|
return $self; |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
sub cleanup { |
399
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
400
|
|
|
|
|
|
|
|
401
|
0
|
|
|
|
|
|
$self->{channel_list} = { }; |
402
|
0
|
|
|
|
|
|
$self->{isupport} = { }; |
403
|
0
|
|
|
|
|
|
$self->{casemap_func} = $LOWER_CASEMAP{rfc1459}; |
404
|
0
|
|
|
|
|
|
$self->{prefix_chars} = '@+'; |
405
|
0
|
|
|
|
|
|
$self->{prefix2mode} = { '@' => 'o', '+' => 'v' }; |
406
|
0
|
|
|
|
|
|
$self->{channel_chars} = '#&'; |
407
|
|
|
|
|
|
|
|
408
|
0
|
|
|
|
|
|
$self->{change_nick_cb_guard} = |
409
|
|
|
|
|
|
|
$self->reg_cb ( |
410
|
|
|
|
|
|
|
irc_437 => \&change_nick_login_cb, |
411
|
|
|
|
|
|
|
irc_433 => \&change_nick_login_cb, |
412
|
|
|
|
|
|
|
); |
413
|
|
|
|
|
|
|
|
414
|
0
|
|
|
|
|
|
delete $self->{away_status}; |
415
|
0
|
|
|
|
|
|
delete $self->{dcc}; |
416
|
0
|
|
|
|
|
|
delete $self->{dcc_id}; |
417
|
0
|
|
|
|
|
|
delete $self->{_tmp_namereply}; |
418
|
0
|
|
|
|
|
|
delete $self->{last_pong_recv}; |
419
|
0
|
|
|
|
|
|
delete $self->{last_ping_sent}; |
420
|
0
|
|
|
|
|
|
delete $self->{_ping_timer}; |
421
|
0
|
|
|
|
|
|
delete $self->{con_queue}; |
422
|
0
|
|
|
|
|
|
delete $self->{chan_queue}; |
423
|
0
|
|
|
|
|
|
delete $self->{registered}; |
424
|
0
|
|
|
|
|
|
delete $self->{idents}; |
425
|
0
|
|
|
|
|
|
delete $self->{nick}; |
426
|
0
|
|
|
|
|
|
delete $self->{user}; |
427
|
0
|
|
|
|
|
|
delete $self->{real}; |
428
|
0
|
|
|
|
|
|
delete $self->{server_pass}; |
429
|
0
|
|
|
|
|
|
delete $self->{register_cb_guard}; |
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
=item $cl->connect ($host, $port) |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
=item $cl->connect ($host, $port, $info) |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
This method does the same as the C<connect> method of L<AnyEvent::Connection>, |
437
|
|
|
|
|
|
|
but if the C<$info> parameter is passed it will automatically register with the |
438
|
|
|
|
|
|
|
IRC server upon connect for you, and you won't have to call the C<register> |
439
|
|
|
|
|
|
|
method yourself. If C<$info> only contains the timeout value it will not |
440
|
|
|
|
|
|
|
automatically connect, this way you can pass a custom connect timeout value |
441
|
|
|
|
|
|
|
without having to register. |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
The keys of the hash reference you can pass in C<$info> are: |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
nick - the nickname you want to register as |
446
|
|
|
|
|
|
|
user - your username |
447
|
|
|
|
|
|
|
real - your realname |
448
|
|
|
|
|
|
|
password - the server password |
449
|
|
|
|
|
|
|
timeout - the TCP connect timeout |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
All keys, except C<nick> are optional. |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
=cut |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
sub connect { |
456
|
0
|
|
|
0
|
1
|
|
my ($self, $host, $port, $info) = @_; |
457
|
|
|
|
|
|
|
|
458
|
0
|
|
|
|
|
|
my $timeout = delete $info->{timeout}; |
459
|
|
|
|
|
|
|
|
460
|
0
|
0
|
0
|
|
|
|
if (defined $info and keys %$info) { |
461
|
|
|
|
|
|
|
$self->{register_cb_guard} = $self->reg_cb ( |
462
|
|
|
|
|
|
|
ext_before_connect => sub { |
463
|
0
|
|
|
0
|
|
|
my ($self, $err) = @_; |
464
|
|
|
|
|
|
|
|
465
|
0
|
0
|
|
|
|
|
unless ($err) { |
466
|
0
|
|
|
|
|
|
$self->register ( |
467
|
|
|
|
|
|
|
$info->{nick}, $info->{user}, $info->{real}, $info->{password} |
468
|
|
|
|
|
|
|
); |
469
|
|
|
|
|
|
|
} |
470
|
|
|
|
|
|
|
|
471
|
0
|
|
|
|
|
|
delete $self->{register_cb_guard}; |
472
|
|
|
|
|
|
|
} |
473
|
0
|
|
|
|
|
|
); |
474
|
|
|
|
|
|
|
} |
475
|
|
|
|
|
|
|
|
476
|
0
|
|
|
|
|
|
$self->SUPER::connect ($host, $port, $timeout); |
477
|
|
|
|
|
|
|
} |
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
=item $cl->register ($nick, $user, $real, $server_pass) |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
Sends the IRC registration commands NICK and USER. |
482
|
|
|
|
|
|
|
If C<$server_pass> is passed also a PASS command is generated. |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
NOTE: If you passed the nick, user, etc. already to the C<connect> method |
485
|
|
|
|
|
|
|
you won't need to call this method, as L<AnyEvent::IRC::Client> will do that |
486
|
|
|
|
|
|
|
for you. |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
=cut |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
sub register { |
491
|
0
|
|
|
0
|
1
|
|
my ($self, $nick, $user, $real, $pass) = @_; |
492
|
|
|
|
|
|
|
|
493
|
0
|
|
|
|
|
|
$self->{nick} = $nick; |
494
|
0
|
|
|
|
|
|
$self->{user} = $user; |
495
|
0
|
|
|
|
|
|
$self->{real} = $real; |
496
|
0
|
|
|
|
|
|
$self->{server_pass} = $pass; |
497
|
|
|
|
|
|
|
|
498
|
0
|
0
|
|
|
|
|
$self->send_msg ("PASS", $pass) if defined $pass; |
499
|
0
|
|
|
|
|
|
$self->send_msg ("NICK", $nick); |
500
|
0
|
|
0
|
|
|
|
$self->send_msg ("USER", $user || $nick, "*", "0", $real || $nick); |
|
|
|
0
|
|
|
|
|
501
|
|
|
|
|
|
|
} |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
=item $cl->set_nick_change_cb ($callback) |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
This method lets you modify the nickname renaming mechanism when registering |
506
|
|
|
|
|
|
|
the connection. C<$callback> is called with the current nickname as first |
507
|
|
|
|
|
|
|
argument when a ERR_NICKNAMEINUSE or ERR_UNAVAILRESOURCE error occurs on login. |
508
|
|
|
|
|
|
|
The return value of C<$callback> will then be used to change the nickname. |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
If C<$callback> is not defined the default nick change callback will be used |
511
|
|
|
|
|
|
|
again. |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
The default callback appends '_' to the end of the nickname supplied in the |
514
|
|
|
|
|
|
|
C<register> routine. |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
If the callback returns the same nickname that was given it the connection |
517
|
|
|
|
|
|
|
will be terminated. |
518
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
=cut |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
sub set_nick_change_cb { |
522
|
0
|
|
|
0
|
1
|
|
my ($self, $cb) = @_; |
523
|
0
|
0
|
|
|
|
|
$cb = $self->{def_nick_change} unless defined $cb; |
524
|
0
|
|
|
|
|
|
$self->{nick_change} = $cb; |
525
|
|
|
|
|
|
|
} |
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
=item $cl->nick () |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
Returns the current nickname, under which this connection |
530
|
|
|
|
|
|
|
is registered at the IRC server. It might be different from the |
531
|
|
|
|
|
|
|
one that was passed to C<register> as a nick-collision might happened |
532
|
|
|
|
|
|
|
on login. |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
=cut |
535
|
|
|
|
|
|
|
|
536
|
0
|
|
|
0
|
1
|
|
sub nick { $_[0]->{nick} } |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
=item $cl->is_my_nick ($string) |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
This returns true if C<$string> is the nick of ourself. |
541
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
=cut |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
sub is_my_nick { |
545
|
0
|
|
|
0
|
1
|
|
my ($self, $string) = @_; |
546
|
0
|
|
|
|
|
|
$self->eq_str ($string, $self->nick); |
547
|
|
|
|
|
|
|
} |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
=item $cl->registered () |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
Returns a true value when the connection has been registered successful and |
552
|
|
|
|
|
|
|
you can send commands. |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
=cut |
555
|
|
|
|
|
|
|
|
556
|
0
|
|
|
0
|
1
|
|
sub registered { $_[0]->{registered} } |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
=item $cl->channel_list () |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
=item $cl->channel_list ($channel) |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
Without C<$channel> parameter: This returns a hash reference. The keys are the |
563
|
|
|
|
|
|
|
currently joined channels in lower case. The values are hash references which |
564
|
|
|
|
|
|
|
contain the joined nicks as key (NOT in lower case!) and the nick modes as |
565
|
|
|
|
|
|
|
values (as returned from C<nick_modes ()>). |
566
|
|
|
|
|
|
|
|
567
|
|
|
|
|
|
|
If the C<$channel> parameter is given it returns the hash reference of the channel |
568
|
|
|
|
|
|
|
occupants or undef if the channel does not exist. |
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
=cut |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
sub channel_list { |
573
|
0
|
|
|
0
|
1
|
|
my ($self, $chan) = @_; |
574
|
|
|
|
|
|
|
|
575
|
0
|
0
|
|
|
|
|
if (defined $chan) { |
576
|
0
|
|
|
|
|
|
return $self->{channel_list}->{$self->lower_case ($chan)} |
577
|
|
|
|
|
|
|
} else { |
578
|
0
|
|
0
|
|
|
|
return $self->{channel_list} || {}; |
579
|
|
|
|
|
|
|
} |
580
|
|
|
|
|
|
|
} |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
=item $cl->nick_modes ($channel, $nick) |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
This returns the mode map of the C<$nick> on C<$channel>. |
585
|
|
|
|
|
|
|
Returns undef if the channel isn't joined or the user is not on it. |
586
|
|
|
|
|
|
|
Returns a hash reference with the modes the user has as keys and 1's as values. |
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
=cut |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
sub nick_modes { |
591
|
0
|
|
|
0
|
1
|
|
my ($self, $channel, $nick) = @_; |
592
|
|
|
|
|
|
|
|
593
|
0
|
0
|
|
|
|
|
my $c = $self->channel_list ($channel) |
594
|
|
|
|
|
|
|
or return undef; |
595
|
|
|
|
|
|
|
|
596
|
0
|
|
|
|
|
|
my (%lcc) = map { $self->lower_case ($_) => $c->{$_} } keys %$c; |
|
0
|
|
|
|
|
|
|
597
|
0
|
|
|
|
|
|
return $lcc{$self->lower_case ($nick)}; |
598
|
|
|
|
|
|
|
} |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
=item $cl->send_msg (...) |
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
See also L<AnyEvent::IRC::Connection>. |
603
|
|
|
|
|
|
|
|
604
|
|
|
|
|
|
|
=cut |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
sub send_msg { |
607
|
0
|
|
|
0
|
1
|
|
my ($self, @a) = @_; |
608
|
0
|
|
|
|
|
|
$self->event (debug_send => @a); |
609
|
0
|
|
|
|
|
|
$self->SUPER::send_msg (@a); |
610
|
|
|
|
|
|
|
} |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
=item $cl->send_srv ($command, @params) |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
This function sends an IRC message that is constructed by C<mk_msg (undef, |
615
|
|
|
|
|
|
|
$command, @params)> (see L<AnyEvent::IRC::Util>). If the C<registered> event |
616
|
|
|
|
|
|
|
has NOT yet been emitted the messages are queued until that event is emitted, |
617
|
|
|
|
|
|
|
and then sent to the server. |
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
B<NOTE:> If you stop the registered event (with C<stop_event>, see L<Object::Event>) |
620
|
|
|
|
|
|
|
in a callback registered to the C<before_registered> event, the C<send_srv> queue |
621
|
|
|
|
|
|
|
will B<NOT> be flushed and B<NOT> sent to the server! |
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
This allows you to simply write this: |
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
my $cl = AnyEvent::IRC::Client->new; |
626
|
|
|
|
|
|
|
$cl->connect ('irc.freenode.net', 6667, { nick => 'testbot' }); |
627
|
|
|
|
|
|
|
$cl->send_srv (PRIVMSG => 'elmex', 'Hi there!'); |
628
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
Instead of: |
630
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
my $cl = AnyEvent::IRC::Client->new; |
632
|
|
|
|
|
|
|
$cl->reg_cb ( |
633
|
|
|
|
|
|
|
registered => sub { |
634
|
|
|
|
|
|
|
$cl->send_msg (PRIVMSG => 'elmex', 'Hi there!'); |
635
|
|
|
|
|
|
|
} |
636
|
|
|
|
|
|
|
); |
637
|
|
|
|
|
|
|
$cl->connect ('irc.freenode.net', 6667, { nick => 'testbot' }); |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
=cut |
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
sub send_srv { |
642
|
0
|
|
|
0
|
1
|
|
my ($self, @msg) = @_; |
643
|
|
|
|
|
|
|
|
644
|
0
|
0
|
|
|
|
|
if ($self->registered) { |
645
|
0
|
|
|
|
|
|
$self->send_msg (@msg); |
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
} else { |
648
|
0
|
|
|
|
|
|
push @{$self->{con_queue}}, \@msg; |
|
0
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
} |
650
|
|
|
|
|
|
|
} |
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
=item $cl->clear_srv_queue () |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
Clears the server send queue. |
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
=cut |
657
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
sub clear_srv_queue { |
659
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
660
|
0
|
|
|
|
|
|
$self->{con_queue} = []; |
661
|
|
|
|
|
|
|
} |
662
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
=item $cl->send_chan ($channel, $command, @params) |
665
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
This function sends a message (constructed by C<mk_msg (undef, $command, |
667
|
|
|
|
|
|
|
@params)> to the server, like C<send_srv> only that it will queue |
668
|
|
|
|
|
|
|
the messages if it hasn't joined the channel C<$channel> yet. The queued |
669
|
|
|
|
|
|
|
messages will be send once the connection successfully JOINed the C<$channel>. |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
C<$channel> will be lowercased so that any case that comes from the server matches. |
672
|
|
|
|
|
|
|
(Yes, IRC handles upper and lower case as equal :-( |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
Be careful with this, there are chances you might not join the channel you |
675
|
|
|
|
|
|
|
wanted to join. You may wanted to join #bla and the server redirects that |
676
|
|
|
|
|
|
|
and sends you that you joined #blubb. You may use C<clear_chan_queue> to |
677
|
|
|
|
|
|
|
remove the queue after some timeout after joining, so that you don't end up |
678
|
|
|
|
|
|
|
with a memory leak. |
679
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
=cut |
681
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
sub send_chan { |
683
|
0
|
|
|
0
|
1
|
|
my ($self, $chan, @msg) = @_; |
684
|
|
|
|
|
|
|
|
685
|
0
|
0
|
|
|
|
|
if ($self->{channel_list}->{$self->lower_case ($chan)}) { |
686
|
0
|
|
|
|
|
|
$self->send_msg (@msg); |
687
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
} else { |
689
|
0
|
|
|
|
|
|
push @{$self->{chan_queue}->{$self->lower_case ($chan)}}, \@msg; |
|
0
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
} |
691
|
|
|
|
|
|
|
} |
692
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
=item $cl->clear_chan_queue ($channel) |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
Clears the channel queue of the channel C<$channel>. |
696
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
=cut |
698
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
sub clear_chan_queue { |
700
|
0
|
|
|
0
|
1
|
|
my ($self, $chan) = @_; |
701
|
0
|
|
|
|
|
|
$self->{chan_queue}->{$self->lower_case ($chan)} = []; |
702
|
|
|
|
|
|
|
} |
703
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
=item my (@lines) = $cl->send_long_message ($encoding, $overhead, $cmd, @params, $msg) |
705
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
As IRC only allows 512 byte blocks of messages and sometimes |
707
|
|
|
|
|
|
|
your messages might get longer, you have a problem. This method |
708
|
|
|
|
|
|
|
will solve your problem: |
709
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
This method can be used to split up long messages into multiple |
711
|
|
|
|
|
|
|
commands. |
712
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
C<$cmd> and C<@params> are the IRC command and it's first parameters, |
714
|
|
|
|
|
|
|
except the last one: the C<$msg>. C<$msg> can be a Unicode string, |
715
|
|
|
|
|
|
|
which will be encoded in C<$encoding> before sending. |
716
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
If you want to send a CTCP message you can encode it in the C<$cmd> by |
718
|
|
|
|
|
|
|
appending the CTCP command with a C<"\001">. For example if you want to |
719
|
|
|
|
|
|
|
send a CTCP ACTION you have to give this C<$cmd>: |
720
|
|
|
|
|
|
|
|
721
|
|
|
|
|
|
|
$cl->send_long_message (undef, 0, "PRIVMSG\001ACTION", "#test", "rofls"); |
722
|
|
|
|
|
|
|
|
723
|
|
|
|
|
|
|
C<$encoding> can be undef if you don't need any recoding of C<$msg>. |
724
|
|
|
|
|
|
|
But in case you want to send Unicode it is necessary to determine where |
725
|
|
|
|
|
|
|
to split a message exactly, to not break the encoding. |
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
Please also note that the C<nick_ident> for your own nick is necessary to |
728
|
|
|
|
|
|
|
compute this. To ensure best performance as possible use the |
729
|
|
|
|
|
|
|
C<send_initial_whois> option if you want to use this method. |
730
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
But note that this method might not work 100% correct and you might still get |
732
|
|
|
|
|
|
|
at least partially chopped off lines if you use C<send_long_message> before the |
733
|
|
|
|
|
|
|
C<WHOIS> reply to C<send_initial_whois> arrived. |
734
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
To be on the safest side you might want to wait until that initial C<WHOIS> |
736
|
|
|
|
|
|
|
reply arrived. |
737
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
The return value of this method is the list of the actually sent lines (but |
739
|
|
|
|
|
|
|
without encoding applied). |
740
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
=cut |
742
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
sub send_long_message { |
744
|
0
|
|
|
0
|
1
|
|
my ($self, $encoding, $overhead, $cmd, @params) = @_; |
745
|
0
|
|
|
|
|
|
my $msg = pop @params; |
746
|
|
|
|
|
|
|
|
747
|
0
|
|
|
|
|
|
my $ctcp; |
748
|
0
|
|
|
|
|
|
($cmd, $ctcp) = split /\001/, $cmd; |
749
|
|
|
|
|
|
|
|
750
|
0
|
|
|
|
|
|
my $id = $self->nick_ident ($self->nick); |
751
|
0
|
0
|
|
|
|
|
if ($id eq '') { |
752
|
0
|
|
|
|
|
|
$id = "X" x 60; # just in case the ident is not available... |
753
|
|
|
|
|
|
|
} |
754
|
|
|
|
|
|
|
|
755
|
0
|
|
|
|
|
|
my $init_len = length mk_msg ($id, $cmd, @params, " "); # i know off by 1 |
756
|
|
|
|
|
|
|
|
757
|
0
|
0
|
|
|
|
|
if ($ctcp ne '') { |
758
|
0
|
|
|
|
|
|
$init_len += length ($ctcp) + 3; # CTCP cmd + " " + "\001" x 2 |
759
|
|
|
|
|
|
|
} |
760
|
|
|
|
|
|
|
|
761
|
0
|
|
|
|
|
|
my $max_len = 500; # give 10 bytes extra margin |
762
|
|
|
|
|
|
|
|
763
|
0
|
|
|
|
|
|
my $line_len = $max_len - $init_len; |
764
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
# split up the multiple lines in the message: |
766
|
0
|
|
|
|
|
|
my @lines = split /\n/, $msg; |
767
|
|
|
|
|
|
|
|
768
|
|
|
|
|
|
|
# splitup long lines into multiple ones: |
769
|
0
|
|
|
|
|
|
@lines = |
770
|
|
|
|
|
|
|
map split_unicode_string ($encoding, $_, $line_len), @lines; |
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
# send lines line-by-line: |
773
|
0
|
|
|
|
|
|
for my $line (@lines) { |
774
|
0
|
|
|
|
|
|
my $smsg = encode ($encoding, $line); |
775
|
|
|
|
|
|
|
|
776
|
0
|
0
|
|
|
|
|
if ($ctcp ne '') { |
777
|
0
|
|
|
|
|
|
$smsg = encode_ctcp ([$ctcp, $smsg]) |
778
|
|
|
|
|
|
|
} |
779
|
|
|
|
|
|
|
|
780
|
0
|
|
|
|
|
|
$self->send_srv ($cmd => @params, $smsg); |
781
|
|
|
|
|
|
|
} |
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
@lines |
784
|
0
|
|
|
|
|
|
} |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
=item $cl->enable_ping ($interval, $cb) |
787
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
This method enables a periodical ping to the server with an interval of |
789
|
|
|
|
|
|
|
C<$interval> seconds. If no PONG was received from the server until the next |
790
|
|
|
|
|
|
|
interval the connection will be terminated or the callback in C<$cb> will be called. |
791
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
(C<$cb> will have the connection object as it's first argument.) |
793
|
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
Make sure you call this method after the connection has been established. |
795
|
|
|
|
|
|
|
(eg. in the callback for the C<registered> event). |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
=cut |
798
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
sub enable_ping { |
800
|
0
|
|
|
0
|
1
|
|
my ($self, $int, $cb) = @_; |
801
|
|
|
|
|
|
|
|
802
|
0
|
|
|
|
|
|
$self->{last_pong_recv} = 0; |
803
|
0
|
|
|
|
|
|
$self->{last_ping_sent} = time; |
804
|
|
|
|
|
|
|
|
805
|
0
|
|
|
|
|
|
$self->send_srv (PING => "AnyEvent::IRC"); |
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
$self->{_ping_timer} = |
808
|
|
|
|
|
|
|
AE::timer $int, 0, sub { |
809
|
0
|
0
|
|
0
|
|
|
if ($self->{last_pong_recv} < $self->{last_ping_sent}) { |
810
|
0
|
|
|
|
|
|
delete $self->{_ping_timer}; |
811
|
0
|
0
|
|
|
|
|
if ($cb) { |
812
|
0
|
|
|
|
|
|
$cb->($self); |
813
|
|
|
|
|
|
|
} else { |
814
|
0
|
|
|
|
|
|
$self->disconnect ("Server timeout"); |
815
|
|
|
|
|
|
|
} |
816
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
} else { |
818
|
0
|
|
|
|
|
|
$self->enable_ping ($int, $cb); |
819
|
|
|
|
|
|
|
} |
820
|
0
|
|
|
|
|
|
}; |
821
|
|
|
|
|
|
|
} |
822
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
=item $cl->lower_case ($str) |
824
|
|
|
|
|
|
|
|
825
|
|
|
|
|
|
|
Converts the given string to lowercase according to CASEMAPPING setting given by |
826
|
|
|
|
|
|
|
the IRC server. If none was sent, the default - rfc1459 - will be used. |
827
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
=cut |
829
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
sub lower_case { |
831
|
0
|
|
|
0
|
1
|
|
my($self, $str) = @_; |
832
|
0
|
|
|
|
|
|
local $_ = $str; |
833
|
0
|
|
|
|
|
|
$self->{casemap_func}->(); |
834
|
0
|
|
|
|
|
|
return $_; |
835
|
|
|
|
|
|
|
} |
836
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
=item $cl->eq_str ($str1, $str2) |
838
|
|
|
|
|
|
|
|
839
|
|
|
|
|
|
|
This function compares two strings, whether they are describing the same |
840
|
|
|
|
|
|
|
IRC entity. They are lower cased by the networks case rules and compared then. |
841
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
=cut |
843
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
sub eq_str { |
845
|
0
|
|
|
0
|
1
|
|
my ($self, $a, $b) = @_; |
846
|
0
|
|
|
|
|
|
$self->lower_case ($a) eq $self->lower_case ($b) |
847
|
|
|
|
|
|
|
} |
848
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
=item $cl->isupport () |
850
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
=item $cl->isupport ($key) |
852
|
|
|
|
|
|
|
|
853
|
|
|
|
|
|
|
Provides access to the ISUPPORT variables sent by the IRC server. If $key is |
854
|
|
|
|
|
|
|
given this method will return its value only, otherwise a hashref with all values |
855
|
|
|
|
|
|
|
is returned |
856
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
=cut |
858
|
|
|
|
|
|
|
|
859
|
|
|
|
|
|
|
sub isupport { |
860
|
0
|
|
|
0
|
1
|
|
my($self, $key) = @_; |
861
|
0
|
0
|
|
|
|
|
if (defined ($key)) { |
862
|
0
|
|
|
|
|
|
return $self->{isupport}->{$key}; |
863
|
|
|
|
|
|
|
} else { |
864
|
0
|
|
|
|
|
|
return $self->{isupport}; |
865
|
|
|
|
|
|
|
} |
866
|
|
|
|
|
|
|
} |
867
|
|
|
|
|
|
|
|
868
|
|
|
|
|
|
|
=item $cl->split_nick_mode ($prefixed_nick) |
869
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
This method splits the C<$prefix_nick> (eg. '+elmex') up into the |
871
|
|
|
|
|
|
|
mode of the user and the nickname. |
872
|
|
|
|
|
|
|
|
873
|
|
|
|
|
|
|
This method returns 2 values: the mode map and the nickname. |
874
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
The mode map is a hash reference with the keys being the modes the nick has set |
876
|
|
|
|
|
|
|
and the values being 1. |
877
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
NOTE: If you feed in a prefixed ident ('@elmex!elmex@fofofof.de') you get 3 values |
879
|
|
|
|
|
|
|
out actually: the mode map, the nickname and the ident, otherwise the 3rd value is undef. |
880
|
|
|
|
|
|
|
|
881
|
|
|
|
|
|
|
=cut |
882
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
sub split_nick_mode { |
884
|
0
|
|
|
0
|
1
|
|
my ($self, $prefixed_nick) = @_; |
885
|
|
|
|
|
|
|
|
886
|
0
|
|
|
|
|
|
my $pchrs = $self->{prefix_chars}; |
887
|
|
|
|
|
|
|
|
888
|
0
|
|
|
|
|
|
my %mode_map; |
889
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
my $nick; |
891
|
|
|
|
|
|
|
|
892
|
0
|
0
|
|
|
|
|
if ($prefixed_nick =~ /^([\Q$pchrs\E]+)(.+)$/) { |
893
|
0
|
|
|
|
|
|
my $p = $1; |
894
|
0
|
|
|
|
|
|
$nick = $2; |
895
|
0
|
|
|
|
|
|
for (split //, $p) { $mode_map{$self->map_prefix_to_mode ($_)} = 1 } |
|
0
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
} else { |
897
|
0
|
|
|
|
|
|
$nick = $prefixed_nick; |
898
|
|
|
|
|
|
|
} |
899
|
|
|
|
|
|
|
|
900
|
0
|
|
|
|
|
|
my (@n) = split_prefix ($nick); |
901
|
|
|
|
|
|
|
|
902
|
0
|
0
|
0
|
|
|
|
if (@n > 1 && defined $n[1]) { |
903
|
0
|
|
|
|
|
|
return (\%mode_map, $n[0], $nick); |
904
|
|
|
|
|
|
|
} else { |
905
|
0
|
|
|
|
|
|
return (\%mode_map, $nick, undef); |
906
|
|
|
|
|
|
|
} |
907
|
|
|
|
|
|
|
} |
908
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
=item $cl->map_prefix_to_mode ($prefix) |
910
|
|
|
|
|
|
|
|
911
|
|
|
|
|
|
|
Maps the nick prefix (eg. '@') to the corresponding mode (eg. 'o'). |
912
|
|
|
|
|
|
|
Returns undef if no such prefix exists (on the connected server). |
913
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
=cut |
915
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
sub map_prefix_to_mode { |
917
|
0
|
|
|
0
|
1
|
|
my ($self, $prefix) = @_; |
918
|
0
|
|
|
|
|
|
$self->{prefix2mode}->{$prefix} |
919
|
|
|
|
|
|
|
} |
920
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
=item $cl->map_mode_to_prefix ($mode) |
922
|
|
|
|
|
|
|
|
923
|
|
|
|
|
|
|
Maps the nick mode (eg. 'o') to the corresponding prefix (eg. '@'). |
924
|
|
|
|
|
|
|
Returns undef if no such mode exists (on the connected server). |
925
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
=cut |
927
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
sub map_mode_to_prefix { |
929
|
0
|
|
|
0
|
1
|
|
my ($self, $mode) = @_; |
930
|
0
|
|
|
|
|
|
for (keys %{$self->{prefix2mode}}) { |
|
0
|
|
|
|
|
|
|
931
|
0
|
0
|
|
|
|
|
return $_ if $self->{prefix2mode}->{$_} eq $mode; |
932
|
|
|
|
|
|
|
} |
933
|
|
|
|
|
|
|
|
934
|
0
|
|
|
|
|
|
return undef; |
935
|
|
|
|
|
|
|
} |
936
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
=item $cl->available_nick_modes () |
938
|
|
|
|
|
|
|
|
939
|
|
|
|
|
|
|
Returns a list of possible modes on this IRC server. (eg. 'o' for op). |
940
|
|
|
|
|
|
|
|
941
|
|
|
|
|
|
|
=cut |
942
|
|
|
|
|
|
|
|
943
|
|
|
|
|
|
|
sub available_nick_modes { |
944
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
945
|
0
|
|
|
|
|
|
map { $self->map_prefix_to_mode ($_) } split //, $self->{prefix_chars} |
|
0
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
} |
947
|
|
|
|
|
|
|
|
948
|
|
|
|
|
|
|
=item $cl->is_channel_name ($string) |
949
|
|
|
|
|
|
|
|
950
|
|
|
|
|
|
|
This return true if C<$string> is a channel name. It analyzes the prefix |
951
|
|
|
|
|
|
|
of the string (eg. if it is '#') and returns true if it finds a channel prefix. |
952
|
|
|
|
|
|
|
Those prefixes might be server specific, so ISUPPORT is checked for that too. |
953
|
|
|
|
|
|
|
|
954
|
|
|
|
|
|
|
=cut |
955
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
sub is_channel_name { |
957
|
0
|
|
|
0
|
1
|
|
my ($self, $string) = @_; |
958
|
|
|
|
|
|
|
|
959
|
0
|
|
|
|
|
|
my $cchrs = $self->{channel_chars}; |
960
|
0
|
|
|
|
|
|
$string =~ /^([\Q$cchrs\E]+)(.+)$/; |
961
|
|
|
|
|
|
|
} |
962
|
|
|
|
|
|
|
|
963
|
|
|
|
|
|
|
=item $cl->nick_ident ($nick) |
964
|
|
|
|
|
|
|
|
965
|
|
|
|
|
|
|
This method returns the whole ident of the C<$nick> if the information is available. |
966
|
|
|
|
|
|
|
If the nick's ident hasn't been seen yet, undef is returned. |
967
|
|
|
|
|
|
|
|
968
|
|
|
|
|
|
|
B<NOTE:> If you want to rely on the C<nick_ident> of your own nick you should |
969
|
|
|
|
|
|
|
make sure to enable the C<send_initial_whois> option in the constructor. |
970
|
|
|
|
|
|
|
|
971
|
|
|
|
|
|
|
=cut |
972
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
sub nick_ident { |
974
|
0
|
|
|
0
|
1
|
|
my ($self, $nick) = @_; |
975
|
0
|
|
|
|
|
|
$self->{idents}->{$self->lower_case ($nick)} |
976
|
|
|
|
|
|
|
} |
977
|
|
|
|
|
|
|
|
978
|
|
|
|
|
|
|
=item my $bool = $cl->away_status |
979
|
|
|
|
|
|
|
|
980
|
|
|
|
|
|
|
Returns a true value if you are away or undef if you are not away. |
981
|
|
|
|
|
|
|
|
982
|
|
|
|
|
|
|
=cut |
983
|
|
|
|
|
|
|
|
984
|
0
|
|
|
0
|
1
|
|
sub away_status { $_[0]->{away_status} } |
985
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
=item $cl->ctcp_auto_reply ($ctcp_command, @msg) |
987
|
|
|
|
|
|
|
|
988
|
|
|
|
|
|
|
=item $cl->ctcp_auto_reply ($ctcp_command, $coderef) |
989
|
|
|
|
|
|
|
|
990
|
|
|
|
|
|
|
This method installs an auto-reply for the reception of the C<$ctcp_command> |
991
|
|
|
|
|
|
|
via PRIVMSG, C<@msg> will be used as argument to the C<encode_ctcp> function of |
992
|
|
|
|
|
|
|
the L<AnyEvent::IRC::Util> package. The replies will be sent with the NOTICE |
993
|
|
|
|
|
|
|
IRC command. |
994
|
|
|
|
|
|
|
|
995
|
|
|
|
|
|
|
If C<$coderef> was given and is a code reference, it will called each time a |
996
|
|
|
|
|
|
|
C<$ctcp_command> is received, this is useful for eg. CTCP PING reply |
997
|
|
|
|
|
|
|
generation. The arguments will be the same arguments that the C<ctcp> event |
998
|
|
|
|
|
|
|
callbacks get. (See also C<ctcp> event description above). The return value of |
999
|
|
|
|
|
|
|
the called subroutine should be a list of arguments for C<encode_ctcp>. |
1000
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
Currently you can only configure one auto-reply per C<$ctcp_command>. |
1002
|
|
|
|
|
|
|
|
1003
|
|
|
|
|
|
|
Example: |
1004
|
|
|
|
|
|
|
|
1005
|
|
|
|
|
|
|
$cl->ctcp_auto_reply ('VERSION', ['VERSION', 'ScriptBla:0.1:Perl']); |
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
$cl->ctcp_auto_reply ('PING', sub { |
1008
|
|
|
|
|
|
|
my ($cl, $src, $target, $tag, $msg, $type) = @_; |
1009
|
|
|
|
|
|
|
['PING', $msg] |
1010
|
|
|
|
|
|
|
}); |
1011
|
|
|
|
|
|
|
|
1012
|
|
|
|
|
|
|
=cut |
1013
|
|
|
|
|
|
|
|
1014
|
|
|
|
|
|
|
sub ctcp_auto_reply { |
1015
|
0
|
|
|
0
|
1
|
|
my ($self, $ctcp_command, @msg) = @_; |
1016
|
|
|
|
|
|
|
|
1017
|
0
|
|
|
|
|
|
$self->{ctcp_auto_replies}->{$ctcp_command} = \@msg; |
1018
|
|
|
|
|
|
|
} |
1019
|
|
|
|
|
|
|
|
1020
|
|
|
|
|
|
|
sub _setup_internal_dcc_handlers { |
1021
|
0
|
|
|
0
|
|
|
my ($self) = @_; |
1022
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
$self->reg_cb (ctcp_dcc => sub { |
1024
|
0
|
|
|
0
|
|
|
my ($self, $src, $target, $msg, $type) = @_; |
1025
|
|
|
|
|
|
|
|
1026
|
0
|
0
|
|
|
|
|
if ($self->is_my_nick ($target)) { |
1027
|
0
|
|
|
|
|
|
my ($dcc_type, $arg, $addr, $port) = split /\x20/, $msg; |
1028
|
|
|
|
|
|
|
|
1029
|
0
|
|
|
|
|
|
$dcc_type = lc $dcc_type; |
1030
|
|
|
|
|
|
|
|
1031
|
0
|
0
|
|
|
|
|
if ($dcc_type eq 'send') { |
1032
|
0
|
0
|
|
|
|
|
if ($msg =~ /SEND (.*?) (\d+) (\d+)/) { |
1033
|
0
|
|
|
|
|
|
($arg, $addr, $port) = ($1, $2, $3); |
1034
|
0
|
|
|
|
|
|
$arg =~ s/^\"(.*)\"$/\1/; |
1035
|
|
|
|
|
|
|
} |
1036
|
|
|
|
|
|
|
} |
1037
|
|
|
|
|
|
|
|
1038
|
0
|
|
|
|
|
|
$addr = format_address (pack "N", $addr); |
1039
|
|
|
|
|
|
|
|
1040
|
0
|
|
|
|
|
|
my $id = ++$self->{dcc_id}; |
1041
|
|
|
|
|
|
|
|
1042
|
0
|
|
|
|
|
|
$self->{dcc}->{$id} = { |
1043
|
|
|
|
|
|
|
type => lc ($dcc_type), |
1044
|
|
|
|
|
|
|
dest => $self->lower_case ($src), |
1045
|
|
|
|
|
|
|
ip => $addr, |
1046
|
|
|
|
|
|
|
port => $port, |
1047
|
|
|
|
|
|
|
arg => $arg, |
1048
|
|
|
|
|
|
|
}; |
1049
|
|
|
|
|
|
|
|
1050
|
0
|
|
|
|
|
|
$self->event (dcc_request => $id, $src, $dcc_type, $arg, $addr, $port); |
1051
|
|
|
|
|
|
|
} |
1052
|
0
|
|
|
|
|
|
}); |
1053
|
|
|
|
|
|
|
|
1054
|
|
|
|
|
|
|
$self->reg_cb (dcc_ready => sub { |
1055
|
0
|
|
|
0
|
|
|
my ($self, $id, $dest, $type, $local_ip, $local_port) = @_; |
1056
|
|
|
|
|
|
|
|
1057
|
0
|
|
|
|
|
|
$local_ip = unpack ("N", parse_address ($local_ip)); |
1058
|
|
|
|
|
|
|
|
1059
|
0
|
0
|
|
|
|
|
if ($type eq 'chat') { |
|
|
0
|
|
|
|
|
|
1060
|
0
|
|
|
|
|
|
$self->send_msg ( |
1061
|
|
|
|
|
|
|
PRIVMSG => $dest, |
1062
|
|
|
|
|
|
|
encode_ctcp ([DCC => "CHAT", "CHAT", $local_ip, $local_port])); |
1063
|
|
|
|
|
|
|
|
1064
|
|
|
|
|
|
|
} elsif ($type eq 'send') { |
1065
|
0
|
|
|
|
|
|
$self->send_msg ( |
1066
|
|
|
|
|
|
|
PRIVMSG => $dest, |
1067
|
|
|
|
|
|
|
encode_ctcp ([DCC => "SEND", "NOTHING", $local_ip, $local_port])); |
1068
|
|
|
|
|
|
|
} |
1069
|
0
|
|
|
|
|
|
}); |
1070
|
|
|
|
|
|
|
|
1071
|
|
|
|
|
|
|
$self->reg_cb (dcc_accepted => sub { |
1072
|
0
|
|
|
0
|
|
|
my ($self, $id, $type, $hdl) = @_; |
1073
|
|
|
|
|
|
|
|
1074
|
0
|
0
|
|
|
|
|
if ($type eq 'chat') { |
1075
|
|
|
|
|
|
|
$hdl->on_read (sub { |
1076
|
0
|
|
|
|
|
|
my ($hdl) = @_; |
1077
|
|
|
|
|
|
|
|
1078
|
|
|
|
|
|
|
$hdl->push_read (line => sub { |
1079
|
0
|
|
|
|
|
|
my ($hdl, $line) = @_; |
1080
|
0
|
|
|
|
|
|
$self->event (dcc_chat_msg => $id, $line); |
1081
|
0
|
|
|
|
|
|
}); |
1082
|
0
|
|
|
|
|
|
}); |
1083
|
|
|
|
|
|
|
} |
1084
|
0
|
|
|
|
|
|
}); |
1085
|
|
|
|
|
|
|
|
1086
|
|
|
|
|
|
|
$self->reg_cb (dcc_connected => sub { |
1087
|
0
|
|
|
0
|
|
|
my ($self, $id, $type, $hdl) = @_; |
1088
|
|
|
|
|
|
|
|
1089
|
0
|
0
|
|
|
|
|
if ($type eq 'chat') { |
1090
|
|
|
|
|
|
|
$hdl->on_read (sub { |
1091
|
0
|
|
|
|
|
|
my ($hdl) = @_; |
1092
|
|
|
|
|
|
|
|
1093
|
|
|
|
|
|
|
$hdl->push_read (line => sub { |
1094
|
0
|
|
|
|
|
|
my ($hdl, $line) = @_; |
1095
|
0
|
|
|
|
|
|
$self->event (dcc_chat_msg => $id, $line); |
1096
|
0
|
|
|
|
|
|
}); |
1097
|
0
|
|
|
|
|
|
}); |
1098
|
|
|
|
|
|
|
} |
1099
|
0
|
|
|
|
|
|
}); |
1100
|
|
|
|
|
|
|
} |
1101
|
|
|
|
|
|
|
|
1102
|
|
|
|
|
|
|
=item $cl->dcc_initiate ($dest, $type, $timeout, $local_ip, $local_port) |
1103
|
|
|
|
|
|
|
|
1104
|
|
|
|
|
|
|
This function will initiate a DCC TCP connection to C<$dest> of type C<$type>. |
1105
|
|
|
|
|
|
|
It will setup a listening TCP socket on C<$local_port>, or a random port if |
1106
|
|
|
|
|
|
|
C<$local_port> is undefined. C<$local_ip> is the IP that is being sent to the |
1107
|
|
|
|
|
|
|
receiver of the DCC connection. If it is undef the local socket will be bound |
1108
|
|
|
|
|
|
|
to 0 (or "::" in case of IPv6) and C<$local_ip> will probably be something like |
1109
|
|
|
|
|
|
|
"0.0.0.0". It is always advisable to set C<$local_ip> to a (from the "outside", |
1110
|
|
|
|
|
|
|
what ever that might be) reachable IP Address. |
1111
|
|
|
|
|
|
|
|
1112
|
|
|
|
|
|
|
C<$timeout> is the time in seconds after which the listening socket will be |
1113
|
|
|
|
|
|
|
closed if the receiver didn't connect yet. The default is 300 (5 minutes). |
1114
|
|
|
|
|
|
|
|
1115
|
|
|
|
|
|
|
When the local listening socket has been setup the C<dcc_ready> event is |
1116
|
|
|
|
|
|
|
emitted. When the receiver connects to the socket the C<dcc_accepted> event is |
1117
|
|
|
|
|
|
|
emitted. And whenever a dcc connection is closed the C<dcc_close> event is |
1118
|
|
|
|
|
|
|
emitted. |
1119
|
|
|
|
|
|
|
|
1120
|
|
|
|
|
|
|
For canceling the DCC offer or closing the connection see C<dcc_disconnect> below. |
1121
|
|
|
|
|
|
|
|
1122
|
|
|
|
|
|
|
The return value of this function will be the ID of the initiated DCC connection, |
1123
|
|
|
|
|
|
|
which can be used for functions such as C<dcc_disconnect>, C<send_dcc_chat> or |
1124
|
|
|
|
|
|
|
C<dcc_handle>. |
1125
|
|
|
|
|
|
|
|
1126
|
|
|
|
|
|
|
=cut |
1127
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
sub dcc_initiate { |
1129
|
0
|
|
|
0
|
1
|
|
my ($self, $dest, $type, $timeout, $local_ip, $local_port) = @_; |
1130
|
|
|
|
|
|
|
|
1131
|
0
|
|
|
|
|
|
$dest = $self->lower_case ($dest); |
1132
|
0
|
|
|
|
|
|
$type = lc $type; |
1133
|
|
|
|
|
|
|
|
1134
|
0
|
|
|
|
|
|
my $id = ++$self->{dcc_id}; |
1135
|
0
|
|
|
|
|
|
my $dcc = $self->{dcc}->{$id} = { id => $id, type => $type, dest => $dest }; |
1136
|
|
|
|
|
|
|
|
1137
|
0
|
|
|
|
|
|
weaken $dcc; |
1138
|
0
|
|
|
|
|
|
weaken $self; |
1139
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
$dcc->{timeout} = AnyEvent->timer (after => $timeout || 5 * 60, cb => sub { |
1141
|
0
|
0
|
|
0
|
|
|
$self->dcc_disconnect ($id, "TIMEOUT") if $self; |
1142
|
0
|
|
0
|
|
|
|
}); |
1143
|
|
|
|
|
|
|
|
1144
|
|
|
|
|
|
|
$dcc->{listener} = tcp_server undef, $local_port, sub { |
1145
|
0
|
|
|
0
|
|
|
my ($fh, $h, $p) = @_; |
1146
|
0
|
0
|
0
|
|
|
|
return unless $dcc && $self; |
1147
|
|
|
|
|
|
|
|
1148
|
|
|
|
|
|
|
$dcc->{handle} = AnyEvent::Handle->new ( |
1149
|
|
|
|
|
|
|
fh => $fh, |
1150
|
|
|
|
|
|
|
on_eof => sub { |
1151
|
0
|
|
|
|
|
|
$self->dcc_disconnect ($id, "EOF"); |
1152
|
|
|
|
|
|
|
}, |
1153
|
|
|
|
|
|
|
on_error => sub { |
1154
|
0
|
|
|
|
|
|
$self->dcc_disconnect ($id, "ERROR: $!"); |
1155
|
|
|
|
|
|
|
} |
1156
|
0
|
|
|
|
|
|
); |
1157
|
|
|
|
|
|
|
|
1158
|
0
|
|
|
|
|
|
$self->event (dcc_accepted => $id, $type, $dcc->{handle}); |
1159
|
|
|
|
|
|
|
|
1160
|
0
|
|
|
|
|
|
delete $dcc->{listener}; |
1161
|
0
|
|
|
|
|
|
delete $dcc->{timeout}; |
1162
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
}, sub { |
1164
|
0
|
|
|
0
|
|
|
my ($fh, $host, $port) = @_; |
1165
|
0
|
0
|
0
|
|
|
|
return unless $dcc && $self; |
1166
|
|
|
|
|
|
|
|
1167
|
0
|
0
|
|
|
|
|
$local_ip = $host unless defined $local_ip; |
1168
|
0
|
|
|
|
|
|
$local_port = $port; |
1169
|
|
|
|
|
|
|
|
1170
|
0
|
|
|
|
|
|
$dcc->{local_ip} = $local_ip; |
1171
|
0
|
|
|
|
|
|
$dcc->{local_port} = $local_port; |
1172
|
|
|
|
|
|
|
|
1173
|
0
|
|
|
|
|
|
$self->event (dcc_ready => $id, $dest, $type, $local_ip, $local_port); |
1174
|
0
|
|
|
|
|
|
}; |
1175
|
|
|
|
|
|
|
|
1176
|
0
|
|
|
|
|
|
$id |
1177
|
|
|
|
|
|
|
} |
1178
|
|
|
|
|
|
|
|
1179
|
|
|
|
|
|
|
|
1180
|
|
|
|
|
|
|
=item $cl->dcc_disconnect ($id, $reason) |
1181
|
|
|
|
|
|
|
|
1182
|
|
|
|
|
|
|
In case you want to withdraw a DCC offer sent by C<start_dcc> or close |
1183
|
|
|
|
|
|
|
a DCC connection you call this function. |
1184
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
C<$id> is the DCC connection ID. C<$reason> should be a human readable reason |
1186
|
|
|
|
|
|
|
why you ended the dcc offer, but it's only used for local logging purposes (see |
1187
|
|
|
|
|
|
|
C<dcc_close> event). |
1188
|
|
|
|
|
|
|
|
1189
|
|
|
|
|
|
|
=cut |
1190
|
|
|
|
|
|
|
|
1191
|
|
|
|
|
|
|
sub dcc_disconnect { |
1192
|
0
|
|
|
0
|
1
|
|
my ($self, $id, $reason) = @_; |
1193
|
|
|
|
|
|
|
|
1194
|
0
|
0
|
|
|
|
|
if (my $dcc = delete $self->{dcc}->{$id}) { |
1195
|
0
|
|
|
|
|
|
delete $dcc->{handle}; |
1196
|
0
|
|
|
|
|
|
$self->event (dcc_close => $id, $dcc->{type}, $reason); |
1197
|
|
|
|
|
|
|
} |
1198
|
|
|
|
|
|
|
} |
1199
|
|
|
|
|
|
|
|
1200
|
|
|
|
|
|
|
=item $cl->dcc_accept ($id, $timeout) |
1201
|
|
|
|
|
|
|
|
1202
|
|
|
|
|
|
|
This will accept an incoming DCC request as received by the C<dcc_request> |
1203
|
|
|
|
|
|
|
event. The C<dcc_connected> event will be emitted when we successfully |
1204
|
|
|
|
|
|
|
connected. And the C<dcc_close> event when the connection was disconnected. |
1205
|
|
|
|
|
|
|
|
1206
|
|
|
|
|
|
|
C<$timeout> is the connection try timeout in seconds. The default is 300 (5 minutes). |
1207
|
|
|
|
|
|
|
|
1208
|
|
|
|
|
|
|
=cut |
1209
|
|
|
|
|
|
|
|
1210
|
|
|
|
|
|
|
sub dcc_accept { |
1211
|
0
|
|
|
0
|
1
|
|
my ($self, $id, $timeout) = @_; |
1212
|
|
|
|
|
|
|
|
1213
|
0
|
0
|
|
|
|
|
my $dcc = $self->{dcc}->{$id} |
1214
|
|
|
|
|
|
|
or return; |
1215
|
|
|
|
|
|
|
|
1216
|
0
|
|
|
|
|
|
weaken $dcc; |
1217
|
0
|
|
|
|
|
|
weaken $self; |
1218
|
|
|
|
|
|
|
|
1219
|
|
|
|
|
|
|
$dcc->{timeout} = AnyEvent->timer (after => $timeout || 5 * 60, cb => sub { |
1220
|
0
|
0
|
|
0
|
|
|
$self->dcc_disconnect ($id, "CONNECT TIMEOUT") if $self; |
1221
|
0
|
|
0
|
|
|
|
}); |
1222
|
|
|
|
|
|
|
|
1223
|
|
|
|
|
|
|
$dcc->{connect} = tcp_connect $dcc->{ip}, $dcc->{port}, sub { |
1224
|
0
|
|
|
0
|
|
|
my ($fh) = @_; |
1225
|
0
|
0
|
0
|
|
|
|
return unless $dcc && $self; |
1226
|
|
|
|
|
|
|
|
1227
|
0
|
|
|
|
|
|
delete $dcc->{timeout}; |
1228
|
0
|
|
|
|
|
|
delete $dcc->{connect}; |
1229
|
|
|
|
|
|
|
|
1230
|
0
|
0
|
|
|
|
|
unless ($fh) { |
1231
|
0
|
|
|
|
|
|
$self->dcc_disconnect ($id, "CONNECT ERROR: $!"); |
1232
|
0
|
|
|
|
|
|
return; |
1233
|
|
|
|
|
|
|
} |
1234
|
|
|
|
|
|
|
|
1235
|
|
|
|
|
|
|
$dcc->{handle} = AnyEvent::Handle->new ( |
1236
|
|
|
|
|
|
|
fh => $fh, |
1237
|
|
|
|
|
|
|
on_eof => sub { |
1238
|
0
|
|
|
|
|
|
delete $dcc->{handle}; |
1239
|
0
|
|
|
|
|
|
$self->dcc_disconnect ($id, "EOF"); |
1240
|
|
|
|
|
|
|
}, |
1241
|
|
|
|
|
|
|
on_error => sub { |
1242
|
0
|
|
|
|
|
|
delete $dcc->{handle}; |
1243
|
0
|
|
|
|
|
|
$self->dcc_disconnect ($id, "ERROR: $!"); |
1244
|
|
|
|
|
|
|
} |
1245
|
0
|
|
|
|
|
|
); |
1246
|
|
|
|
|
|
|
|
1247
|
0
|
|
|
|
|
|
$self->event (dcc_connected => $id, $dcc->{type}, $dcc->{handle}); |
1248
|
0
|
|
|
|
|
|
}; |
1249
|
|
|
|
|
|
|
|
1250
|
0
|
|
|
|
|
|
$id |
1251
|
|
|
|
|
|
|
} |
1252
|
|
|
|
|
|
|
|
1253
|
|
|
|
|
|
|
sub dcc_handle { |
1254
|
0
|
|
|
0
|
0
|
|
my ($self, $id) = @_; |
1255
|
|
|
|
|
|
|
|
1256
|
0
|
0
|
|
|
|
|
if (my $dcc = $self->{dcc}->{$id}) { |
1257
|
0
|
|
|
|
|
|
return $dcc->{handle} |
1258
|
|
|
|
|
|
|
} |
1259
|
0
|
|
|
|
|
|
return; |
1260
|
|
|
|
|
|
|
} |
1261
|
|
|
|
|
|
|
|
1262
|
|
|
|
|
|
|
sub send_dcc_chat { |
1263
|
0
|
|
|
0
|
0
|
|
my ($self, $id, $msg) = @_; |
1264
|
|
|
|
|
|
|
|
1265
|
0
|
0
|
|
|
|
|
if (my $dcc = $self->{dcc}->{$id}) { |
1266
|
0
|
0
|
|
|
|
|
if ($dcc->{handle}) { |
1267
|
0
|
|
|
|
|
|
$dcc->{handle}->push_write ("$msg\015\012"); |
1268
|
|
|
|
|
|
|
} |
1269
|
|
|
|
|
|
|
} |
1270
|
|
|
|
|
|
|
} |
1271
|
|
|
|
|
|
|
|
1272
|
|
|
|
|
|
|
################################################################################ |
1273
|
|
|
|
|
|
|
# Private utility functions |
1274
|
|
|
|
|
|
|
################################################################################ |
1275
|
|
|
|
|
|
|
|
1276
|
|
|
|
|
|
|
sub _was_me { |
1277
|
0
|
|
|
0
|
|
|
my ($self, $msg) = @_; |
1278
|
0
|
|
|
|
|
|
$self->lower_case (prefix_nick ($msg)) eq $self->lower_case ($self->nick ()) |
1279
|
|
|
|
|
|
|
} |
1280
|
|
|
|
|
|
|
|
1281
|
|
|
|
|
|
|
sub update_ident { |
1282
|
0
|
|
|
0
|
0
|
|
my ($self, $ident) = @_; |
1283
|
0
|
|
|
|
|
|
my ($n, $u, $h) = split_prefix ($ident); |
1284
|
0
|
|
|
|
|
|
my $old = $self->{idents}->{$self->lower_case ($n)}; |
1285
|
0
|
|
|
|
|
|
$self->{idents}->{$self->lower_case ($n)} = $ident; |
1286
|
0
|
0
|
|
|
|
|
if ($old ne $ident) { |
1287
|
0
|
|
|
|
|
|
$self->event (ident_change => $n, $ident); |
1288
|
|
|
|
|
|
|
} |
1289
|
|
|
|
|
|
|
#d# warn "IDENTS:\n".(join "\n", map { "\t$_\t=>\t$self->{idents}->{$_}" } keys %{$self->{idents}})."\n"; |
1290
|
|
|
|
|
|
|
} |
1291
|
|
|
|
|
|
|
|
1292
|
|
|
|
|
|
|
################################################################################ |
1293
|
|
|
|
|
|
|
# Channel utility functions |
1294
|
|
|
|
|
|
|
################################################################################ |
1295
|
|
|
|
|
|
|
|
1296
|
|
|
|
|
|
|
sub channel_remove { |
1297
|
0
|
|
|
0
|
1
|
|
my ($self, $msg, $chan, $nicks) = @_; |
1298
|
|
|
|
|
|
|
|
1299
|
0
|
|
|
|
|
|
for my $nick (@$nicks) { |
1300
|
0
|
0
|
|
|
|
|
if ($self->lower_case ($nick) eq $self->lower_case ($self->nick ())) { |
1301
|
0
|
|
|
|
|
|
delete $self->{chan_queue}->{$self->lower_case ($chan)}; |
1302
|
0
|
|
|
|
|
|
delete $self->{channel_list}->{$self->lower_case ($chan)}; |
1303
|
0
|
|
|
|
|
|
last; |
1304
|
|
|
|
|
|
|
} else { |
1305
|
0
|
|
|
|
|
|
delete $self->{channel_list}->{$self->lower_case ($chan)}->{$nick}; |
1306
|
|
|
|
|
|
|
} |
1307
|
|
|
|
|
|
|
} |
1308
|
|
|
|
|
|
|
} |
1309
|
|
|
|
|
|
|
|
1310
|
|
|
|
|
|
|
sub channel_add { |
1311
|
0
|
|
|
0
|
1
|
|
my ($self, $msg, $chan, $nicks, $modes) = @_; |
1312
|
|
|
|
|
|
|
|
1313
|
0
|
|
|
|
|
|
my @mods = @$modes; |
1314
|
|
|
|
|
|
|
|
1315
|
0
|
|
|
|
|
|
for my $nick (@$nicks) { |
1316
|
0
|
|
|
|
|
|
my $mode = shift @mods; |
1317
|
|
|
|
|
|
|
|
1318
|
0
|
0
|
|
|
|
|
if ($self->is_my_nick ($nick)) { |
1319
|
0
|
|
|
|
|
|
for (@{$self->{chan_queue}->{$self->lower_case ($chan)}}) { |
|
0
|
|
|
|
|
|
|
1320
|
0
|
|
|
|
|
|
$self->send_msg (@$_); |
1321
|
|
|
|
|
|
|
} |
1322
|
|
|
|
|
|
|
|
1323
|
0
|
|
|
|
|
|
$self->clear_chan_queue ($chan); |
1324
|
|
|
|
|
|
|
} |
1325
|
|
|
|
|
|
|
|
1326
|
0
|
|
0
|
|
|
|
my $ch = $self->{channel_list}->{$self->lower_case ($chan)} ||= { }; |
1327
|
|
|
|
|
|
|
|
1328
|
0
|
0
|
|
|
|
|
if (defined $mode) { |
1329
|
0
|
|
|
|
|
|
$ch->{$nick} = $mode; |
1330
|
0
|
|
|
|
|
|
$self->event (channel_nickmode_update => $chan, $nick); |
1331
|
|
|
|
|
|
|
} else { |
1332
|
0
|
0
|
|
|
|
|
$ch->{$nick} = { } unless defined $ch->{$nick}; |
1333
|
|
|
|
|
|
|
} |
1334
|
|
|
|
|
|
|
} |
1335
|
|
|
|
|
|
|
} |
1336
|
|
|
|
|
|
|
|
1337
|
|
|
|
|
|
|
sub channel_mode_change { |
1338
|
0
|
|
|
0
|
0
|
|
my ($self, $chan, $op, $mode, $nick) = @_; |
1339
|
|
|
|
|
|
|
|
1340
|
0
|
|
|
|
|
|
my $nickmode = $self->nick_modes ($chan, $nick); |
1341
|
0
|
0
|
|
|
|
|
defined $nickmode or return; |
1342
|
|
|
|
|
|
|
|
1343
|
0
|
0
|
|
|
|
|
$op eq '+' |
1344
|
|
|
|
|
|
|
? $nickmode->{$mode} = 1 |
1345
|
|
|
|
|
|
|
: delete $nickmode->{$mode}; |
1346
|
|
|
|
|
|
|
} |
1347
|
|
|
|
|
|
|
|
1348
|
|
|
|
|
|
|
sub _filter_new_nicks_from_channel { |
1349
|
0
|
|
|
0
|
|
|
my ($self, $chan, @nicks) = @_; |
1350
|
0
|
|
|
|
|
|
grep { not exists $self->{channel_list}->{$self->lower_case ($chan)}->{$_} } @nicks; |
|
0
|
|
|
|
|
|
|
1351
|
|
|
|
|
|
|
} |
1352
|
|
|
|
|
|
|
|
1353
|
|
|
|
|
|
|
################################################################################ |
1354
|
|
|
|
|
|
|
# Callbacks |
1355
|
|
|
|
|
|
|
################################################################################ |
1356
|
|
|
|
|
|
|
|
1357
|
|
|
|
|
|
|
sub anymsg_cb { |
1358
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1359
|
|
|
|
|
|
|
|
1360
|
0
|
|
|
|
|
|
my $cmd = lc $msg->{command}; |
1361
|
|
|
|
|
|
|
|
1362
|
0
|
0
|
0
|
|
|
|
if ($cmd =~ /^\d\d\d$/ && not ($cmd >= 400 && $cmd <= 599)) { |
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
1363
|
0
|
|
|
|
|
|
$self->event (statmsg => $msg); |
1364
|
|
|
|
|
|
|
} elsif (($cmd >= 400 && $cmd <= 599) || $cmd eq 'error') { |
1365
|
0
|
|
|
|
|
|
$self->event (error => $msg->{command}, |
1366
|
0
|
0
|
|
|
|
|
(@{$msg->{params}} ? $msg->{params}->[-1] : ''), |
1367
|
|
|
|
|
|
|
$msg); |
1368
|
|
|
|
|
|
|
} |
1369
|
|
|
|
|
|
|
} |
1370
|
|
|
|
|
|
|
|
1371
|
|
|
|
|
|
|
sub privmsg_cb { |
1372
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1373
|
|
|
|
|
|
|
|
1374
|
0
|
|
|
|
|
|
my ($trail, $ctcp) = decode_ctcp ($msg->{params}->[-1]); |
1375
|
|
|
|
|
|
|
|
1376
|
0
|
|
|
|
|
|
for (@$ctcp) { |
1377
|
0
|
|
|
|
|
|
$self->event (ctcp => prefix_nick ($msg), $msg->{params}->[0], $_->[0], $_->[1], $msg->{command}); |
1378
|
0
|
|
|
|
|
|
$self->event ("ctcp_".lc ($_->[0]), prefix_nick ($msg), $msg->{params}->[0], $_->[1], $msg->{command}); |
1379
|
|
|
|
|
|
|
} |
1380
|
|
|
|
|
|
|
|
1381
|
0
|
|
|
|
|
|
$msg->{params}->[-1] = $trail; |
1382
|
|
|
|
|
|
|
|
1383
|
0
|
0
|
|
|
|
|
if ($msg->{params}->[-1] ne '') { |
1384
|
0
|
|
|
|
|
|
my $targ = $msg->{params}->[0]; |
1385
|
0
|
0
|
|
|
|
|
if ($self->is_channel_name ($targ)) { |
1386
|
0
|
|
|
|
|
|
$self->event (publicmsg => $targ, $msg); |
1387
|
|
|
|
|
|
|
|
1388
|
|
|
|
|
|
|
} else { |
1389
|
0
|
|
|
|
|
|
$self->event (privatemsg => $targ, $msg); |
1390
|
|
|
|
|
|
|
} |
1391
|
|
|
|
|
|
|
} |
1392
|
|
|
|
|
|
|
} |
1393
|
|
|
|
|
|
|
|
1394
|
|
|
|
|
|
|
sub welcome_cb { |
1395
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1396
|
|
|
|
|
|
|
|
1397
|
0
|
0
|
|
|
|
|
if ($self->{registered}) { |
1398
|
0
|
|
|
|
|
|
return; |
1399
|
|
|
|
|
|
|
} |
1400
|
|
|
|
|
|
|
|
1401
|
0
|
|
|
|
|
|
$self->{registered} = 1; |
1402
|
0
|
|
|
|
|
|
$self->event ('registered'); |
1403
|
|
|
|
|
|
|
} |
1404
|
|
|
|
|
|
|
|
1405
|
|
|
|
|
|
|
sub registered_cb { |
1406
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1407
|
|
|
|
|
|
|
|
1408
|
0
|
0
|
|
|
|
|
$self->send_srv (WHOIS => $self->nick) |
1409
|
|
|
|
|
|
|
if $self->{send_initial_whois}; |
1410
|
|
|
|
|
|
|
|
1411
|
0
|
|
|
|
|
|
for (@{$self->{con_queue}}) { |
|
0
|
|
|
|
|
|
|
1412
|
0
|
|
|
|
|
|
$self->send_msg (@$_); |
1413
|
|
|
|
|
|
|
} |
1414
|
0
|
|
|
|
|
|
$self->clear_srv_queue (); |
1415
|
|
|
|
|
|
|
} |
1416
|
|
|
|
|
|
|
|
1417
|
|
|
|
|
|
|
sub isupport_cb { |
1418
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1419
|
|
|
|
|
|
|
|
1420
|
0
|
|
|
|
|
|
foreach (@{$msg->{params}}) { |
|
0
|
|
|
|
|
|
|
1421
|
0
|
0
|
|
|
|
|
if (/([A-Z]+)(?:=(.+))?/) { |
1422
|
0
|
0
|
|
|
|
|
$self->{isupport}->{$1} = defined $2 ? $2 : 1; |
1423
|
|
|
|
|
|
|
} |
1424
|
|
|
|
|
|
|
} |
1425
|
|
|
|
|
|
|
|
1426
|
0
|
0
|
|
|
|
|
if (defined (my $casemap = $self->{isupport}->{CASEMAPPING})) { |
1427
|
0
|
0
|
|
|
|
|
if (defined (my $func = $LOWER_CASEMAP{$casemap})) { |
1428
|
0
|
|
|
|
|
|
$self->{casemap_func} = $func; |
1429
|
|
|
|
|
|
|
} else { |
1430
|
0
|
|
|
|
|
|
$self->{casemap_func} = $LOWER_CASEMAP{rfc1459}; |
1431
|
|
|
|
|
|
|
} |
1432
|
|
|
|
|
|
|
} |
1433
|
|
|
|
|
|
|
|
1434
|
0
|
0
|
|
|
|
|
if (defined (my $nick_prefixes = $self->{isupport}->{PREFIX})) { |
1435
|
0
|
0
|
|
|
|
|
if ($nick_prefixes =~ /^\(([^)]+)\)(.+)$/) { |
1436
|
0
|
|
|
|
|
|
my ($modes, $prefixes) = ($1, $2); |
1437
|
0
|
|
|
|
|
|
$self->{prefix_chars} = $prefixes; |
1438
|
0
|
|
|
|
|
|
my @prefixes = split //, $prefixes; |
1439
|
0
|
|
|
|
|
|
$self->{prefix2mode} = { }; |
1440
|
0
|
|
|
|
|
|
for (split //, $modes) { |
1441
|
0
|
|
|
|
|
|
$self->{prefix2mode}->{shift @prefixes} = $_; |
1442
|
|
|
|
|
|
|
} |
1443
|
|
|
|
|
|
|
} |
1444
|
|
|
|
|
|
|
} |
1445
|
|
|
|
|
|
|
|
1446
|
0
|
0
|
0
|
|
|
|
if ($self->{isupport}->{NAMESX} |
1447
|
|
|
|
|
|
|
&& !$self->{protoctl}->{NAMESX}) { |
1448
|
0
|
|
|
|
|
|
$self->send_srv (PROTOCTL => 'NAMESX'); |
1449
|
0
|
|
|
|
|
|
$self->{protoctl}->{NAMESX} = 1; |
1450
|
|
|
|
|
|
|
} |
1451
|
|
|
|
|
|
|
|
1452
|
0
|
0
|
0
|
|
|
|
if ($self->{isupport}->{UHNAMES} |
1453
|
|
|
|
|
|
|
&& !$self->{protoctl}->{UHNAMES}) { |
1454
|
0
|
|
|
|
|
|
$self->send_srv (PROTOCTL => 'UHNAMES'); |
1455
|
0
|
|
|
|
|
|
$self->{protoctl}->{UHNAMES} = 1; |
1456
|
|
|
|
|
|
|
} |
1457
|
|
|
|
|
|
|
|
1458
|
0
|
0
|
|
|
|
|
if (defined (my $chan_prefixes = $self->{isupport}->{CHANTYPES})) { |
1459
|
0
|
|
|
|
|
|
$self->{channel_chars} = $chan_prefixes; |
1460
|
|
|
|
|
|
|
} |
1461
|
|
|
|
|
|
|
} |
1462
|
|
|
|
|
|
|
|
1463
|
|
|
|
|
|
|
sub ping_cb { |
1464
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1465
|
0
|
|
|
|
|
|
$self->send_msg ("PONG", $msg->{params}->[0]); |
1466
|
|
|
|
|
|
|
} |
1467
|
|
|
|
|
|
|
|
1468
|
|
|
|
|
|
|
sub pong_cb { |
1469
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1470
|
0
|
|
|
|
|
|
$self->{last_pong_recv} = time; |
1471
|
|
|
|
|
|
|
} |
1472
|
|
|
|
|
|
|
|
1473
|
|
|
|
|
|
|
sub nick_cb { |
1474
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1475
|
0
|
|
|
|
|
|
my $nick = prefix_nick ($msg); |
1476
|
0
|
|
|
|
|
|
my $newnick = $msg->{params}->[0]; |
1477
|
0
|
|
|
|
|
|
my $wasme = $self->_was_me ($msg); |
1478
|
|
|
|
|
|
|
|
1479
|
0
|
0
|
|
|
|
|
if ($wasme) { $self->{nick} = $newnick } |
|
0
|
|
|
|
|
|
|
1480
|
|
|
|
|
|
|
|
1481
|
0
|
|
|
|
|
|
my @chans; |
1482
|
|
|
|
|
|
|
|
1483
|
0
|
|
|
|
|
|
for my $channame (keys %{$self->{channel_list}}) { |
|
0
|
|
|
|
|
|
|
1484
|
0
|
|
|
|
|
|
my $chan = $self->{channel_list}->{$channame}; |
1485
|
0
|
0
|
|
|
|
|
if (exists $chan->{$nick}) { |
1486
|
0
|
|
|
|
|
|
$chan->{$newnick} = delete $chan->{$nick}; |
1487
|
|
|
|
|
|
|
|
1488
|
0
|
|
|
|
|
|
push @chans, $channame; |
1489
|
|
|
|
|
|
|
} |
1490
|
|
|
|
|
|
|
} |
1491
|
|
|
|
|
|
|
|
1492
|
0
|
|
|
|
|
|
$self->event (nick_change => $nick, $newnick, $wasme); |
1493
|
|
|
|
|
|
|
|
1494
|
0
|
|
|
|
|
|
for (@chans) { |
1495
|
0
|
|
|
|
|
|
$self->event (channel_change => $msg, $_, $nick, $newnick, $wasme); |
1496
|
|
|
|
|
|
|
} |
1497
|
|
|
|
|
|
|
} |
1498
|
|
|
|
|
|
|
|
1499
|
|
|
|
|
|
|
sub namereply_cb { |
1500
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1501
|
0
|
|
|
|
|
|
my @nicks = split / /, $msg->{params}->[-1]; |
1502
|
0
|
|
|
|
|
|
push @{$self->{_tmp_namereply}}, @nicks; |
|
0
|
|
|
|
|
|
|
1503
|
|
|
|
|
|
|
} |
1504
|
|
|
|
|
|
|
|
1505
|
|
|
|
|
|
|
sub endofnames_cb { |
1506
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1507
|
0
|
|
|
|
|
|
my $chan = $msg->{params}->[1]; |
1508
|
0
|
|
|
|
|
|
my @names_result = @{delete $self->{_tmp_namereply}}; |
|
0
|
|
|
|
|
|
|
1509
|
0
|
|
|
|
|
|
my @modes = map { ($self->split_nick_mode ($_))[0] } @names_result; |
|
0
|
|
|
|
|
|
|
1510
|
0
|
|
|
|
|
|
my @nicks = map { ($self->split_nick_mode ($_))[1] } @names_result; |
|
0
|
|
|
|
|
|
|
1511
|
0
|
|
|
|
|
|
my @idents = grep { defined } map { ($self->split_nick_mode ($_))[2] } @names_result; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1512
|
0
|
|
|
|
|
|
my @new_nicks = $self->_filter_new_nicks_from_channel ($chan, @nicks); |
1513
|
|
|
|
|
|
|
|
1514
|
0
|
|
|
|
|
|
$self->channel_add ($msg, $chan, \@nicks, \@modes); |
1515
|
0
|
|
|
|
|
|
$self->update_ident ($_) for @idents; |
1516
|
0
|
0
|
|
|
|
|
$self->event (channel_add => $msg, $chan, @new_nicks) if @new_nicks; |
1517
|
|
|
|
|
|
|
} |
1518
|
|
|
|
|
|
|
|
1519
|
|
|
|
|
|
|
sub whoreply_cb { |
1520
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1521
|
0
|
|
|
|
|
|
my (undef, $channel, $user, $host, $server, $nick) = @{$msg->{params}}; |
|
0
|
|
|
|
|
|
|
1522
|
0
|
|
|
|
|
|
$self->update_ident (join_prefix ($nick, $user, $host)); |
1523
|
|
|
|
|
|
|
} |
1524
|
|
|
|
|
|
|
|
1525
|
|
|
|
|
|
|
sub whoisuser_cb { |
1526
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1527
|
0
|
|
|
|
|
|
my (undef, $nick, $user, $host) = @{$msg->{params}}; |
|
0
|
|
|
|
|
|
|
1528
|
0
|
|
|
|
|
|
$self->update_ident (join_prefix ($nick, $user, $host)); |
1529
|
|
|
|
|
|
|
} |
1530
|
|
|
|
|
|
|
|
1531
|
|
|
|
|
|
|
sub join_cb { |
1532
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1533
|
0
|
|
|
|
|
|
my $chan = $msg->{params}->[0]; |
1534
|
0
|
|
|
|
|
|
my $nick = prefix_nick ($msg); |
1535
|
|
|
|
|
|
|
|
1536
|
0
|
|
|
|
|
|
my @new_nicks = $self->_filter_new_nicks_from_channel ($chan, $nick); |
1537
|
|
|
|
|
|
|
|
1538
|
0
|
|
|
|
|
|
$self->channel_add ($msg, $chan, [$nick], [undef]); |
1539
|
0
|
0
|
|
|
|
|
$self->event (channel_add => $msg, $chan, @new_nicks) if @new_nicks; |
1540
|
0
|
|
|
|
|
|
$self->event (join => $nick, $chan, $self->_was_me ($msg)); |
1541
|
|
|
|
|
|
|
|
1542
|
0
|
0
|
0
|
|
|
|
if ($self->_was_me ($msg) && !$self->isupport ('UHNAMES')) { |
1543
|
0
|
|
|
|
|
|
$self->send_srv (WHO => $chan); |
1544
|
|
|
|
|
|
|
} |
1545
|
|
|
|
|
|
|
} |
1546
|
|
|
|
|
|
|
|
1547
|
|
|
|
|
|
|
sub part_cb { |
1548
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1549
|
0
|
|
|
|
|
|
my $chan = $msg->{params}->[0]; |
1550
|
0
|
|
|
|
|
|
my $nick = prefix_nick ($msg); |
1551
|
|
|
|
|
|
|
|
1552
|
0
|
|
|
|
|
|
$self->event (part => $nick, $chan, $self->_was_me ($msg), $msg->{params}->[1]); |
1553
|
0
|
|
|
|
|
|
$self->channel_remove ($msg, $chan, [$nick]); |
1554
|
0
|
|
|
|
|
|
$self->event (channel_remove => $msg, $chan, $nick); |
1555
|
|
|
|
|
|
|
} |
1556
|
|
|
|
|
|
|
|
1557
|
|
|
|
|
|
|
sub kick_cb { |
1558
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1559
|
0
|
|
|
|
|
|
my $chan = $msg->{params}->[0]; |
1560
|
0
|
|
|
|
|
|
my $kicked_nick = $msg->{params}->[1]; |
1561
|
0
|
|
|
|
|
|
my $kicker_nick = prefix_nick($msg); |
1562
|
|
|
|
|
|
|
|
1563
|
0
|
|
|
|
|
|
$self->event (kick => $kicked_nick, $chan, $self->_was_me ($msg), $msg->{params}->[2], $kicker_nick); |
1564
|
0
|
|
|
|
|
|
$self->channel_remove ($msg, $chan, [$kicked_nick]); |
1565
|
0
|
|
|
|
|
|
$self->event (channel_remove => $msg, $chan, $kicked_nick); |
1566
|
|
|
|
|
|
|
} |
1567
|
|
|
|
|
|
|
|
1568
|
|
|
|
|
|
|
sub quit_cb { |
1569
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1570
|
0
|
|
|
|
|
|
my $nick = prefix_nick ($msg); |
1571
|
|
|
|
|
|
|
|
1572
|
0
|
|
|
|
|
|
$self->event (quit => $nick, $msg->{params}->[0]); |
1573
|
|
|
|
|
|
|
|
1574
|
0
|
|
|
|
|
|
for (keys %{$self->{channel_list}}) { |
|
0
|
|
|
|
|
|
|
1575
|
0
|
0
|
|
|
|
|
if ($self->{channel_list}->{$_}->{$nick}) { |
1576
|
0
|
|
|
|
|
|
$self->channel_remove ($msg, $_, [$nick]); |
1577
|
0
|
|
|
|
|
|
$self->event (channel_remove => $msg, $_, $nick); |
1578
|
|
|
|
|
|
|
} |
1579
|
|
|
|
|
|
|
} |
1580
|
|
|
|
|
|
|
} |
1581
|
|
|
|
|
|
|
|
1582
|
|
|
|
|
|
|
sub mode_cb { |
1583
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1584
|
0
|
|
|
|
|
|
my $changer = prefix_nick ($msg); |
1585
|
0
|
|
|
|
|
|
my ($target, $mode, $dest) = (@{$msg->{params}}); |
|
0
|
|
|
|
|
|
|
1586
|
|
|
|
|
|
|
|
1587
|
0
|
0
|
|
|
|
|
if ($self->is_channel_name ($target)) { |
1588
|
0
|
0
|
0
|
|
|
|
if ($mode =~ /^([+-])(\S+)$/ && defined $dest) { |
1589
|
0
|
|
|
|
|
|
my ($op, $mode) = ($1, $2); |
1590
|
|
|
|
|
|
|
|
1591
|
0
|
0
|
|
|
|
|
if (defined $self->map_mode_to_prefix ($mode)) { |
1592
|
0
|
|
|
|
|
|
$self->channel_mode_change ($target, $op, $mode, $dest); |
1593
|
0
|
|
|
|
|
|
$self->event (channel_nickmode_update => $target, $dest); |
1594
|
|
|
|
|
|
|
} |
1595
|
|
|
|
|
|
|
} |
1596
|
|
|
|
|
|
|
} |
1597
|
|
|
|
|
|
|
} |
1598
|
|
|
|
|
|
|
|
1599
|
|
|
|
|
|
|
sub away_change_cb { |
1600
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1601
|
|
|
|
|
|
|
|
1602
|
0
|
0
|
|
|
|
|
if ($msg->{command} eq '305') { # no longer away |
1603
|
0
|
|
|
|
|
|
delete $self->{away_status}; |
1604
|
|
|
|
|
|
|
} else { # away |
1605
|
0
|
|
|
|
|
|
$self->{away_status} = 1; |
1606
|
|
|
|
|
|
|
} |
1607
|
|
|
|
|
|
|
|
1608
|
0
|
|
|
|
|
|
$self->event (away_status_change => $self->{away_status}); |
1609
|
|
|
|
|
|
|
} |
1610
|
|
|
|
|
|
|
|
1611
|
|
|
|
|
|
|
sub debug_cb { |
1612
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1613
|
0
|
|
|
|
|
|
$self->event (debug_recv => $msg); |
1614
|
|
|
|
|
|
|
} |
1615
|
|
|
|
|
|
|
|
1616
|
|
|
|
|
|
|
sub change_nick_login_cb { |
1617
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1618
|
|
|
|
|
|
|
|
1619
|
0
|
0
|
|
|
|
|
if ($self->registered) { |
1620
|
0
|
|
|
|
|
|
delete $self->{change_nick_cb_guard}; |
1621
|
|
|
|
|
|
|
|
1622
|
|
|
|
|
|
|
} else { |
1623
|
0
|
|
|
|
|
|
my $newnick = $self->{nick_change}->($self->nick); |
1624
|
|
|
|
|
|
|
|
1625
|
0
|
0
|
|
|
|
|
if ($self->lower_case ($newnick) eq $self->lower_case ($self->{nick})) { |
1626
|
0
|
|
|
|
|
|
$self->disconnect ("couldn't change nick to non-conflicting one"); |
1627
|
0
|
|
|
|
|
|
return 0; |
1628
|
|
|
|
|
|
|
} |
1629
|
|
|
|
|
|
|
|
1630
|
0
|
|
|
|
|
|
$self->{nick} = $newnick; |
1631
|
0
|
|
|
|
|
|
$self->send_msg ("NICK", $newnick); |
1632
|
|
|
|
|
|
|
} |
1633
|
|
|
|
|
|
|
} |
1634
|
|
|
|
|
|
|
|
1635
|
|
|
|
|
|
|
sub disconnect_cb { |
1636
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
1637
|
|
|
|
|
|
|
|
1638
|
0
|
|
|
|
|
|
for (keys %{$self->{channel_list}}) { |
|
0
|
|
|
|
|
|
|
1639
|
0
|
|
|
|
|
|
$self->channel_remove (undef, $_, [$self->nick]); |
1640
|
0
|
|
|
|
|
|
$self->event (channel_remove => undef, $_, $self->nick) |
1641
|
|
|
|
|
|
|
} |
1642
|
|
|
|
|
|
|
|
1643
|
0
|
|
|
|
|
|
$self->cleanup; |
1644
|
|
|
|
|
|
|
} |
1645
|
|
|
|
|
|
|
|
1646
|
|
|
|
|
|
|
sub rpl_topic_cb { |
1647
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1648
|
0
|
|
|
|
|
|
my $chan = $msg->{params}->[1]; |
1649
|
0
|
|
|
|
|
|
my $topic = $msg->{params}->[-1]; |
1650
|
|
|
|
|
|
|
|
1651
|
0
|
|
|
|
|
|
$self->event (channel_topic => $chan, $topic); |
1652
|
|
|
|
|
|
|
} |
1653
|
|
|
|
|
|
|
|
1654
|
|
|
|
|
|
|
sub topic_change_cb { |
1655
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1656
|
0
|
|
|
|
|
|
my $who = prefix_nick ($msg); |
1657
|
0
|
|
|
|
|
|
my $chan = $msg->{params}->[0]; |
1658
|
0
|
|
|
|
|
|
my $topic = $msg->{params}->[-1]; |
1659
|
|
|
|
|
|
|
|
1660
|
0
|
|
|
|
|
|
$self->event (channel_topic => $chan, $topic, $who); |
1661
|
|
|
|
|
|
|
} |
1662
|
|
|
|
|
|
|
|
1663
|
|
|
|
|
|
|
sub update_ident_cb { |
1664
|
0
|
|
|
0
|
0
|
|
my ($self, $msg) = @_; |
1665
|
|
|
|
|
|
|
|
1666
|
0
|
0
|
|
|
|
|
if (is_nick_prefix ($msg->{prefix})) { |
1667
|
0
|
|
|
|
|
|
$self->update_ident ($msg->{prefix}); |
1668
|
|
|
|
|
|
|
} |
1669
|
|
|
|
|
|
|
} |
1670
|
|
|
|
|
|
|
|
1671
|
|
|
|
|
|
|
sub update_ident_nick_change_cb { |
1672
|
0
|
|
|
0
|
0
|
|
my ($self, $old, $new) = @_; |
1673
|
|
|
|
|
|
|
|
1674
|
0
|
|
|
|
|
|
my $oldid = $self->nick_ident ($old); |
1675
|
0
|
0
|
|
|
|
|
return unless defined $oldid; |
1676
|
|
|
|
|
|
|
|
1677
|
0
|
|
|
|
|
|
my ($n, $u, $h) = split_prefix ($oldid); |
1678
|
|
|
|
|
|
|
|
1679
|
0
|
|
|
|
|
|
$self->update_ident (join_prefix ($new, $u, $h)); |
1680
|
|
|
|
|
|
|
} |
1681
|
|
|
|
|
|
|
|
1682
|
|
|
|
|
|
|
sub ctcp_auto_reply_cb { |
1683
|
0
|
|
|
0
|
0
|
|
my ($self, $src, $targ, $tag, $msg, $type) = @_; |
1684
|
|
|
|
|
|
|
|
1685
|
0
|
0
|
|
|
|
|
return if $type ne 'PRIVMSG'; |
1686
|
|
|
|
|
|
|
|
1687
|
0
|
0
|
|
|
|
|
my $ctcprepl = $self->{ctcp_auto_replies}->{$tag} |
1688
|
|
|
|
|
|
|
or return; |
1689
|
|
|
|
|
|
|
|
1690
|
0
|
0
|
|
|
|
|
if (ref ($ctcprepl->[0]) eq 'CODE') { |
1691
|
0
|
|
|
|
|
|
$ctcprepl = [$ctcprepl->[0]->($self, $src, $targ, $tag, $msg, $type)] |
1692
|
|
|
|
|
|
|
} |
1693
|
|
|
|
|
|
|
|
1694
|
0
|
|
|
|
|
|
$self->send_msg (NOTICE => $src, encode_ctcp (@$ctcprepl)); |
1695
|
|
|
|
|
|
|
} |
1696
|
|
|
|
|
|
|
|
1697
|
|
|
|
|
|
|
=back |
1698
|
|
|
|
|
|
|
|
1699
|
|
|
|
|
|
|
=head1 EXAMPLES |
1700
|
|
|
|
|
|
|
|
1701
|
|
|
|
|
|
|
See samples/anyeventirccl and other samples in samples/ for some examples on how to use AnyEvent::IRC::Client. |
1702
|
|
|
|
|
|
|
|
1703
|
|
|
|
|
|
|
=head1 AUTHOR |
1704
|
|
|
|
|
|
|
|
1705
|
|
|
|
|
|
|
Robin Redeker, C<< <elmex@ta-sa.org> >> |
1706
|
|
|
|
|
|
|
|
1707
|
|
|
|
|
|
|
=head1 SEE ALSO |
1708
|
|
|
|
|
|
|
|
1709
|
|
|
|
|
|
|
L<AnyEvent::IRC::Connection> |
1710
|
|
|
|
|
|
|
|
1711
|
|
|
|
|
|
|
RFC 1459 - Internet Relay Chat: Client Protocol |
1712
|
|
|
|
|
|
|
|
1713
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
1714
|
|
|
|
|
|
|
|
1715
|
|
|
|
|
|
|
Copyright 2006-2009 Robin Redeker, all rights reserved. |
1716
|
|
|
|
|
|
|
|
1717
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
1718
|
|
|
|
|
|
|
under the same terms as Perl itself. |
1719
|
|
|
|
|
|
|
|
1720
|
|
|
|
|
|
|
=cut |
1721
|
|
|
|
|
|
|
|
1722
|
|
|
|
|
|
|
1; |