| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package App::Pocoirc; |
|
2
|
|
|
|
|
|
|
BEGIN { |
|
3
|
1
|
|
|
1
|
|
3330
|
$App::Pocoirc::AUTHORITY = 'cpan:HINRIK'; |
|
4
|
|
|
|
|
|
|
} |
|
5
|
|
|
|
|
|
|
{ |
|
6
|
|
|
|
|
|
|
$App::Pocoirc::VERSION = '0.47'; |
|
7
|
|
|
|
|
|
|
} |
|
8
|
|
|
|
|
|
|
|
|
9
|
1
|
|
|
1
|
|
8
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
42
|
|
|
10
|
1
|
|
|
1
|
|
5
|
use warnings FATAL => 'all'; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
45
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
1
|
|
|
1
|
|
50
|
use App::Pocoirc::Status; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
use Class::Load qw(try_load_class); |
|
14
|
|
|
|
|
|
|
use Fcntl qw(O_CREAT O_EXCL O_WRONLY); |
|
15
|
|
|
|
|
|
|
use File::Glob ':glob'; |
|
16
|
|
|
|
|
|
|
use File::Spec::Functions 'rel2abs'; |
|
17
|
|
|
|
|
|
|
use IO::Handle; |
|
18
|
|
|
|
|
|
|
use IRC::Utils qw(decode_irc); |
|
19
|
|
|
|
|
|
|
use POE; |
|
20
|
|
|
|
|
|
|
use POE::Component::Client::DNS; |
|
21
|
|
|
|
|
|
|
use POSIX 'strftime'; |
|
22
|
|
|
|
|
|
|
use Scalar::Util 'looks_like_number'; |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
sub new { |
|
25
|
|
|
|
|
|
|
my ($package, %args) = @_; |
|
26
|
|
|
|
|
|
|
return bless \%args, $package; |
|
27
|
|
|
|
|
|
|
} |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
sub run { |
|
30
|
|
|
|
|
|
|
my ($self) = @_; |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# we print IRC output, which will be UTF-8 |
|
33
|
|
|
|
|
|
|
binmode $_, ':utf8' for (*STDOUT, *STDERR); |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
if ($self->{list_plugins}) { |
|
36
|
|
|
|
|
|
|
require Module::Pluggable; |
|
37
|
|
|
|
|
|
|
Module::Pluggable->import( |
|
38
|
|
|
|
|
|
|
sub_name => '_available_plugins', |
|
39
|
|
|
|
|
|
|
search_path => 'POE::Component::IRC::Plugin', |
|
40
|
|
|
|
|
|
|
); |
|
41
|
|
|
|
|
|
|
for my $plugin (sort $self->_available_plugins()) { |
|
42
|
|
|
|
|
|
|
$plugin =~ s/^POE::Component::IRC::Plugin:://; |
|
43
|
|
|
|
|
|
|
print $plugin, "\n"; |
|
44
|
|
|
|
|
|
|
} |
|
45
|
|
|
|
|
|
|
return; |
|
46
|
|
|
|
|
|
|
} |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
$self->_setup(); |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
if ($self->{check_cfg}) { |
|
51
|
|
|
|
|
|
|
print "The configuration is valid and all modules could be compiled.\n"; |
|
52
|
|
|
|
|
|
|
return; |
|
53
|
|
|
|
|
|
|
} |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
if ($self->{daemonize}) { |
|
56
|
|
|
|
|
|
|
require Proc::Daemon; |
|
57
|
|
|
|
|
|
|
eval { |
|
58
|
|
|
|
|
|
|
Proc::Daemon::Init->(); |
|
59
|
|
|
|
|
|
|
if (defined $self->{log_file}) { |
|
60
|
|
|
|
|
|
|
open STDOUT, '>>:encoding(utf8)', $self->{log_file} |
|
61
|
|
|
|
|
|
|
or die "Can't open $self->{log_file}: $!\n"; |
|
62
|
|
|
|
|
|
|
open STDERR, '>>&STDOUT' or die "Can't redirect STDERR: $!\n"; |
|
63
|
|
|
|
|
|
|
STDOUT->autoflush(1); |
|
64
|
|
|
|
|
|
|
} |
|
65
|
|
|
|
|
|
|
$poe_kernel->has_forked(); |
|
66
|
|
|
|
|
|
|
}; |
|
67
|
|
|
|
|
|
|
chomp $@; |
|
68
|
|
|
|
|
|
|
die "Can't daemonize: $@\n" if $@; |
|
69
|
|
|
|
|
|
|
} |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
if (defined $self->{pid_file}) { |
|
72
|
|
|
|
|
|
|
sysopen my $fh, $self->{pid_file}, O_CREAT|O_EXCL|O_WRONLY |
|
73
|
|
|
|
|
|
|
or die "Can't create pid file or it already exists. Pocoirc already running?\n"; |
|
74
|
|
|
|
|
|
|
print $fh "$$\n"; |
|
75
|
|
|
|
|
|
|
close $fh; |
|
76
|
|
|
|
|
|
|
} |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
POE::Session->create( |
|
79
|
|
|
|
|
|
|
object_states => [ |
|
80
|
|
|
|
|
|
|
$self => [qw( |
|
81
|
|
|
|
|
|
|
_start |
|
82
|
|
|
|
|
|
|
sig_die |
|
83
|
|
|
|
|
|
|
sig_int |
|
84
|
|
|
|
|
|
|
sig_term |
|
85
|
|
|
|
|
|
|
irc_plugin_add |
|
86
|
|
|
|
|
|
|
irc_plugin_del |
|
87
|
|
|
|
|
|
|
irc_plugin_error |
|
88
|
|
|
|
|
|
|
irc_plugin_status |
|
89
|
|
|
|
|
|
|
irc_network |
|
90
|
|
|
|
|
|
|
irc_shutdown |
|
91
|
|
|
|
|
|
|
)], |
|
92
|
|
|
|
|
|
|
$self => { |
|
93
|
|
|
|
|
|
|
irc_432 => 'irc_432_or_433', |
|
94
|
|
|
|
|
|
|
irc_433 => 'irc_432_or_433', |
|
95
|
|
|
|
|
|
|
}, |
|
96
|
|
|
|
|
|
|
], |
|
97
|
|
|
|
|
|
|
); |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
$poe_kernel->run(); |
|
100
|
|
|
|
|
|
|
unlink $self->{pid_file} if defined $self->{pid_file}; |
|
101
|
|
|
|
|
|
|
return; |
|
102
|
|
|
|
|
|
|
} |
|
103
|
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
sub _setup { |
|
105
|
|
|
|
|
|
|
my ($self) = @_; |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
if (defined $self->{cfg}{pid_file}) { |
|
108
|
|
|
|
|
|
|
$self->{pid_file} = rel2abs(bsd_glob(delete $self->{cfg}{pid_file})); |
|
109
|
|
|
|
|
|
|
} |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
if (defined $self->{cfg}{log_file}) { |
|
112
|
|
|
|
|
|
|
my $log = rel2abs(bsd_glob(delete $self->{cfg}{log_file})); |
|
113
|
|
|
|
|
|
|
open my $fh, '>>', $log or die "Can't open $log: $!\n"; |
|
114
|
|
|
|
|
|
|
close $fh; |
|
115
|
|
|
|
|
|
|
$self->{log_file} = $log; |
|
116
|
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
if (!$self->{no_color}) { |
|
119
|
|
|
|
|
|
|
require Term::ANSIColor; |
|
120
|
|
|
|
|
|
|
Term::ANSIColor->import(); |
|
121
|
|
|
|
|
|
|
} |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
if (defined $self->{cfg}{lib}) { |
|
124
|
|
|
|
|
|
|
if (ref $self->{cfg}{lib} eq 'ARRAY' && @{ $self->{cfg}{lib} }) { |
|
125
|
|
|
|
|
|
|
unshift @INC, map { rel2abs(bsd_glob($_)) } @{ delete $self->{cfg}{lib} }; |
|
126
|
|
|
|
|
|
|
} |
|
127
|
|
|
|
|
|
|
else { |
|
128
|
|
|
|
|
|
|
unshift @INC, rel2abs(bsd_glob(delete $self->{cfg}{lib})); |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
} |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
$self->_load_classes(); |
|
133
|
|
|
|
|
|
|
return; |
|
134
|
|
|
|
|
|
|
} |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub _load_classes { |
|
137
|
|
|
|
|
|
|
my ($self) = @_; |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
for my $plug_spec (@{ $self->{cfg}{global_plugins} || [] }) { |
|
140
|
|
|
|
|
|
|
$self->_load_plugin($plug_spec); |
|
141
|
|
|
|
|
|
|
} |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
while (my ($network, $opts) = each %{ $self->{cfg}{networks} }) { |
|
144
|
|
|
|
|
|
|
while (my ($opt, $value) = each %{ $self->{cfg} }) { |
|
145
|
|
|
|
|
|
|
next if $opt =~ /^(?:networks|global_plugins|local_plugins)$/; |
|
146
|
|
|
|
|
|
|
$opts->{$opt} = $value if !defined $opts->{$opt}; |
|
147
|
|
|
|
|
|
|
} |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
for my $plug_spec (@{ $opts->{local_plugins} || [] }) { |
|
150
|
|
|
|
|
|
|
$self->_load_plugin($plug_spec); |
|
151
|
|
|
|
|
|
|
} |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
if (!defined $opts->{server}) { |
|
154
|
|
|
|
|
|
|
die "Server for network '$network' not specified\n"; |
|
155
|
|
|
|
|
|
|
} |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
if (defined $opts->{class}) { |
|
158
|
|
|
|
|
|
|
$opts->{class} = _load_either_class( |
|
159
|
|
|
|
|
|
|
"POE::Component::IRC::$opts->{class}", |
|
160
|
|
|
|
|
|
|
$opts->{class}, |
|
161
|
|
|
|
|
|
|
); |
|
162
|
|
|
|
|
|
|
} |
|
163
|
|
|
|
|
|
|
else { |
|
164
|
|
|
|
|
|
|
$opts->{class} = 'POE::Component::IRC::State'; |
|
165
|
|
|
|
|
|
|
my ($success, $error) = try_load_class($opts->{class}); |
|
166
|
|
|
|
|
|
|
chomp $error if defined $error; |
|
167
|
|
|
|
|
|
|
die "Can't load class $opts->{class}: $error\n" if !$success; |
|
168
|
|
|
|
|
|
|
} |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
return; |
|
172
|
|
|
|
|
|
|
} |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
# create plugins, spawn components, and connect to IRC |
|
175
|
|
|
|
|
|
|
sub _start { |
|
176
|
|
|
|
|
|
|
my ($kernel, $session, $self) = @_[KERNEL, SESSION, OBJECT]; |
|
177
|
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
$kernel->sig(DIE => 'sig_die'); |
|
179
|
|
|
|
|
|
|
$kernel->sig(INT => 'sig_int'); |
|
180
|
|
|
|
|
|
|
$kernel->sig(TERM => 'sig_term'); |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
$self->_status(undef, 'normal', "Started (pid $$)"); |
|
183
|
|
|
|
|
|
|
my ($own, $global, $local) = $self->_construct_objects(); |
|
184
|
|
|
|
|
|
|
$self->_register_plugins($session->ID(), $own, $global, $local); |
|
185
|
|
|
|
|
|
|
$self->{own_plugins} = $own; |
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
for my $entry (@{ $self->{ircs} }) { |
|
188
|
|
|
|
|
|
|
my ($network, $irc) = @$entry; |
|
189
|
|
|
|
|
|
|
$self->_status($network, 'normal', 'Connecting to IRC ('.$irc->server.')'); |
|
190
|
|
|
|
|
|
|
$irc->yield('connect'); |
|
191
|
|
|
|
|
|
|
} |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
return; |
|
194
|
|
|
|
|
|
|
} |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
sub _construct_objects { |
|
197
|
|
|
|
|
|
|
my ($self) = @_; |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
# create the shared DNS resolver |
|
200
|
|
|
|
|
|
|
$self->{resolver} = POE::Component::Client::DNS->spawn(); |
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
# construct global plugins |
|
203
|
|
|
|
|
|
|
$self->_status(undef, 'normal', "Constructing global plugins"); |
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
my $global_plugs = $self->_create_plugins(delete $self->{cfg}{global_plugins}); |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
my $own_plugs = [ |
|
208
|
|
|
|
|
|
|
[ |
|
209
|
|
|
|
|
|
|
'PocoircStatus', |
|
210
|
|
|
|
|
|
|
App::Pocoirc::Status->new( |
|
211
|
|
|
|
|
|
|
Pocoirc => $self, |
|
212
|
|
|
|
|
|
|
Trace => $self->{trace}, |
|
213
|
|
|
|
|
|
|
Verbose => $self->{verbose}, |
|
214
|
|
|
|
|
|
|
Dynamic => (defined $self->{cfg_file} ? 1 : 0), |
|
215
|
|
|
|
|
|
|
), |
|
216
|
|
|
|
|
|
|
], |
|
217
|
|
|
|
|
|
|
]; |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
if ($self->{interactive}) { |
|
220
|
|
|
|
|
|
|
require App::Pocoirc::ReadLine; |
|
221
|
|
|
|
|
|
|
push @$own_plugs, [ |
|
222
|
|
|
|
|
|
|
'PocoircReadLine', |
|
223
|
|
|
|
|
|
|
App::Pocoirc::ReadLine->new( |
|
224
|
|
|
|
|
|
|
Pocoirc => $self, |
|
225
|
|
|
|
|
|
|
), |
|
226
|
|
|
|
|
|
|
]; |
|
227
|
|
|
|
|
|
|
} |
|
228
|
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
my $local_plugs; |
|
230
|
|
|
|
|
|
|
# construct IRC components |
|
231
|
|
|
|
|
|
|
while (my ($network, $opts) = each %{ $self->{cfg}{networks} }) { |
|
232
|
|
|
|
|
|
|
my $class = delete $opts->{class}; |
|
233
|
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
# construct network-specific plugins |
|
235
|
|
|
|
|
|
|
$self->_status($network, 'normal', 'Constructing local plugins'); |
|
236
|
|
|
|
|
|
|
$local_plugs->{$network} = $self->_create_plugins(delete $opts->{local_plugins}); |
|
237
|
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
$self->_status($network, 'normal', "Spawning IRC component ($class)"); |
|
239
|
|
|
|
|
|
|
my $irc = $class->spawn( |
|
240
|
|
|
|
|
|
|
%$opts, |
|
241
|
|
|
|
|
|
|
Resolver => $self->{resolver}, |
|
242
|
|
|
|
|
|
|
); |
|
243
|
|
|
|
|
|
|
my $isa = eval { $irc->isa($class) }; |
|
244
|
|
|
|
|
|
|
die "isa() test failed for component of class $class\n" if !$isa; |
|
245
|
|
|
|
|
|
|
push @{ $self->{ircs} }, [$network, $irc]; |
|
246
|
|
|
|
|
|
|
} |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
return $own_plugs, $global_plugs, $local_plugs; |
|
249
|
|
|
|
|
|
|
} |
|
250
|
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
sub _load_either_class { |
|
252
|
|
|
|
|
|
|
my ($primary, $secondary) = @_; |
|
253
|
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
my ($success, $error, @err); |
|
255
|
|
|
|
|
|
|
($success, $error) = try_load_class($primary); |
|
256
|
|
|
|
|
|
|
return $primary if $success; |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
push @err, $error; |
|
259
|
|
|
|
|
|
|
($success, $error) = try_load_class($secondary); |
|
260
|
|
|
|
|
|
|
return $secondary if $success; |
|
261
|
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
chomp $error if defined $error; |
|
263
|
|
|
|
|
|
|
push @err, $error; |
|
264
|
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
my $class = "$primary or $secondary"; |
|
266
|
|
|
|
|
|
|
if (@err == 2) { |
|
267
|
|
|
|
|
|
|
if ($err[0] =~ /^Can't locate / && $err[1] !~ /^Can't locate /) { |
|
268
|
|
|
|
|
|
|
$class = $secondary; |
|
269
|
|
|
|
|
|
|
shift @err; |
|
270
|
|
|
|
|
|
|
} |
|
271
|
|
|
|
|
|
|
elsif ($err[1] =~ /^Can't locate / && $err[0] !~ /^Can't locate /) { |
|
272
|
|
|
|
|
|
|
$class = $primary; |
|
273
|
|
|
|
|
|
|
pop @err; |
|
274
|
|
|
|
|
|
|
} |
|
275
|
|
|
|
|
|
|
} |
|
276
|
|
|
|
|
|
|
my $reason = join "\n", map { " $_" } @err; |
|
277
|
|
|
|
|
|
|
die "Failed to load class $class:\n$reason\n"; |
|
278
|
|
|
|
|
|
|
} |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
sub _register_plugins { |
|
281
|
|
|
|
|
|
|
my ($self, $session_id, $own, $global, $local) = @_; |
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
for my $entry (@{ $self->{ircs} }) { |
|
284
|
|
|
|
|
|
|
my ($network, $irc) = @$entry; |
|
285
|
|
|
|
|
|
|
$self->_status($network, 'normal', 'Registering plugins'); |
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
for my $plugin (@$own, @$global, @{ $local->{$network} }) { |
|
288
|
|
|
|
|
|
|
my ($name, $object) = @$plugin; |
|
289
|
|
|
|
|
|
|
$irc->plugin_add("${name}_$session_id", $object, |
|
290
|
|
|
|
|
|
|
network => $network, |
|
291
|
|
|
|
|
|
|
); |
|
292
|
|
|
|
|
|
|
} |
|
293
|
|
|
|
|
|
|
} |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
return; |
|
296
|
|
|
|
|
|
|
} |
|
297
|
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
sub _dump { |
|
299
|
|
|
|
|
|
|
my ($arg) = @_; |
|
300
|
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
if (ref $arg eq 'ARRAY') { |
|
302
|
|
|
|
|
|
|
my @elems; |
|
303
|
|
|
|
|
|
|
for my $elem (@$arg) { |
|
304
|
|
|
|
|
|
|
push @elems, _dump($elem); |
|
305
|
|
|
|
|
|
|
} |
|
306
|
|
|
|
|
|
|
return '['. join(', ', @elems) .']'; |
|
307
|
|
|
|
|
|
|
} |
|
308
|
|
|
|
|
|
|
elsif (ref $arg eq 'HASH') { |
|
309
|
|
|
|
|
|
|
my @pairs; |
|
310
|
|
|
|
|
|
|
for my $key (keys %$arg) { |
|
311
|
|
|
|
|
|
|
push @pairs, [$key, _dump($arg->{$key})]; |
|
312
|
|
|
|
|
|
|
} |
|
313
|
|
|
|
|
|
|
return '{'. join(', ', map { "$_->[0] => $_->[1]" } @pairs) .'}'; |
|
314
|
|
|
|
|
|
|
} |
|
315
|
|
|
|
|
|
|
elsif (ref $arg) { |
|
316
|
|
|
|
|
|
|
require overload; |
|
317
|
|
|
|
|
|
|
return overload::StrVal($arg); |
|
318
|
|
|
|
|
|
|
} |
|
319
|
|
|
|
|
|
|
elsif (defined $arg) { |
|
320
|
|
|
|
|
|
|
return $arg if looks_like_number($arg); |
|
321
|
|
|
|
|
|
|
return "'".decode_irc($arg)."'"; |
|
322
|
|
|
|
|
|
|
} |
|
323
|
|
|
|
|
|
|
else { |
|
324
|
|
|
|
|
|
|
return 'undef'; |
|
325
|
|
|
|
|
|
|
} |
|
326
|
|
|
|
|
|
|
} |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
sub _event_debug { |
|
329
|
|
|
|
|
|
|
my ($self, $irc, $args, $event) = @_; |
|
330
|
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
if (!defined $event) { |
|
332
|
|
|
|
|
|
|
$event = (caller(1))[3]; |
|
333
|
|
|
|
|
|
|
$event =~ s/.*:://; |
|
334
|
|
|
|
|
|
|
} |
|
335
|
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
my @output; |
|
337
|
|
|
|
|
|
|
for my $i (0..$#{ $args }) { |
|
338
|
|
|
|
|
|
|
push @output, "ARG$i: " . _dump($args->[$i]); |
|
339
|
|
|
|
|
|
|
} |
|
340
|
|
|
|
|
|
|
$self->_status($irc, 'debug', "$event: ".join(', ', @output)); |
|
341
|
|
|
|
|
|
|
return; |
|
342
|
|
|
|
|
|
|
} |
|
343
|
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
# let's log this if it's preventing us from logging in |
|
345
|
|
|
|
|
|
|
sub irc_432_or_433 { |
|
346
|
|
|
|
|
|
|
my $self = $_[OBJECT]; |
|
347
|
|
|
|
|
|
|
my $irc = $_[SENDER]->get_heap(); |
|
348
|
|
|
|
|
|
|
my $reason = decode_irc($_[ARG2]->[1]); |
|
349
|
|
|
|
|
|
|
return if $irc->logged_in(); |
|
350
|
|
|
|
|
|
|
my $nick = $irc->nick_name(); |
|
351
|
|
|
|
|
|
|
$self->_status($irc, 'normal', "Login attempt failed: $reason"); |
|
352
|
|
|
|
|
|
|
return; |
|
353
|
|
|
|
|
|
|
} |
|
354
|
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
# fetch the server name if we're not using a config file |
|
356
|
|
|
|
|
|
|
sub irc_network { |
|
357
|
|
|
|
|
|
|
my ($self, $sender, $network) = @_[OBJECT, SENDER, ARG0]; |
|
358
|
|
|
|
|
|
|
my $irc = $sender->get_heap(); |
|
359
|
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
for my $idx (0..$#{ $self->{ircs} }) { |
|
361
|
|
|
|
|
|
|
if ($self->{ircs}[$idx][1] == $irc) { |
|
362
|
|
|
|
|
|
|
$self->{ircs}[$idx][0] = $network; |
|
363
|
|
|
|
|
|
|
last; |
|
364
|
|
|
|
|
|
|
} |
|
365
|
|
|
|
|
|
|
} |
|
366
|
|
|
|
|
|
|
return; |
|
367
|
|
|
|
|
|
|
} |
|
368
|
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
# we handle plugin status messages here because the status plugin won't |
|
370
|
|
|
|
|
|
|
# see these for previously added plugins or plugin_del for itself, etc |
|
371
|
|
|
|
|
|
|
sub irc_plugin_add { |
|
372
|
|
|
|
|
|
|
my ($self, $alias) = @_[OBJECT, ARG0]; |
|
373
|
|
|
|
|
|
|
my $irc = $_[SENDER]->get_heap(); |
|
374
|
|
|
|
|
|
|
$self->_event_debug($irc, [@_[ARG0..$#_]], 'S_plugin_add') if $self->{trace}; |
|
375
|
|
|
|
|
|
|
$self->_status($irc, 'normal', "Added plugin $alias"); |
|
376
|
|
|
|
|
|
|
return; |
|
377
|
|
|
|
|
|
|
} |
|
378
|
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
sub irc_plugin_del { |
|
380
|
|
|
|
|
|
|
my ($self, $alias) = @_[OBJECT, ARG0]; |
|
381
|
|
|
|
|
|
|
my $irc = $_[SENDER]->get_heap(); |
|
382
|
|
|
|
|
|
|
$self->_event_debug($irc, [@_[ARG0..$#_]], 'S_plugin_del') if $self->{trace}; |
|
383
|
|
|
|
|
|
|
$self->_status($irc, 'normal', "Deleted plugin $alias"); |
|
384
|
|
|
|
|
|
|
return; |
|
385
|
|
|
|
|
|
|
} |
|
386
|
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
sub irc_plugin_error { |
|
388
|
|
|
|
|
|
|
my ($self, $error) = @_[OBJECT, ARG0]; |
|
389
|
|
|
|
|
|
|
my $irc = $_[SENDER]->get_heap(); |
|
390
|
|
|
|
|
|
|
$self->_event_debug($irc, [@_[ARG0..$#_]], 'S_plugin_error') if $self->{trace}; |
|
391
|
|
|
|
|
|
|
$self->_status($irc, 'error', $error); |
|
392
|
|
|
|
|
|
|
return; |
|
393
|
|
|
|
|
|
|
} |
|
394
|
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
sub irc_plugin_status { |
|
396
|
|
|
|
|
|
|
my ($self, $plugin, @args) = @_[OBJECT, ARG0..$#_]; |
|
397
|
|
|
|
|
|
|
my $irc = $_[SENDER]->get_heap(); |
|
398
|
|
|
|
|
|
|
my $plugins = $irc->plugin_list(); |
|
399
|
|
|
|
|
|
|
my %plug2alias = map { $plugins->{$_} => $_ } keys %$plugins; |
|
400
|
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
my $extension = ref $plugin eq 'App::Pocoirc::Status' |
|
402
|
|
|
|
|
|
|
? '' |
|
403
|
|
|
|
|
|
|
: "/$plug2alias{$plugin}"; |
|
404
|
|
|
|
|
|
|
$self->_status($self->_irc_to_network($irc).$extension, @args); |
|
405
|
|
|
|
|
|
|
return; |
|
406
|
|
|
|
|
|
|
} |
|
407
|
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
sub irc_shutdown { |
|
409
|
|
|
|
|
|
|
my ($self) = $_[OBJECT]; |
|
410
|
|
|
|
|
|
|
my $irc = $_[SENDER]->get_heap(); |
|
411
|
|
|
|
|
|
|
$self->_event_debug($irc, [@_[ARG0..$#_]], 'S_shutdown') if $self->{trace}; |
|
412
|
|
|
|
|
|
|
$self->_status($irc, 'normal', 'IRC component shut down'); |
|
413
|
|
|
|
|
|
|
return; |
|
414
|
|
|
|
|
|
|
} |
|
415
|
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
sub verbose { |
|
417
|
|
|
|
|
|
|
my ($self, $value) = @_; |
|
418
|
|
|
|
|
|
|
if (defined $value) { |
|
419
|
|
|
|
|
|
|
$self->{verbose} = $value; |
|
420
|
|
|
|
|
|
|
for my $plugin (@{ $self->{own_plugins} }) { |
|
421
|
|
|
|
|
|
|
$plugin->[1]->verbose($value) if $plugin->[1]->can('verbose'); |
|
422
|
|
|
|
|
|
|
} |
|
423
|
|
|
|
|
|
|
} |
|
424
|
|
|
|
|
|
|
return $self->{verbose}; |
|
425
|
|
|
|
|
|
|
} |
|
426
|
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
sub trace { |
|
428
|
|
|
|
|
|
|
my ($self, $value) = @_; |
|
429
|
|
|
|
|
|
|
if (defined $value) { |
|
430
|
|
|
|
|
|
|
$self->{trace} = $value; |
|
431
|
|
|
|
|
|
|
for my $plugin (@{ $self->{own_plugins} }) { |
|
432
|
|
|
|
|
|
|
$plugin->[1]->trace($value) if $plugin->[1]->can('trace'); |
|
433
|
|
|
|
|
|
|
} |
|
434
|
|
|
|
|
|
|
} |
|
435
|
|
|
|
|
|
|
return $self->{trace}; |
|
436
|
|
|
|
|
|
|
} |
|
437
|
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
sub _status { |
|
439
|
|
|
|
|
|
|
my ($self, $context, $type, $message) = @_; |
|
440
|
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
my $stamp = strftime('%Y-%m-%d %H:%M:%S', localtime); |
|
442
|
|
|
|
|
|
|
my $irc = eval { $context->isa('POE::Component::IRC') }; |
|
443
|
|
|
|
|
|
|
$context = $self->_irc_to_network($context) if $irc; |
|
444
|
|
|
|
|
|
|
$context = defined $context ? " [$context]\t" : ' '; |
|
445
|
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
if (defined $type && $type eq 'error') { |
|
447
|
|
|
|
|
|
|
$message = "!!! $message"; |
|
448
|
|
|
|
|
|
|
} |
|
449
|
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
my $log_line = "$stamp$context$message"; |
|
451
|
|
|
|
|
|
|
my $term_line = $log_line; |
|
452
|
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
if (!$self->{no_color}) { |
|
454
|
|
|
|
|
|
|
if (defined $type && $type eq 'error') { |
|
455
|
|
|
|
|
|
|
$term_line = colored($term_line, 'red'); |
|
456
|
|
|
|
|
|
|
} |
|
457
|
|
|
|
|
|
|
elsif (defined $type && $type eq 'debug') { |
|
458
|
|
|
|
|
|
|
$term_line = colored($term_line, 'yellow'); |
|
459
|
|
|
|
|
|
|
} |
|
460
|
|
|
|
|
|
|
else { |
|
461
|
|
|
|
|
|
|
$term_line = colored($term_line, 'green'); |
|
462
|
|
|
|
|
|
|
} |
|
463
|
|
|
|
|
|
|
} |
|
464
|
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
print $term_line, "\n" if !$self->{daemonize}; |
|
466
|
|
|
|
|
|
|
if (defined $self->{log_file}) { |
|
467
|
|
|
|
|
|
|
if (open my $fh, '>>:encoding(utf8)', $self->{log_file}) { |
|
468
|
|
|
|
|
|
|
$fh->autoflush(1); |
|
469
|
|
|
|
|
|
|
print $fh $log_line, "\n"; |
|
470
|
|
|
|
|
|
|
close $fh; |
|
471
|
|
|
|
|
|
|
} |
|
472
|
|
|
|
|
|
|
elsif (!$self->{daemonize}) { |
|
473
|
|
|
|
|
|
|
warn "Can't open $self->{log_file}: $!\n"; |
|
474
|
|
|
|
|
|
|
} |
|
475
|
|
|
|
|
|
|
} |
|
476
|
|
|
|
|
|
|
return; |
|
477
|
|
|
|
|
|
|
} |
|
478
|
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
sub _irc_to_network { |
|
480
|
|
|
|
|
|
|
my ($self, $irc) = @_; |
|
481
|
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
for my $entry (@{ $self->{ircs} }) { |
|
483
|
|
|
|
|
|
|
my ($network, $object) = @$entry; |
|
484
|
|
|
|
|
|
|
return $network if $irc == $object; |
|
485
|
|
|
|
|
|
|
} |
|
486
|
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
return; |
|
488
|
|
|
|
|
|
|
} |
|
489
|
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
# find out the canonical class name for the plugin and load it |
|
491
|
|
|
|
|
|
|
sub _load_plugin { |
|
492
|
|
|
|
|
|
|
my ($self, $plug_spec) = @_; |
|
493
|
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
return if defined $plug_spec->[2]; |
|
495
|
|
|
|
|
|
|
my ($class, $args) = @$plug_spec; |
|
496
|
|
|
|
|
|
|
$args = {} if !defined $args; |
|
497
|
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
my $canonclass = _load_either_class( |
|
499
|
|
|
|
|
|
|
"POE::Component::IRC::Plugin::$class", |
|
500
|
|
|
|
|
|
|
$class, |
|
501
|
|
|
|
|
|
|
); |
|
502
|
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
$plug_spec->[1] = $args; |
|
504
|
|
|
|
|
|
|
$plug_spec->[2] = $canonclass; |
|
505
|
|
|
|
|
|
|
return; |
|
506
|
|
|
|
|
|
|
} |
|
507
|
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
sub _create_plugins { |
|
509
|
|
|
|
|
|
|
my ($self, $plugins) = @_; |
|
510
|
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
my @return; |
|
512
|
|
|
|
|
|
|
for my $plug_spec (@$plugins) { |
|
513
|
|
|
|
|
|
|
my ($class, $args, $canonclass) = @$plug_spec; |
|
514
|
|
|
|
|
|
|
my $obj = $canonclass->new(%$args); |
|
515
|
|
|
|
|
|
|
my $isa = eval { $obj->isa($canonclass) }; |
|
516
|
|
|
|
|
|
|
die "isa() test failed for plugin of class $canonclass\n" if !$isa; |
|
517
|
|
|
|
|
|
|
push @return, [$class, $obj]; |
|
518
|
|
|
|
|
|
|
} |
|
519
|
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
return \@return; |
|
521
|
|
|
|
|
|
|
} |
|
522
|
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
sub sig_die { |
|
524
|
|
|
|
|
|
|
my ($kernel, $self, $ex) = @_[KERNEL, OBJECT, ARG1]; |
|
525
|
|
|
|
|
|
|
chomp $ex->{error_str}; |
|
526
|
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
my $error = "Event $ex->{event} in session ".$ex->{dest_session}->ID |
|
528
|
|
|
|
|
|
|
." raised exception:\n $ex->{error_str}"; |
|
529
|
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
$self->_status(undef, 'error', $error); |
|
531
|
|
|
|
|
|
|
$self->shutdown('Exiting due to an exception') if !$self->{shutdown}; |
|
532
|
|
|
|
|
|
|
$kernel->sig_handled(); |
|
533
|
|
|
|
|
|
|
return; |
|
534
|
|
|
|
|
|
|
} |
|
535
|
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
sub sig_int { |
|
537
|
|
|
|
|
|
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
|
538
|
|
|
|
|
|
|
$self->shutdown('Exiting due to SIGINT') if !$self->{shutdown}; |
|
539
|
|
|
|
|
|
|
$kernel->sig_handled(); |
|
540
|
|
|
|
|
|
|
return; |
|
541
|
|
|
|
|
|
|
} |
|
542
|
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
sub sig_term { |
|
544
|
|
|
|
|
|
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
|
545
|
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
$self->shutdown('Exiting due to SIGTERM') if !$self->{shutdown}; |
|
547
|
|
|
|
|
|
|
$kernel->sig_handled(); |
|
548
|
|
|
|
|
|
|
return; |
|
549
|
|
|
|
|
|
|
} |
|
550
|
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
sub shutdown { |
|
552
|
|
|
|
|
|
|
my ($self, $reason) = @_; |
|
553
|
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
$self->_status(undef, 'normal', $reason); |
|
555
|
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
my $logged_in; |
|
557
|
|
|
|
|
|
|
for my $irc (@{ $self->{ircs} }) { |
|
558
|
|
|
|
|
|
|
my ($network, $obj) = @$irc; |
|
559
|
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
if (!$logged_in && $obj->logged_in()) { |
|
561
|
|
|
|
|
|
|
$logged_in = 1; |
|
562
|
|
|
|
|
|
|
$self->_status(undef, 'normal', |
|
563
|
|
|
|
|
|
|
'Waiting up to 5 seconds for IRC server(s) to disconnect us'); |
|
564
|
|
|
|
|
|
|
} |
|
565
|
|
|
|
|
|
|
$obj->yield('shutdown', $reason, 5); |
|
566
|
|
|
|
|
|
|
} |
|
567
|
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
$self->{resolver}->shutdown() if $self->{resolver}; |
|
569
|
|
|
|
|
|
|
$self->{shutdown} = 1; |
|
570
|
|
|
|
|
|
|
return; |
|
571
|
|
|
|
|
|
|
} |
|
572
|
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
1; |
|
574
|
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
=encoding utf8 |
|
576
|
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
=head1 NAME |
|
578
|
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
App::Pocoirc - A command line tool for launching POE::Component::IRC clients |
|
580
|
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
582
|
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
This distribution provides a generic way to launch IRC clients which use |
|
584
|
|
|
|
|
|
|
L. The main features are: |
|
585
|
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
=over 4 |
|
587
|
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
=item * Prints useful status information (to your terminal and/or a log file) |
|
589
|
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
=item * Will daemonize if you so wish |
|
591
|
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
=item * Supports a configuration file |
|
593
|
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
=item * Offers a user friendly way to pass arguments to POE::Component::IRC |
|
595
|
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
=item * Supports multiple IRC components and lets you specify which plugins |
|
597
|
|
|
|
|
|
|
to load locally (one object per component) or globally (single object) |
|
598
|
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
=item * Has an interactive mode where you can issue issue commands and |
|
600
|
|
|
|
|
|
|
call methods on the IRC component(s). |
|
601
|
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
It can be used to launch IRC bots or proxies, loaded with plugins of your |
|
603
|
|
|
|
|
|
|
choice. It is very useful for testing and debugging |
|
604
|
|
|
|
|
|
|
L plugins as well as IRC servers. |
|
605
|
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
=back |
|
607
|
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
=head1 CONFIGURATION |
|
609
|
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
nick: foobar1234 |
|
611
|
|
|
|
|
|
|
username: foobar |
|
612
|
|
|
|
|
|
|
log_file: /my/log.file |
|
613
|
|
|
|
|
|
|
lib: /my/modules |
|
614
|
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
global_plugins: |
|
616
|
|
|
|
|
|
|
- [CTCP] |
|
617
|
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
local_plugins: |
|
619
|
|
|
|
|
|
|
- [BotTraffic] |
|
620
|
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
networks: |
|
622
|
|
|
|
|
|
|
freenode: |
|
623
|
|
|
|
|
|
|
server: irc.freenode.net |
|
624
|
|
|
|
|
|
|
local_plugins: |
|
625
|
|
|
|
|
|
|
- [AutoJoin, { Channels: ['#foodsfdsf'] } ] |
|
626
|
|
|
|
|
|
|
magnet: |
|
627
|
|
|
|
|
|
|
server: irc.perl.org |
|
628
|
|
|
|
|
|
|
nick: hlagherf32fr |
|
629
|
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
The configuration file is in L or L format. It consists |
|
631
|
|
|
|
|
|
|
of a hash containing C, C, C, C, |
|
632
|
|
|
|
|
|
|
C, C, and default parameters to |
|
633
|
|
|
|
|
|
|
L. Only C is |
|
634
|
|
|
|
|
|
|
required. |
|
635
|
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
C is either the name of a directory containing Perl modules (e.g. |
|
637
|
|
|
|
|
|
|
plugins), or an array of such names. Kind of like Perl's I<-I>. |
|
638
|
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
C is the path to a log file to which status messages will be written. |
|
640
|
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
C is the IRC component class. Defaults to |
|
642
|
|
|
|
|
|
|
L. |
|
643
|
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
=head2 Networks |
|
645
|
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
The C option should be a hash of network hashes. The keys are the |
|
647
|
|
|
|
|
|
|
names of the networks. A network hash can contain C and |
|
648
|
|
|
|
|
|
|
parameters to POE::Component::IRC. None are required, except C if not |
|
649
|
|
|
|
|
|
|
defined at the top level. The POE::Component::IRC parameters specified in this |
|
650
|
|
|
|
|
|
|
hash will override the ones specified at the top level. |
|
651
|
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
=head2 Plugins |
|
653
|
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
The C and C options should consist of an array |
|
655
|
|
|
|
|
|
|
containing the short plugin class name (e.g. 'AutoJoin') and optionally a hash |
|
656
|
|
|
|
|
|
|
of arguments to that plugin. When figuring out the correct package name, |
|
657
|
|
|
|
|
|
|
App::Pocoirc will first try to load POE::Component::IRC::Plugin::I |
|
658
|
|
|
|
|
|
|
before trying to load I. |
|
659
|
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
The plugins in C will be instantiated once and then added to |
|
661
|
|
|
|
|
|
|
all IRC components. B not all plugins are designed to be used with |
|
662
|
|
|
|
|
|
|
multiple IRC components simultaneously. |
|
663
|
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
If you specify C at the top level, it will serve as a default |
|
665
|
|
|
|
|
|
|
list of local plugins, which can be overridden in a network hash. |
|
666
|
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
=head1 OUTPUT |
|
668
|
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
Here is some example output from the program: |
|
670
|
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
$ pocoirc -f example/config.yml |
|
672
|
|
|
|
|
|
|
2011-04-18 18:10:52 Started (pid 20105) |
|
673
|
|
|
|
|
|
|
2011-04-18 18:10:52 Constructing global plugins |
|
674
|
|
|
|
|
|
|
2011-04-18 18:10:52 [freenode] Constructing local plugins |
|
675
|
|
|
|
|
|
|
2011-04-18 18:10:52 [freenode] Spawning IRC component (POE::Component::IRC::State) |
|
676
|
|
|
|
|
|
|
2011-04-18 18:10:52 [magnet] Constructing local plugins |
|
677
|
|
|
|
|
|
|
2011-04-18 18:10:52 [magnet] Spawning IRC component (POE::Component::IRC::State) |
|
678
|
|
|
|
|
|
|
2011-04-18 18:10:52 [freenode] Registering plugins |
|
679
|
|
|
|
|
|
|
2011-04-18 18:10:52 [magnet] Registering plugins |
|
680
|
|
|
|
|
|
|
2011-04-18 18:10:52 [freenode] Connecting to IRC (irc.freenode.net) |
|
681
|
|
|
|
|
|
|
2011-04-18 18:10:52 [magnet] Connecting to IRC (irc.perl.org) |
|
682
|
|
|
|
|
|
|
2011-04-18 18:10:52 [freenode] Added plugin Whois3 |
|
683
|
|
|
|
|
|
|
2011-04-18 18:10:52 [freenode] Added plugin ISupport3 |
|
684
|
|
|
|
|
|
|
2011-04-18 18:10:52 [freenode] Added plugin DCC3 |
|
685
|
|
|
|
|
|
|
2011-04-18 18:10:52 [magnet] Added plugin Whois5 |
|
686
|
|
|
|
|
|
|
2011-04-18 18:10:52 [magnet] Added plugin ISupport5 |
|
687
|
|
|
|
|
|
|
2011-04-18 18:10:52 [magnet] Added plugin DCC5 |
|
688
|
|
|
|
|
|
|
2011-04-18 18:10:52 [freenode] Added plugin CTCP1 |
|
689
|
|
|
|
|
|
|
2011-04-18 18:10:52 [freenode] Added plugin AutoJoin1 |
|
690
|
|
|
|
|
|
|
2011-04-18 18:10:52 [freenode] Added plugin PocoircStatus1 |
|
691
|
|
|
|
|
|
|
2011-04-18 18:10:52 [magnet] Added plugin CTCP1 |
|
692
|
|
|
|
|
|
|
2011-04-18 18:10:52 [magnet] Added plugin PocoircStatus1 |
|
693
|
|
|
|
|
|
|
2011-04-18 18:10:52 [magnet] Connected to server irc.perl.org |
|
694
|
|
|
|
|
|
|
2011-04-18 18:10:52 [magnet] Server notice: *** Looking up your hostname... |
|
695
|
|
|
|
|
|
|
2011-04-18 18:10:52 [magnet] Server notice: *** Checking Ident |
|
696
|
|
|
|
|
|
|
2011-04-18 18:10:52 [freenode] Connected to server irc.freenode.net |
|
697
|
|
|
|
|
|
|
2011-04-18 18:10:53 [magnet] Server notice: *** Found your hostname |
|
698
|
|
|
|
|
|
|
2011-04-18 18:10:53 [freenode] Server notice: *** Looking up your hostname... |
|
699
|
|
|
|
|
|
|
2011-04-18 18:10:53 [freenode] Server notice: *** Checking Ident |
|
700
|
|
|
|
|
|
|
2011-04-18 18:10:53 [freenode] Server notice: *** Couldn't look up your hostname |
|
701
|
|
|
|
|
|
|
2011-04-18 18:11:03 [magnet] Server notice: *** No Ident response |
|
702
|
|
|
|
|
|
|
2011-04-18 18:11:03 [magnet] Logged in to server magnet.shadowcat.co.uk with nick hlagherf32fr |
|
703
|
|
|
|
|
|
|
2011-04-18 18:11:07 [freenode] Server notice: *** No Ident response |
|
704
|
|
|
|
|
|
|
2011-04-18 18:11:07 [freenode] Logged in to server niven.freenode.net with nick foobar1234 |
|
705
|
|
|
|
|
|
|
2011-04-18 18:11:11 [freenode] Joined channel #foodsfdsf |
|
706
|
|
|
|
|
|
|
^C2011-04-18 18:11:22 Exiting due to SIGINT |
|
707
|
|
|
|
|
|
|
2011-04-18 18:11:22 Waiting up to 5 seconds for IRC server(s) to disconnect us |
|
708
|
|
|
|
|
|
|
2011-04-18 18:11:22 [magnet] Error from IRC server: Closing Link: 212-30-192-157.static.simnet.is () |
|
709
|
|
|
|
|
|
|
2011-04-18 18:11:22 [magnet] Deleted plugin DCC5 |
|
710
|
|
|
|
|
|
|
2011-04-18 18:11:22 [magnet] Deleted plugin ISupport5 |
|
711
|
|
|
|
|
|
|
2011-04-18 18:11:22 [magnet] Deleted plugin CTCP1 |
|
712
|
|
|
|
|
|
|
2011-04-18 18:11:22 [magnet] Deleted plugin Whois5 |
|
713
|
|
|
|
|
|
|
2011-04-18 18:11:22 [magnet] Deleted plugin PocoircStatus1 |
|
714
|
|
|
|
|
|
|
2011-04-18 18:11:22 [magnet] IRC component shut down |
|
715
|
|
|
|
|
|
|
2011-04-18 18:11:22 [freenode] Quit from IRC (Client Quit) |
|
716
|
|
|
|
|
|
|
2011-04-18 18:11:22 [freenode] Error from IRC server: Closing Link: 212.30.192.157 (Client Quit) |
|
717
|
|
|
|
|
|
|
2011-04-18 18:11:22 [freenode] Deleted plugin AutoJoin1 |
|
718
|
|
|
|
|
|
|
2011-04-18 18:11:22 [freenode] Deleted plugin CTCP1 |
|
719
|
|
|
|
|
|
|
2011-04-18 18:11:22 [freenode] Deleted plugin DCC3 |
|
720
|
|
|
|
|
|
|
2011-04-18 18:11:22 [freenode] Deleted plugin PocoircStatus1 |
|
721
|
|
|
|
|
|
|
2011-04-18 18:11:22 [freenode] Deleted plugin Whois3 |
|
722
|
|
|
|
|
|
|
2011-04-18 18:11:22 [freenode] Deleted plugin ISupport3 |
|
723
|
|
|
|
|
|
|
2011-04-18 18:11:22 [freenode] IRC component shut down |
|
724
|
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
=head1 AUTHOR |
|
726
|
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
Hinrik Ern SigurEsson, hinrik.sig@gmail.com |
|
728
|
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
|
730
|
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
Copyright 2010 Hinrik Ern SigurEsson |
|
732
|
|
|
|
|
|
|
|
|
733
|
|
|
|
|
|
|
This program is free software, you can redistribute it and/or modify |
|
734
|
|
|
|
|
|
|
it under the same terms as Perl itself. |
|
735
|
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
=cut |