line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package POE::Component::IRC::Plugin::MultiProxy::State; |
2
|
|
|
|
|
|
|
BEGIN { |
3
|
1
|
|
|
1
|
|
1546
|
$POE::Component::IRC::Plugin::MultiProxy::State::AUTHORITY = 'cpan:HINRIK'; |
4
|
|
|
|
|
|
|
} |
5
|
|
|
|
|
|
|
BEGIN { |
6
|
1
|
|
|
1
|
|
16
|
$POE::Component::IRC::Plugin::MultiProxy::State::VERSION = '0.01'; |
7
|
|
|
|
|
|
|
} |
8
|
|
|
|
|
|
|
|
9
|
1
|
|
|
1
|
|
9
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
52
|
|
10
|
1
|
|
|
1
|
|
5
|
use warnings FATAL => 'all'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
39
|
|
11
|
1
|
|
|
1
|
|
5
|
use POE::Filter::IRCD; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
29
|
|
12
|
1
|
|
|
1
|
|
9
|
use POE::Component::IRC::Common qw(parse_user u_irc); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
64
|
|
13
|
1
|
|
|
1
|
|
5
|
use POE::Component::IRC::Plugin qw(:ALL); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
3985
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
sub new { |
16
|
0
|
|
|
0
|
1
|
|
my ($package) = @_; |
17
|
0
|
|
|
|
|
|
return bless { }, $package; |
18
|
|
|
|
|
|
|
} |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
sub PCI_register { |
21
|
0
|
|
|
0
|
0
|
|
my ($self, $irc) = @_; |
22
|
0
|
|
|
|
|
|
$self->{irc} = $irc; |
23
|
0
|
|
|
|
|
|
$self->{filter} = POE::Filter::IRCD->new(); |
24
|
0
|
|
|
|
|
|
$irc->plugin_register($self, SERVER => qw(001 away_sync_start away_sync_end join chan_mode chan_sync chan_sync_invex chan_sync_excepts nick_sync raw)); |
25
|
0
|
|
|
|
|
|
return 1; |
26
|
|
|
|
|
|
|
} |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
sub PCI_unregister { |
29
|
0
|
|
|
0
|
0
|
|
my ($self, $irc) = @_; |
30
|
0
|
|
|
|
|
|
return 1; |
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
sub S_001 { |
34
|
0
|
|
|
0
|
0
|
|
my ($self, $irc) = splice @_, 0, 2; |
35
|
0
|
|
|
|
|
|
$self->{syncing_away} = { }; |
36
|
0
|
|
|
|
|
|
$self->{syncing_op} = { }; |
37
|
0
|
|
|
|
|
|
$self->{syncing_join} = { }; |
38
|
0
|
|
|
|
|
|
$self->{op_queue} = { }; |
39
|
0
|
|
|
|
|
|
$self->{join_queue} = { }; |
40
|
|
|
|
|
|
|
|
41
|
0
|
|
|
|
|
|
return PCI_EAT_NONE; |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub S_join { |
45
|
0
|
|
|
0
|
0
|
|
my ($self, $irc) = splice @_, 0, 2; |
46
|
0
|
|
|
|
|
|
my $mapping = $irc->isupport('CASEMAPPING'); |
47
|
0
|
|
|
|
|
|
my $unick = u_irc((parse_user(${ $_[0] }))[0], $mapping); |
|
0
|
|
|
|
|
|
|
48
|
0
|
|
|
|
|
|
my $uchan = u_irc(${ $_[1] }, $mapping); |
|
0
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
|
50
|
0
|
0
|
|
|
|
|
if ($unick eq u_irc($irc->nick_name(), $mapping)) { |
51
|
0
|
|
|
|
|
|
$self->{syncing_join}{$uchan} = 1; |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
else { |
54
|
0
|
|
|
|
|
|
$self->{syncing_join}{$unick}++; |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
|
57
|
0
|
|
|
|
|
|
return PCI_EAT_NONE; |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
sub S_away_sync_start { |
61
|
0
|
|
|
0
|
0
|
|
my ($self, $irc) = splice @_, 0, 2; |
62
|
0
|
|
|
|
|
|
my $mapping = $irc->isupport('CASEMAPPING'); |
63
|
0
|
|
|
|
|
|
my $uchan = u_irc(${ $_[0] }, $mapping); |
|
0
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
|
65
|
0
|
|
|
|
|
|
$self->{syncing_away}{$uchan} = 1; |
66
|
0
|
|
|
|
|
|
return PCI_EAT_NONE; |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub S_away_sync_end { |
70
|
0
|
|
|
0
|
0
|
|
my ($self, $irc) = splice @_, 0, 2; |
71
|
0
|
|
|
|
|
|
my $mapping = $irc->isupport('CASEMAPPING'); |
72
|
0
|
|
|
|
|
|
my $uchan = u_irc(${ $_[0] }, $mapping); |
|
0
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
|
74
|
0
|
|
|
|
|
|
delete $self->{syncing_away}{$uchan}; |
75
|
0
|
|
|
|
|
|
return PCI_EAT_NONE; |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
sub S_chan_mode { |
79
|
0
|
|
|
0
|
0
|
|
my ($self, $irc) = splice @_, 0, 2; |
80
|
0
|
|
|
|
|
|
my $mapping = $irc->isupport('CASEMAPPING'); |
81
|
0
|
|
|
|
|
|
my $uchan = u_irc(${ $_[1] }, $mapping); |
|
0
|
|
|
|
|
|
|
82
|
0
|
|
|
|
|
|
my $mode = ${ $_[2] }; |
|
0
|
|
|
|
|
|
|
83
|
0
|
|
|
|
|
|
my $unick = u_irc($irc->nick_name(), $mapping); |
84
|
|
|
|
|
|
|
|
85
|
0
|
0
|
|
|
|
|
if ($mode =~ /\+o/) { |
86
|
0
|
|
|
|
|
|
my @operands = split / /, ${ $_[3] }; |
|
0
|
|
|
|
|
|
|
87
|
0
|
0
|
|
|
|
|
if (grep { u_irc($_, $mapping) eq $unick } @operands) { |
|
0
|
|
|
|
|
|
|
88
|
0
|
|
|
|
|
|
$self->{syncing_op}{$uchan}{invex} = 1; |
89
|
0
|
|
|
|
|
|
$self->{syncing_op}{$uchan}{excepts} = 1; |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
0
|
|
|
|
|
|
return PCI_EAT_NONE; |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
sub S_chan_sync { |
97
|
0
|
|
|
0
|
0
|
|
my ($self, $irc) = splice @_, 0, 2; |
98
|
0
|
|
|
|
|
|
my $mapping = $irc->isupport('CASEMAPPING'); |
99
|
0
|
|
|
|
|
|
my $uchan = u_irc(${ $_[0] }, $mapping); |
|
0
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
101
|
0
|
|
|
|
|
|
delete $self->{syncing_join}{$uchan}; |
102
|
0
|
|
|
|
|
|
$self->_flush_queue($self->{join_queue}{$uchan}); |
103
|
0
|
|
|
|
|
|
return PCI_EAT_NONE; |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
sub S_chan_sync_invex { |
107
|
0
|
|
|
0
|
0
|
|
my ($self, $irc) = splice @_, 0, 2; |
108
|
0
|
|
|
|
|
|
my $mapping = $irc->isupport('CASEMAPPING'); |
109
|
0
|
|
|
|
|
|
my $uchan = u_irc(${ $_[0] }, $mapping); |
|
0
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
|
111
|
0
|
|
|
|
|
|
$self->_flush_queue($self->{op_queue}{$uchan}{invex}); |
112
|
0
|
|
|
|
|
|
delete $self->{syncing_op}{$uchan}{invex}; |
113
|
0
|
0
|
|
|
|
|
delete $self->{syncing_op}{$uchan} if !keys %{ $self->{syncing_op}{$uchan} }; |
|
0
|
|
|
|
|
|
|
114
|
0
|
|
|
|
|
|
return PCI_EAT_NONE; |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
sub S_chan_sync_excepts { |
118
|
0
|
|
|
0
|
0
|
|
my ($self, $irc) = splice @_, 0, 2; |
119
|
0
|
|
|
|
|
|
my $mapping = $irc->isupport('CASEMAPPING'); |
120
|
0
|
|
|
|
|
|
my $uchan = u_irc(${ $_[0] }, $mapping); |
|
0
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
|
122
|
0
|
|
|
|
|
|
$self->_flush_queue($self->{op_queue}{$uchan}{excepts}); |
123
|
0
|
|
|
|
|
|
delete $self->{syncing_op}{$uchan}{excepts}; |
124
|
0
|
0
|
|
|
|
|
delete $self->{syncing_op}{$uchan} if !keys %{ $self->{syncing_op}{$uchan} }; |
|
0
|
|
|
|
|
|
|
125
|
0
|
|
|
|
|
|
return PCI_EAT_NONE; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
sub S_nick_sync { |
129
|
0
|
|
|
0
|
0
|
|
my ($self, $irc) = splice @_, 0, 2; |
130
|
0
|
|
|
|
|
|
my $mapping = $irc->isupport('CASEMAPPING'); |
131
|
0
|
|
|
|
|
|
my $unick = u_irc(${ $_[0] }, $mapping); |
|
0
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
|
133
|
0
|
|
|
|
|
|
$self->{syncing_join}{$unick}--; |
134
|
0
|
0
|
|
|
|
|
delete $self->{syncing_join}{$unick} if $self->{syncing_join}{$unick} == 0; |
135
|
0
|
|
|
|
|
|
$self->_flush_queue($self->{join_queue}{$unick}); |
136
|
0
|
|
|
|
|
|
return PCI_EAT_NONE; |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub S_raw { |
140
|
0
|
|
|
0
|
0
|
|
my ($self, $irc) = splice @_, 0, 2; |
141
|
0
|
|
|
|
|
|
my $mapping = $irc->isupport('CASEMAPPING'); |
142
|
0
|
|
|
|
|
|
my $raw_line = ${ $_[0] }; |
|
0
|
|
|
|
|
|
|
143
|
0
|
|
|
|
|
|
my $input = $self->{filter}->get( [ $raw_line ] )->[0]; |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
# syncing_join me |
146
|
0
|
0
|
|
|
|
|
if ($input->{command} =~ /315|324|329|352|367|368/) { |
147
|
0
|
0
|
|
|
|
|
if ($input->{params}[1] =~ /[^#&+!]/) { |
148
|
0
|
0
|
|
|
|
|
if ($self->{syncing_join}{u_irc($input->{params}[1], $mapping)}) { |
149
|
0
|
|
|
|
|
|
return PCI_EAT_PLUGIN; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
# syncing_join other |
155
|
0
|
0
|
|
|
|
|
if ($input->{command} eq '352') { |
156
|
0
|
0
|
|
|
|
|
if ($self->{syncing_join}{u_irc($input->{params}[5], $mapping)}) { |
157
|
0
|
|
|
|
|
|
return PCI_EAT_PLUGIN; |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# syncing_away |
162
|
0
|
0
|
|
|
|
|
if ($input->{command} =~ /315|352/) { |
163
|
0
|
0
|
|
|
|
|
if ($input->{params}[1] =~ /[^#&+!]/) { |
164
|
0
|
0
|
|
|
|
|
if ($self->{syncing_away}{u_irc($input->{params}[1], $mapping)}) { |
165
|
0
|
|
|
|
|
|
return PCI_EAT_PLUGIN; |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
# syncing_op invex |
171
|
0
|
0
|
|
|
|
|
if ($input->{command} =~ /346|347/) { |
172
|
0
|
0
|
|
|
|
|
if ($self->{syncing_op}{u_irc($input->{params}[1], $mapping)}{invex}) { |
173
|
0
|
|
|
|
|
|
return PCI_EAT_PLUGIN; |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# syncing_op excepts |
178
|
0
|
0
|
|
|
|
|
if ($input->{command} =~ /348|349/) { |
179
|
0
|
0
|
|
|
|
|
if ($self->{syncing_op}{u_irc($input->{params}[1], $mapping)}{excepts}) { |
180
|
0
|
|
|
|
|
|
return PCI_EAT_PLUGIN; |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
|
184
|
0
|
|
|
|
|
|
return PCI_EAT_NONE; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
sub _flush_queue { |
188
|
0
|
|
|
0
|
|
|
my ($self, $queue) = @_; |
189
|
0
|
0
|
|
|
|
|
return if !$queue; |
190
|
|
|
|
|
|
|
|
191
|
0
|
|
|
|
|
|
while (my $request = shift @$queue) { |
192
|
0
|
|
|
|
|
|
my ($callback, $reply, $real_what, $args) = @{ $request }; |
|
0
|
|
|
|
|
|
|
193
|
0
|
|
|
|
|
|
$callback->($_) for $self->$reply($real_what, @{ $args }); |
|
0
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
|
196
|
0
|
|
|
|
|
|
return; |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
sub is_syncing { |
200
|
0
|
|
|
0
|
1
|
|
my ($self, $what) = @_; |
201
|
0
|
|
|
|
|
|
my $mapping = $self->{irc}->isupport('CASEMAPPING'); |
202
|
0
|
|
|
|
|
|
my $uwhat = u_irc($what, $mapping); |
203
|
|
|
|
|
|
|
|
204
|
0
|
0
|
|
|
|
|
return 1 if $self->{syncing_join}{$uwhat}; |
205
|
0
|
|
|
|
|
|
return; |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
sub enqueue { |
209
|
0
|
|
|
0
|
1
|
|
my ($self, $callback, $reply, $what, @args) = @_; |
210
|
0
|
|
|
|
|
|
my $mapping = $self->{irc}->isupport('CASEMAPPING'); |
211
|
0
|
|
|
|
|
|
my $uwhat = u_irc($what, $mapping); |
212
|
|
|
|
|
|
|
|
213
|
0
|
0
|
|
|
|
|
if ($reply eq 'mode_reply') { |
|
|
0
|
|
|
|
|
|
214
|
0
|
0
|
0
|
|
|
|
if (grep { defined && $_ eq 'e' } @args && $self->{syncing_op}{$uwhat}{excepts}) { |
|
0
|
0
|
0
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
215
|
0
|
|
|
|
|
|
push @{ $self->{op_queue}{$uwhat}{excepts} }, [$callback, $reply, $what, \@args]; |
|
0
|
|
|
|
|
|
|
216
|
0
|
|
|
|
|
|
return; |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
elsif (grep { defined && $_ eq 'I' } @args && $self->{syncing_op}{$uwhat}{invex}) { |
219
|
0
|
|
|
|
|
|
push @{ $self->{op_queue}{$uwhat}{invex} }, [$callback, $reply, $what, \@args]; |
|
0
|
|
|
|
|
|
|
220
|
0
|
|
|
|
|
|
return; |
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
elsif ($self->{syncing_join}{$uwhat}) { |
223
|
0
|
|
|
|
|
|
push @{ $self->{join_queue}{$uwhat} }, [$callback, $reply, $what, \@args]; |
|
0
|
|
|
|
|
|
|
224
|
0
|
|
|
|
|
|
return; |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
elsif ($reply =~ /(?:who|names|topic)_reply/) { |
228
|
0
|
0
|
|
|
|
|
if ($self->{syncing_join}{$uwhat}) { |
229
|
0
|
|
|
|
|
|
push @{ $self->{join_queue}{$uwhat} }, [$callback, $reply, $what, \@args]; |
|
0
|
|
|
|
|
|
|
230
|
0
|
|
|
|
|
|
return; |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
|
234
|
0
|
|
|
|
|
|
my @lines = $self->$reply($what, @args); |
235
|
0
|
|
|
|
|
|
$callback->(@lines); |
236
|
0
|
|
|
|
|
|
return; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
# handles /^TOPIC (\S+)$/ where $1 is a channel that we're on |
240
|
|
|
|
|
|
|
sub topic_reply { |
241
|
0
|
|
|
0
|
1
|
|
my ($self, $chan) = @_; |
242
|
0
|
|
|
|
|
|
my $irc = $self->{irc}; |
243
|
0
|
|
|
|
|
|
my $me = $irc->nick_name(); |
244
|
0
|
|
|
|
|
|
my $server = $irc->server_name(); |
245
|
0
|
|
|
|
|
|
my @results; |
246
|
|
|
|
|
|
|
|
247
|
0
|
0
|
|
|
|
|
if (!keys %{ $irc->channel_topic($chan) }) { |
|
0
|
|
|
|
|
|
|
248
|
0
|
|
|
|
|
|
push @results, ":$server 331 $me $chan :No topic is set"; |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
else { |
251
|
0
|
|
|
|
|
|
my $topic_info = $irc->channel_topic($chan); |
252
|
0
|
|
|
|
|
|
push @results, ":$server 332 $me $chan :" . $topic_info->{Value}; |
253
|
0
|
|
|
|
|
|
push @results, ":$server 333 $me $chan " . join(' ', @{$topic_info}{qw(SetBy SetAt)}); |
|
0
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
|
256
|
0
|
|
|
|
|
|
return @results; |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
# handles /^NAMES (\S+)$/ where $1 is a channel that we're on |
261
|
|
|
|
|
|
|
sub names_reply { |
262
|
0
|
|
|
0
|
1
|
|
my ($self, $chan) = @_; |
263
|
0
|
|
|
|
|
|
my $irc = $self->{irc}; |
264
|
0
|
|
|
|
|
|
my $me = $irc->nick_name(); |
265
|
0
|
|
|
|
|
|
my $server = $irc->server_name(); |
266
|
0
|
|
|
|
|
|
my $chan_type = '='; |
267
|
0
|
0
|
|
|
|
|
$chan_type = '@' if $irc->is_channel_mode_set($chan, 's'); |
268
|
0
|
0
|
|
|
|
|
$chan_type = '*' if $irc->is_channel_mode_set($chan, 'p'); |
269
|
|
|
|
|
|
|
|
270
|
0
|
|
|
|
|
|
my @nicks = sort map { |
271
|
0
|
|
|
|
|
|
my $nick = $_; |
272
|
0
|
|
|
|
|
|
my $prefix = ''; |
273
|
0
|
0
|
|
|
|
|
$prefix = '+' if $irc->has_channel_voice($chan, $nick); |
274
|
0
|
0
|
|
|
|
|
$prefix = '%' if $irc->is_channel_halfop($chan, $nick); |
275
|
0
|
0
|
|
|
|
|
$prefix = '@' if $irc->is_channel_operator($chan, $nick); |
276
|
0
|
|
|
|
|
|
$prefix . $nick; |
277
|
|
|
|
|
|
|
} $irc->channel_list($chan); |
278
|
|
|
|
|
|
|
|
279
|
0
|
|
|
|
|
|
my $length = length($server) + length($chan) + length($me) + 11; |
280
|
0
|
|
|
|
|
|
my @results; |
281
|
0
|
|
|
|
|
|
my $nick_list = shift @nicks; |
282
|
|
|
|
|
|
|
|
283
|
0
|
|
|
|
|
|
for my $nick (@nicks) { |
284
|
0
|
0
|
|
|
|
|
if (length("$nick_list $nick") + $length <= 510) { |
285
|
0
|
|
|
|
|
|
$nick_list .= " $nick"; |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
else { |
288
|
0
|
|
|
|
|
|
push @results, ":$server 353 $me $chan_type $chan :$nick_list"; |
289
|
0
|
|
|
|
|
|
$nick_list = $nick; |
290
|
|
|
|
|
|
|
} |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
0
|
|
|
|
|
|
push @results, ":$server 353 $me $chan_type $chan :$nick_list"; |
294
|
0
|
|
|
|
|
|
push @results, ":$server 366 $me $chan :End of NAMES list"; |
295
|
|
|
|
|
|
|
|
296
|
0
|
|
|
|
|
|
return @results; |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
# handles /^WHO (\S+)$/ where $1 is a channel we're on or a nickname, NOT a mask |
300
|
|
|
|
|
|
|
sub who_reply { |
301
|
0
|
|
|
0
|
1
|
|
my ($self, $who) = @_; |
302
|
0
|
|
|
|
|
|
my $irc = $self->{irc}; |
303
|
0
|
|
|
|
|
|
my $me = $irc->nick_name(); |
304
|
0
|
|
|
|
|
|
my $server = $irc->server_name(); |
305
|
0
|
0
|
|
|
|
|
my $prefix = $who =~ /^[#&+!]/ ? $who : '*'; |
306
|
|
|
|
|
|
|
|
307
|
0
|
|
|
|
|
|
my @members; |
308
|
0
|
0
|
|
|
|
|
@members = $irc->channel_list($who) if $irc->is_channel_member($who, $me); |
309
|
0
|
0
|
|
|
|
|
@members = ($who) if $irc->_nick_exists($who); |
310
|
|
|
|
|
|
|
|
311
|
0
|
|
|
|
|
|
my @results; |
312
|
0
|
|
|
|
|
|
for my $member (@members) { |
313
|
0
|
|
|
|
|
|
my ($nick, $user, $host) = parse_user($irc->nick_long_form($member)); |
314
|
|
|
|
|
|
|
|
315
|
0
|
0
|
|
|
|
|
my $status = $irc->is_away($nick) ? 'G' : 'H'; |
316
|
0
|
0
|
|
|
|
|
$status .= '*' if $irc->is_operator($nick); |
317
|
0
|
0
|
|
|
|
|
$status .= '@' if $irc->is_channel_operator($who, $nick); |
318
|
0
|
0
|
|
|
|
|
$status .= '%' if $irc->is_channel_halfop($who, $nick); |
319
|
0
|
0
|
0
|
|
|
|
$status .= '+' if $irc->has_channel_voice($who, $nick) && !$irc->is_channel_operator($who, $nick); |
320
|
|
|
|
|
|
|
|
321
|
0
|
|
|
|
|
|
my $info = $irc->nick_info($nick); |
322
|
0
|
0
|
|
|
|
|
my $real = defined $info->{Real} ? $info->{Real} : ''; |
323
|
0
|
0
|
|
|
|
|
my $user_server = defined $info->{Server} ? $info->{Server} : '*'; |
324
|
0
|
0
|
|
|
|
|
my $hops = defined $info->{Hops} ? $info->{Hops} : '*'; |
325
|
0
|
|
|
|
|
|
push @results, ":$server 352 $me $prefix $user $host $user_server $nick $status :$hops $real"; |
326
|
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
|
328
|
0
|
|
|
|
|
|
push @results, ":$server 315 $me $who :End of WHO list"; |
329
|
0
|
|
|
|
|
|
return @results; |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
# handles /^MODE #chan( [Ieb])?$/ and /^MODE our_nick$/ |
333
|
|
|
|
|
|
|
sub mode_reply { |
334
|
0
|
|
|
0
|
0
|
|
my ($self, $chan, $type) = @_; |
335
|
0
|
|
|
|
|
|
my $irc = $self->{irc}; |
336
|
0
|
|
|
|
|
|
my $mapping = $irc->isupport('CASEMAPPING'); |
337
|
0
|
|
|
|
|
|
my $me = $irc->nick_name(); |
338
|
0
|
|
|
|
|
|
my $server = $irc->server_name(); |
339
|
0
|
|
|
|
|
|
my @results; |
340
|
|
|
|
|
|
|
|
341
|
0
|
0
|
|
|
|
|
if (u_irc($chan, $mapping) eq u_irc($me, $mapping)) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
342
|
0
|
|
|
|
|
|
return ":$server 221 $me :+" . $irc->umode(); |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
elsif (!defined $type) { |
345
|
0
|
|
|
|
|
|
my $modes = $irc->channel_modes($chan); |
346
|
|
|
|
|
|
|
|
347
|
0
|
|
|
|
|
|
my $mode_string = ''; |
348
|
0
|
|
|
|
|
|
while (my ($mode, $arg) = each %{ $modes }) { |
|
0
|
|
|
|
|
|
|
349
|
0
|
0
|
|
|
|
|
if (!length $arg) { |
350
|
0
|
|
|
|
|
|
$mode_string .= $mode; |
351
|
0
|
|
|
|
|
|
delete $modes->{$mode}; |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
|
355
|
0
|
|
|
|
|
|
my @args; |
356
|
0
|
|
|
|
|
|
while (my ($mode, $arg) = each %{ $modes }) { |
|
0
|
|
|
|
|
|
|
357
|
0
|
|
|
|
|
|
$mode_string .= $mode; |
358
|
0
|
|
|
|
|
|
push @args, $arg; |
359
|
|
|
|
|
|
|
} |
360
|
|
|
|
|
|
|
|
361
|
0
|
0
|
|
|
|
|
$mode_string .= ' ' . join ' ', @args if @args; |
362
|
0
|
|
|
|
|
|
push @results, ":$server 324 $me $chan +$mode_string"; |
363
|
|
|
|
|
|
|
|
364
|
0
|
0
|
|
|
|
|
if ($irc->channel_creation_time($chan)) { |
365
|
0
|
|
|
|
|
|
my $time = $irc->channel_creation_time($chan); |
366
|
0
|
|
|
|
|
|
push @results, ":$server 329 $me $chan $time"; |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
} |
369
|
|
|
|
|
|
|
elsif ($type eq 'I') { |
370
|
0
|
|
|
|
|
|
while (my ($mask, $info) = each %{ $irc->channel_invex_list($chan) }) { |
|
0
|
|
|
|
|
|
|
371
|
0
|
|
|
|
|
|
push @results, ":$server 346 $me $chan $mask " . join (' ', @{$info}{qw(SetBy SetAt)}); |
|
0
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
} |
373
|
0
|
|
|
|
|
|
push @results, ":$server 347 $me $chan :End of Channel Invite List"; |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
elsif ($type eq 'e') { |
376
|
0
|
|
|
|
|
|
while (my ($mask, $info) = each %{ $irc->channel_except_list($chan) }) { |
|
0
|
|
|
|
|
|
|
377
|
0
|
|
|
|
|
|
push @results, ":$server 348 $me $chan $mask " . join (' ', @{$info}{qw(SetBy SetAt)}); |
|
0
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
} |
379
|
0
|
|
|
|
|
|
push @results, ":$server 349 $me $chan :End of Channel Exception List"; |
380
|
|
|
|
|
|
|
} |
381
|
|
|
|
|
|
|
elsif ($type eq 'b') { |
382
|
0
|
|
|
|
|
|
while (my ($mask, $info) = each %{ $irc->channel_ban_list($chan) }) { |
|
0
|
|
|
|
|
|
|
383
|
0
|
|
|
|
|
|
push @results, ":$server 367 $me $chan $mask " . join (' ', @{$info}{qw(SetBy SetAt)}); |
|
0
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
} |
385
|
0
|
|
|
|
|
|
push @results, ":$server 368 $me $chan :End of Channel Ban List"; |
386
|
|
|
|
|
|
|
} |
387
|
|
|
|
|
|
|
|
388
|
0
|
|
|
|
|
|
return @results; |
389
|
|
|
|
|
|
|
} |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
1; |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
=encoding utf8 |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
=head1 NAME |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
POE::Compoent::IRC::Plugin::MultiProxy::State - Generates IRC server replies based on information provided by POE::Component::IRC::State |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
=head1 SYNOPSIS |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
use POE::Compoent::IRC::Plugin::MultiProxy::State; |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
$irc->plugin_add('State', POE::Compoent::IRC::Plugin::MultiProxy::State->new()); |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
=head1 DESCRIPTION |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
POE::Compoent::IRC::Plugin::MultiProxy::::State is a |
408
|
|
|
|
|
|
|
L plugin. Its role is to use |
409
|
|
|
|
|
|
|
L's information as a |
410
|
|
|
|
|
|
|
cache so that fewer trips will be to the IRC server when clients submit |
411
|
|
|
|
|
|
|
queries. The methods here are only useful for a subset of the use cases that |
412
|
|
|
|
|
|
|
their corresponding commands are capable of, mostly because there are certain |
413
|
|
|
|
|
|
|
cases that only the actual IRC server can handle. However, the methods can |
414
|
|
|
|
|
|
|
handle all the automatic queries that modern IRC clients make, so it does the |
415
|
|
|
|
|
|
|
job. |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
Another thing this plugin does is hide from clients all server replies |
418
|
|
|
|
|
|
|
elicited by L's |
419
|
|
|
|
|
|
|
information gathering. |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
This plugin requires the IRC component to be |
422
|
|
|
|
|
|
|
L or a subclass thereof. |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
=head1 CONSTRUCTOR |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
=head2 C |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
Takes no arguments. |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
Returns a plugin object suitable for feeding to |
431
|
|
|
|
|
|
|
L's C method. |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
=head1 METHODS |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
=head2 C |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
One argument: |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
An IRC channel which the IRC component is on |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
Returns IRC protocol line responses to the C command. |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
=head2 C |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
One argument: |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
An IRC channel which the IRC component is on |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
Returns IRC protocol line responses to the C command. |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
=head2 C |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
One argument: |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
An IRC channel which the IRC component is on, or a known nickname |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
Returns IRC protocol line responses to the C command. |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
=head2 C |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
One or two arguments: |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
The IRC component's nickname, or a channel which the component is on |
464
|
|
|
|
|
|
|
and an optional mode type |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
Returns IRC protocol line responses to the C command. |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
=head2 C |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
In case a client asks for information about a channel while it is being |
471
|
|
|
|
|
|
|
synced, it should call this method, and the information will be provided |
472
|
|
|
|
|
|
|
as soon as it has been gathered. |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
Takes three arguments: |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
A code reference which will be called for every line of response generated, |
477
|
|
|
|
|
|
|
the type of reply being asked for (e.g. 'who_reply'), and the arguments |
478
|
|
|
|
|
|
|
to the corresponding method. |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
=head2 C |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
Takes one argument: |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
An IRC channel. |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
Returns 1 if the channel or nick is being synced, 0 otherwise. |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
=head1 AUTHOR |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
Hinrik Ern SigurEsson, hinrik.sig@gmail.com |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
=cut |