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 |