line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Bot::BasicBot; |
2
|
|
|
|
|
|
|
our $AUTHORITY = 'cpan:BIGPRESH'; |
3
|
|
|
|
|
|
|
$Bot::BasicBot::VERSION = '0.93'; |
4
|
2
|
|
|
2
|
|
118221
|
use strict; |
|
2
|
|
|
|
|
14
|
|
|
2
|
|
|
|
|
92
|
|
5
|
2
|
|
|
2
|
|
10
|
use warnings; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
40
|
|
6
|
|
|
|
|
|
|
|
7
|
2
|
|
|
2
|
|
9
|
use Carp; |
|
2
|
|
|
|
|
11
|
|
|
2
|
|
|
|
|
127
|
|
8
|
2
|
|
|
2
|
|
982
|
use Encode qw(encode); |
|
2
|
|
|
|
|
17800
|
|
|
2
|
|
|
|
|
114
|
|
9
|
2
|
|
|
2
|
|
13
|
use Exporter; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
59
|
|
10
|
2
|
|
|
2
|
|
917
|
use IRC::Utils qw(decode_irc); |
|
2
|
|
|
|
|
15119
|
|
|
2
|
|
|
|
|
132
|
|
11
|
2
|
|
|
2
|
|
1777
|
use POE::Kernel; |
|
2
|
|
|
|
|
101543
|
|
|
2
|
|
|
|
|
12
|
|
12
|
2
|
|
|
2
|
|
62695
|
use POE::Session; |
|
2
|
|
|
|
|
7117
|
|
|
2
|
|
|
|
|
12
|
|
13
|
2
|
|
|
2
|
|
1429
|
use POE::Wheel::Run; |
|
2
|
|
|
|
|
36820
|
|
|
2
|
|
|
|
|
62
|
|
14
|
2
|
|
|
2
|
|
18
|
use POE::Filter::Line; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
49
|
|
15
|
2
|
|
|
2
|
|
1204
|
use POE::Component::IRC::State; |
|
2
|
|
|
|
|
224167
|
|
|
2
|
|
|
|
|
210
|
|
16
|
2
|
|
|
2
|
|
1032
|
use POE::Component::IRC::Plugin::Connector; |
|
2
|
|
|
|
|
4090
|
|
|
2
|
|
|
|
|
65
|
|
17
|
2
|
|
|
2
|
|
1022
|
use Text::Wrap (); |
|
2
|
|
|
|
|
4984
|
|
|
2
|
|
|
|
|
48
|
|
18
|
|
|
|
|
|
|
|
19
|
2
|
|
|
2
|
|
14
|
use base 'Exporter'; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
10169
|
|
20
|
|
|
|
|
|
|
our @EXPORT = qw(say emote); |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub new { |
23
|
0
|
|
|
0
|
1
|
|
my $class = shift; |
24
|
0
|
|
|
|
|
|
my $self = bless {}, $class; |
25
|
|
|
|
|
|
|
|
26
|
0
|
|
|
|
|
|
$self->{IRCNAME} = 'wanna'.int(rand(100000)); |
27
|
0
|
|
|
|
|
|
$self->{ALIASNAME} = 'pony'.int(rand(100000)); |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
# call the set methods |
30
|
0
|
|
|
|
|
|
my %args = @_; |
31
|
0
|
|
|
|
|
|
for my $method (keys %args) { |
32
|
0
|
0
|
|
|
|
|
if ($self->can($method)) { |
33
|
0
|
|
|
|
|
|
$self->$method($args{$method}); |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
else { |
36
|
0
|
|
|
|
|
|
$self->{$method} = $args{$method}; |
37
|
|
|
|
|
|
|
#croak "Invalid argument '$method'"; |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
} |
40
|
0
|
0
|
|
|
|
|
$self->{charset} = 'utf8' if !defined $self->{charset}; |
41
|
|
|
|
|
|
|
|
42
|
0
|
0
|
|
|
|
|
$self->init or die "init did not return a true value - dying"; |
43
|
|
|
|
|
|
|
|
44
|
0
|
|
|
|
|
|
return $self; |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub run { |
48
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# create the callbacks to the object states |
51
|
0
|
|
|
|
|
|
POE::Session->create( |
52
|
|
|
|
|
|
|
object_states => [ |
53
|
|
|
|
|
|
|
$self => { |
54
|
|
|
|
|
|
|
_start => "start_state", |
55
|
|
|
|
|
|
|
die => "die_state", |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
irc_001 => "irc_001_state", |
58
|
|
|
|
|
|
|
irc_msg => "irc_said_state", |
59
|
|
|
|
|
|
|
irc_public => "irc_said_state", |
60
|
|
|
|
|
|
|
irc_ctcp_action => "irc_emoted_state", |
61
|
|
|
|
|
|
|
irc_notice => "irc_noticed_state", |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
irc_disconnected => "irc_disconnected_state", |
64
|
|
|
|
|
|
|
irc_error => "irc_error_state", |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
irc_join => "irc_chanjoin_state", |
67
|
|
|
|
|
|
|
irc_part => "irc_chanpart_state", |
68
|
|
|
|
|
|
|
irc_kick => "irc_kicked_state", |
69
|
|
|
|
|
|
|
irc_nick => "irc_nick_state", |
70
|
|
|
|
|
|
|
irc_quit => "irc_quit_state", |
71
|
|
|
|
|
|
|
irc_mode => "irc_mode_state", |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
fork_close => "fork_close_state", |
74
|
|
|
|
|
|
|
fork_error => "fork_error_state", |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
irc_366 => "names_done_state", |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
irc_332 => "topic_raw_state", |
79
|
|
|
|
|
|
|
irc_topic => "topic_state", |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
irc_shutdown => "shutdown_state", |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
irc_raw => "irc_raw_state", |
84
|
|
|
|
|
|
|
irc_raw_out => "irc_raw_out_state", |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
tick => "tick_state", |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
] |
89
|
|
|
|
|
|
|
); |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
# and say that we want to recive said messages |
92
|
0
|
|
|
|
|
|
$poe_kernel->post($self->{IRCNAME}, 'register', 'all'); |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
# run |
95
|
0
|
0
|
|
|
|
|
$poe_kernel->run() if !$self->{no_run}; |
96
|
0
|
|
|
|
|
|
return; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
|
99
|
0
|
|
|
0
|
1
|
|
sub init { return 1; } |
100
|
|
|
|
|
|
|
|
101
|
0
|
|
|
0
|
1
|
|
sub said { return } |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
sub emoted { |
104
|
0
|
|
|
0
|
1
|
|
return shift->said(@_); |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
sub noticed { |
108
|
0
|
|
|
0
|
1
|
|
return shift->said(@_); |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
0
|
|
|
0
|
1
|
|
sub chanjoin { return } |
112
|
|
|
|
|
|
|
|
113
|
0
|
|
|
0
|
1
|
|
sub chanpart { return } |
114
|
|
|
|
|
|
|
|
115
|
0
|
|
|
0
|
1
|
|
sub got_names { return } |
116
|
|
|
|
|
|
|
|
117
|
0
|
|
|
0
|
1
|
|
sub topic { return } |
118
|
|
|
|
|
|
|
|
119
|
0
|
|
|
0
|
1
|
|
sub nick_change { return } |
120
|
|
|
|
|
|
|
|
121
|
0
|
|
|
0
|
1
|
|
sub mode_change { return } |
122
|
|
|
|
|
|
|
|
123
|
0
|
|
|
0
|
1
|
|
sub kicked { return } |
124
|
|
|
|
|
|
|
|
125
|
0
|
|
|
0
|
1
|
|
sub tick { return 0; } |
126
|
|
|
|
|
|
|
|
127
|
0
|
|
|
0
|
1
|
|
sub help { return "Sorry, this bot has no interactive help." } |
128
|
|
|
|
|
|
|
|
129
|
0
|
|
|
0
|
1
|
|
sub connected { return } |
130
|
|
|
|
|
|
|
|
131
|
0
|
|
|
0
|
0
|
|
sub raw_in { return } |
132
|
0
|
|
|
0
|
0
|
|
sub raw_out { return } |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub userquit { |
135
|
0
|
|
|
0
|
1
|
|
my ($self, $mess) = @_; |
136
|
0
|
|
|
|
|
|
return; |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub schedule_tick { |
140
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
141
|
0
|
|
0
|
|
|
|
my $time = shift || 5; |
142
|
0
|
|
|
|
|
|
$poe_kernel->delay('tick', $time); |
143
|
0
|
|
|
|
|
|
return; |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub forkit { |
147
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
148
|
0
|
|
|
|
|
|
my $args; |
149
|
|
|
|
|
|
|
|
150
|
0
|
0
|
|
|
|
|
if (ref($_[0])) { |
151
|
0
|
|
|
|
|
|
$args = shift; |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
else { |
154
|
0
|
|
|
|
|
|
my %args = @_; |
155
|
0
|
|
|
|
|
|
$args = \%args; |
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
|
158
|
0
|
0
|
|
|
|
|
return if !$args->{run}; |
159
|
|
|
|
|
|
|
|
160
|
0
|
|
0
|
|
|
|
$args->{handler} = $args->{handler} || "_fork_said"; |
161
|
0
|
|
0
|
|
|
|
$args->{arguments} = $args->{arguments} || []; |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
#install a new handler in the POE kernel pointing to |
164
|
|
|
|
|
|
|
# $self->{$args{handler}} |
165
|
0
|
|
0
|
|
|
|
$poe_kernel->state( $args->{handler}, $args->{callback} || $self ); |
166
|
|
|
|
|
|
|
|
167
|
0
|
|
|
|
|
|
my $run; |
168
|
0
|
0
|
|
|
|
|
if (ref($args->{run}) =~ /^CODE/) { |
169
|
|
|
|
|
|
|
$run = sub { |
170
|
0
|
|
|
0
|
|
|
$args->{run}->($args->{body}, @{ $args->{arguments} }) |
|
0
|
|
|
|
|
|
|
171
|
0
|
|
|
|
|
|
}; |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
else { |
174
|
0
|
|
|
|
|
|
$run = $args->{run}; |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
|
177
|
0
|
|
|
|
|
|
my $wheel = POE::Wheel::Run->new( |
178
|
|
|
|
|
|
|
Program => $run, |
179
|
|
|
|
|
|
|
StdoutFilter => POE::Filter::Line->new(), |
180
|
|
|
|
|
|
|
StderrFilter => POE::Filter::Line->new(), |
181
|
|
|
|
|
|
|
StdoutEvent => "$args->{handler}", |
182
|
|
|
|
|
|
|
StderrEvent => "fork_error", |
183
|
|
|
|
|
|
|
CloseEvent => "fork_close" |
184
|
|
|
|
|
|
|
); |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
# Use a signal handler to reap dead processes |
187
|
0
|
|
|
|
|
|
$poe_kernel->sig_child($wheel->PID, "got_sigchld"); |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
# store the wheel object in our bot, so we can retrieve/delete easily |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
$self->{forks}{ $wheel->ID } = { |
192
|
|
|
|
|
|
|
wheel => $wheel, |
193
|
|
|
|
|
|
|
args => { |
194
|
|
|
|
|
|
|
channel => $args->{channel}, |
195
|
|
|
|
|
|
|
who => $args->{who}, |
196
|
|
|
|
|
|
|
address => $args->{address} |
197
|
|
|
|
|
|
|
} |
198
|
0
|
|
|
|
|
|
}; |
199
|
0
|
|
|
|
|
|
return; |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
sub _fork_said { |
203
|
0
|
|
|
0
|
|
|
my ($self, $body, $wheel_id) = @_[OBJECT, ARG0, ARG1]; |
204
|
0
|
|
|
|
|
|
chomp $body; # remove newline necessary to move data; |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
# pick up the default arguments we squirreled away earlier |
207
|
0
|
|
|
|
|
|
my $args = $self->{forks}{$wheel_id}{args}; |
208
|
0
|
|
|
|
|
|
$args->{body} = $body; |
209
|
|
|
|
|
|
|
|
210
|
0
|
|
|
|
|
|
$self->say($args); |
211
|
0
|
|
|
|
|
|
return; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
sub say { |
215
|
|
|
|
|
|
|
# If we're called without an object ref, then we're handling saying |
216
|
|
|
|
|
|
|
# stuff from inside a forked subroutine, so we'll freeze it, and toss |
217
|
|
|
|
|
|
|
# it out on STDOUT so that POE::Wheel::Run's handler can pick it up. |
218
|
0
|
0
|
|
0
|
1
|
|
if (!ref $_[0]) { |
219
|
0
|
|
|
|
|
|
print $_[0], "\n"; |
220
|
0
|
|
|
|
|
|
return 1; |
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
# Otherwise, this is a standard object method |
224
|
|
|
|
|
|
|
|
225
|
0
|
|
|
|
|
|
my $self = shift; |
226
|
0
|
|
|
|
|
|
my $args; |
227
|
0
|
0
|
|
|
|
|
if (ref $_[0]) { |
228
|
0
|
|
|
|
|
|
$args = shift; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
else { |
231
|
0
|
|
|
|
|
|
my %args = @_; |
232
|
0
|
|
|
|
|
|
$args = \%args; |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
0
|
|
|
|
|
|
my $body = $args->{body}; |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
# add the "Foo: bar" at the start |
238
|
0
|
0
|
0
|
|
|
|
if ($args->{channel} ne "msg" && defined $args->{address}) { |
239
|
0
|
|
|
|
|
|
$body = "$args->{who}: $body"; |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
# work out who we're going to send the message to |
243
|
0
|
0
|
|
|
|
|
my $who = $args->{channel} eq "msg" ? $args->{who} : $args->{channel}; |
244
|
|
|
|
|
|
|
|
245
|
0
|
0
|
0
|
|
|
|
if (!defined $who || !defined $body) { |
246
|
0
|
|
|
|
|
|
$self->log("Can't send a message without target and body\n" |
247
|
|
|
|
|
|
|
. " called from " |
248
|
|
|
|
|
|
|
. ( [caller]->[0] ) |
249
|
|
|
|
|
|
|
. " line " |
250
|
|
|
|
|
|
|
. ( [caller]->[2] ) . "\n" |
251
|
|
|
|
|
|
|
. " who = '$who'\n body = '$body'\n"); |
252
|
0
|
|
|
|
|
|
return; |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
# if we have a long body, split it up.. |
256
|
0
|
|
|
|
|
|
local $Text::Wrap::columns = 300; |
257
|
0
|
|
|
|
|
|
local $Text::Wrap::unexpand = 0; # no tabs |
258
|
0
|
|
|
|
|
|
my $wrapped = Text::Wrap::wrap('', '..', $body); # =~ m!(.{1,300})!g; |
259
|
|
|
|
|
|
|
# I think the Text::Wrap docs lie - it doesn't do anything special |
260
|
|
|
|
|
|
|
# in list context |
261
|
0
|
|
|
|
|
|
my @bodies = split /\n+/, $wrapped; |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
# Allows to override the default "PRIVMSG". Used by notice() |
264
|
|
|
|
|
|
|
my $irc_command = defined $args->{irc_command} |
265
|
0
|
0
|
0
|
|
|
|
&& $args->{irc_command} eq 'notice' |
266
|
|
|
|
|
|
|
? 'notice' |
267
|
|
|
|
|
|
|
: 'privmsg'; |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
# post an event that will send the message |
270
|
0
|
|
|
|
|
|
for my $body (@bodies) { |
271
|
0
|
|
|
|
|
|
my ($enc_who, $enc_body) = $self->charset_encode($who, $body); |
272
|
|
|
|
|
|
|
#warn "$enc_who => $enc_body\n"; |
273
|
|
|
|
|
|
|
$poe_kernel->post( |
274
|
|
|
|
|
|
|
$self->{IRCNAME}, |
275
|
0
|
|
|
|
|
|
$irc_command, |
276
|
|
|
|
|
|
|
$enc_who, |
277
|
|
|
|
|
|
|
$enc_body, |
278
|
|
|
|
|
|
|
); |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
0
|
|
|
|
|
|
return; |
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
sub emote { |
285
|
|
|
|
|
|
|
# If we're called without an object ref, then we're handling emoting |
286
|
|
|
|
|
|
|
# stuff from inside a forked subroutine, so we'll freeze it, and |
287
|
|
|
|
|
|
|
# toss it out on STDOUT so that POE::Wheel::Run's handler can pick |
288
|
|
|
|
|
|
|
# it up. |
289
|
0
|
0
|
|
0
|
1
|
|
if (!ref $_[0]) { |
290
|
0
|
|
|
|
|
|
print $_[0], "\n"; |
291
|
0
|
|
|
|
|
|
return 1; |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
# Otherwise, this is a standard object method |
295
|
|
|
|
|
|
|
|
296
|
0
|
|
|
|
|
|
my $self = shift; |
297
|
0
|
|
|
|
|
|
my $args; |
298
|
0
|
0
|
|
|
|
|
if (ref $_[0]) { |
299
|
0
|
|
|
|
|
|
$args = shift; |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
else { |
302
|
0
|
|
|
|
|
|
my %args = @_; |
303
|
0
|
|
|
|
|
|
$args = \%args; |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
|
306
|
0
|
|
|
|
|
|
my $body = $args->{body}; |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
# Work out who we're going to send the message to |
309
|
|
|
|
|
|
|
my $who = $args->{channel} eq "msg" |
310
|
|
|
|
|
|
|
? $args->{who} |
311
|
0
|
0
|
|
|
|
|
: $args->{channel}; |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
# post an event that will send the message |
314
|
|
|
|
|
|
|
# if there's a better way of sending actions i'd love to know - jw |
315
|
|
|
|
|
|
|
# me too; i'll look at it in v0.5 - sb |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
$poe_kernel->post( |
318
|
|
|
|
|
|
|
$self->{IRCNAME}, |
319
|
0
|
|
|
|
|
|
'ctcp', |
320
|
|
|
|
|
|
|
$self->charset_encode($who, "ACTION $body"), |
321
|
|
|
|
|
|
|
); |
322
|
0
|
|
|
|
|
|
return; |
323
|
|
|
|
|
|
|
} |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
sub notice { |
326
|
0
|
0
|
|
0
|
1
|
|
if (!ref $_[0]) { |
327
|
0
|
|
|
|
|
|
print $_[0], "\n"; |
328
|
0
|
|
|
|
|
|
return 1; |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
|
331
|
0
|
|
|
|
|
|
my $self = shift; |
332
|
0
|
|
|
|
|
|
my $args; |
333
|
0
|
0
|
|
|
|
|
if (ref $_[0]) { |
334
|
0
|
|
|
|
|
|
$args = shift; |
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
else { |
337
|
0
|
|
|
|
|
|
my %args = @_; |
338
|
0
|
|
|
|
|
|
$args = \%args; |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
# Don't modify '$args' hashref in-place, or we might |
342
|
|
|
|
|
|
|
# make all subsequent calls into notices |
343
|
|
|
|
|
|
|
return $self->say( |
344
|
0
|
|
|
|
|
|
%{ $args }, |
|
0
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
irc_command => 'notice' |
346
|
|
|
|
|
|
|
); |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
sub pocoirc { |
351
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
352
|
0
|
|
|
|
|
|
return $self->{IRCOBJ}; |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
sub reply { |
356
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
357
|
0
|
|
|
|
|
|
my ($mess, $body) = @_; |
358
|
0
|
|
|
|
|
|
my %hash = %$mess; |
359
|
0
|
|
|
|
|
|
$hash{body} = $body; |
360
|
0
|
|
|
|
|
|
return $self->say(%hash); |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
sub channel_data { |
364
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
365
|
0
|
0
|
|
|
|
|
my $channel = shift or return; |
366
|
0
|
|
|
|
|
|
my $irc = $self->{IRCOBJ}; |
367
|
0
|
|
|
|
|
|
my $channels = $irc->channels(); |
368
|
0
|
0
|
|
|
|
|
return if !exists $channels->{$channel}; |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
return { |
371
|
|
|
|
|
|
|
map { |
372
|
0
|
|
0
|
|
|
|
$_ => { |
|
0
|
|
0
|
|
|
|
|
373
|
|
|
|
|
|
|
op => $irc->is_channel_operator($channel, $_) || 0, |
374
|
|
|
|
|
|
|
voice => $irc->has_channel_voice($channel, $_) || 0, |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
} $irc->channel_list($channel) |
377
|
|
|
|
|
|
|
}; |
378
|
|
|
|
|
|
|
} |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
sub server { |
381
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
382
|
0
|
0
|
|
|
|
|
$self->{server} = shift if @_; |
383
|
0
|
|
0
|
|
|
|
return $self->{server} || "irc.perl.org"; |
384
|
|
|
|
|
|
|
} |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
sub port { |
387
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
388
|
0
|
0
|
|
|
|
|
$self->{port} = shift if @_; |
389
|
0
|
|
0
|
|
|
|
return $self->{port} || "6667"; |
390
|
|
|
|
|
|
|
} |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
sub password { |
393
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
394
|
0
|
0
|
|
|
|
|
$self->{password} = shift if @_; |
395
|
0
|
|
0
|
|
|
|
return $self->{password} || undef; |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
sub ssl { |
399
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
400
|
0
|
0
|
|
|
|
|
$self->{ssl} = shift if @_; |
401
|
0
|
|
0
|
|
|
|
return $self->{ssl} || 0; |
402
|
|
|
|
|
|
|
} |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
sub localaddr { |
405
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
406
|
0
|
0
|
|
|
|
|
$self->{localaddr} = shift if @_; |
407
|
0
|
|
0
|
|
|
|
return $self->{localaddr} || 0; |
408
|
|
|
|
|
|
|
} |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
sub useipv6 { |
411
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
412
|
0
|
0
|
|
|
|
|
$self->{useipv6} = shift if @_; |
413
|
0
|
|
0
|
|
|
|
return $self->{useipv6} || 0; |
414
|
|
|
|
|
|
|
} |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
sub nick { |
417
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
418
|
0
|
0
|
|
|
|
|
$self->{nick} = shift if @_; |
419
|
0
|
0
|
|
|
|
|
return $self->{nick} if defined $self->{nick}; |
420
|
0
|
|
|
|
|
|
return _random_nick(); |
421
|
|
|
|
|
|
|
} |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
sub _random_nick { |
424
|
0
|
|
|
0
|
|
|
my @things = ( 'a' .. 'z' ); |
425
|
0
|
|
|
|
|
|
return join '', ( map { @things[ rand @things ] } 0 .. 4 ), "bot"; |
|
0
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
} |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
sub alt_nicks { |
429
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
430
|
0
|
0
|
|
|
|
|
if (@_) { |
431
|
|
|
|
|
|
|
# make sure we copy |
432
|
0
|
0
|
|
|
|
|
my @args = ( ref $_[0] eq "ARRAY" ) ? @{ $_[0] } : @_; |
|
0
|
|
|
|
|
|
|
433
|
0
|
|
|
|
|
|
$self->{alt_nicks} = \@args; |
434
|
|
|
|
|
|
|
} |
435
|
0
|
0
|
|
|
|
|
return @{ $self->{alt_nicks} || [] }; |
|
0
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
} |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
sub username { |
439
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
440
|
0
|
0
|
|
|
|
|
$self->{username} = shift if @_; |
441
|
0
|
0
|
|
|
|
|
return defined $self->{username} ? $self->{username} : $self->nick; |
442
|
|
|
|
|
|
|
} |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
sub name { |
445
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
446
|
0
|
0
|
|
|
|
|
$self->{name} = shift if @_; |
447
|
0
|
0
|
|
|
|
|
return defined $self->{name} ? $self->{name} : $self->nick . " bot"; |
448
|
|
|
|
|
|
|
} |
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
sub channels { |
451
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
452
|
0
|
0
|
|
|
|
|
if (@_) { |
453
|
|
|
|
|
|
|
# make sure we copy |
454
|
0
|
0
|
|
|
|
|
my @args = ( ref $_[0] eq "ARRAY" ) ? @{ $_[0] } : @_; |
|
0
|
|
|
|
|
|
|
455
|
0
|
|
|
|
|
|
$self->{channels} = \@args; |
456
|
|
|
|
|
|
|
} |
457
|
0
|
0
|
|
|
|
|
return @{ $self->{channels} || [] }; |
|
0
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
sub quit_message { |
461
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
462
|
0
|
0
|
|
|
|
|
$self->{quit_message} = shift if @_; |
463
|
0
|
0
|
|
|
|
|
return defined $self->{quit_message} ? $self->{quit_message} : "Bye"; |
464
|
|
|
|
|
|
|
} |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
sub ignore_list { |
467
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
468
|
0
|
0
|
|
|
|
|
if (@_) { |
469
|
|
|
|
|
|
|
# make sure we copy |
470
|
0
|
0
|
|
|
|
|
my @args = ( ref $_[0] eq "ARRAY" ) ? @{ $_[0] } : @_; |
|
0
|
|
|
|
|
|
|
471
|
0
|
|
|
|
|
|
$self->{ignore_list} = \@args; |
472
|
|
|
|
|
|
|
} |
473
|
0
|
0
|
|
|
|
|
return @{ $self->{ignore_list} || [] }; |
|
0
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
} |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
sub charset { |
477
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
478
|
0
|
0
|
|
|
|
|
if (@_) { |
479
|
0
|
|
|
|
|
|
$self->{charset} = shift; |
480
|
|
|
|
|
|
|
} |
481
|
0
|
|
|
|
|
|
return $self->{charset}; |
482
|
|
|
|
|
|
|
} |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
sub flood { |
485
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
486
|
0
|
0
|
|
|
|
|
$self->{flood} = shift if @_; |
487
|
0
|
|
|
|
|
|
return $self->{flood}; |
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
sub no_run { |
491
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
492
|
0
|
0
|
|
|
|
|
$self->{no_run} = shift if @_; |
493
|
0
|
|
|
|
|
|
return $self->{no_run}; |
494
|
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
sub webirc { |
497
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
498
|
0
|
0
|
|
|
|
|
$self->{webirc} = shift if @_; |
499
|
0
|
|
|
|
|
|
return $self->{webirc}; |
500
|
|
|
|
|
|
|
} |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
sub start_state { |
503
|
0
|
|
|
0
|
0
|
|
my ($self, $kernel, $session) = @_[OBJECT, KERNEL, SESSION]; |
504
|
0
|
|
|
|
|
|
$kernel->sig('DIE', 'die'); |
505
|
0
|
|
|
|
|
|
$self->{session} = $session; |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
# Make an alias for our session, to keep it from getting GC'ed. |
508
|
0
|
|
|
|
|
|
$kernel->alias_set($self->{ALIASNAME}); |
509
|
0
|
|
|
|
|
|
$kernel->delay('tick', 30); |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
$self->{IRCOBJ} = POE::Component::IRC::State->spawn( |
512
|
|
|
|
|
|
|
alias => $self->{IRCNAME}, |
513
|
0
|
|
|
|
|
|
); |
514
|
|
|
|
|
|
|
$self->{IRCOBJ}->plugin_add( |
515
|
0
|
|
|
|
|
|
'Connector', |
516
|
|
|
|
|
|
|
POE::Component::IRC::Plugin::Connector->new(), |
517
|
|
|
|
|
|
|
); |
518
|
0
|
|
|
|
|
|
$kernel->post($self->{IRCNAME}, 'register', 'all'); |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
$kernel->post( |
521
|
|
|
|
|
|
|
$self->{IRCNAME}, |
522
|
0
|
|
|
|
|
|
'connect', |
523
|
|
|
|
|
|
|
{ |
524
|
|
|
|
|
|
|
Nick => $self->nick, |
525
|
|
|
|
|
|
|
Server => $self->server, |
526
|
|
|
|
|
|
|
Port => $self->port, |
527
|
|
|
|
|
|
|
Password => $self->password, |
528
|
|
|
|
|
|
|
UseSSL => $self->ssl, |
529
|
|
|
|
|
|
|
Flood => $self->flood, |
530
|
|
|
|
|
|
|
LocalAddr => $self->localaddr, |
531
|
|
|
|
|
|
|
useipv6 => $self->useipv6, |
532
|
|
|
|
|
|
|
webirc => $self->webirc, |
533
|
|
|
|
|
|
|
$self->charset_encode( |
534
|
|
|
|
|
|
|
Nick => $self->nick, |
535
|
|
|
|
|
|
|
Username => $self->username, |
536
|
|
|
|
|
|
|
Ircname => $self->name, |
537
|
|
|
|
|
|
|
), |
538
|
|
|
|
|
|
|
}, |
539
|
|
|
|
|
|
|
); |
540
|
|
|
|
|
|
|
|
541
|
0
|
|
|
|
|
|
return; |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
sub die_state { |
545
|
0
|
|
|
0
|
0
|
|
my ($kernel, $self, $ex) = @_[KERNEL, OBJECT, ARG1]; |
546
|
0
|
|
|
|
|
|
warn $ex->{error_str}; |
547
|
0
|
|
|
|
|
|
$self->{IRCOBJ}->yield('shutdown'); |
548
|
0
|
|
|
|
|
|
$kernel->sig_handled(); |
549
|
0
|
|
|
|
|
|
return; |
550
|
|
|
|
|
|
|
} |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
sub irc_001_state { |
553
|
0
|
|
|
0
|
0
|
|
my ($self, $kernel) = @_[OBJECT, KERNEL]; |
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
# ignore all messages from ourselves |
556
|
|
|
|
|
|
|
$kernel->post( |
557
|
|
|
|
|
|
|
$self->{IRCNAME}, |
558
|
0
|
|
|
|
|
|
'ignore', |
559
|
|
|
|
|
|
|
$self->charset_encode($self->nick), |
560
|
|
|
|
|
|
|
); |
561
|
|
|
|
|
|
|
|
562
|
0
|
|
|
|
|
|
$self->log("Connected to " . $self->server); |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
# connect to the channel |
565
|
0
|
|
|
|
|
|
for my $channel ($self->channels) { |
566
|
0
|
|
|
|
|
|
$self->log("Trying to join '$channel'\n"); |
567
|
|
|
|
|
|
|
$kernel->post( |
568
|
|
|
|
|
|
|
$self->{IRCNAME}, |
569
|
0
|
|
|
|
|
|
'join', |
570
|
|
|
|
|
|
|
$self->charset_encode($channel), |
571
|
|
|
|
|
|
|
); |
572
|
|
|
|
|
|
|
} |
573
|
|
|
|
|
|
|
|
574
|
0
|
|
|
|
|
|
$self->schedule_tick(5); |
575
|
0
|
|
|
|
|
|
$self->connected(); |
576
|
0
|
|
|
|
|
|
return; |
577
|
|
|
|
|
|
|
} |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
sub irc_disconnected_state { |
580
|
0
|
|
|
0
|
0
|
|
my ($self, $kernel, $server) = @_[OBJECT, KERNEL, ARG0]; |
581
|
0
|
|
|
|
|
|
$self->log("Lost connection to server $server.\n"); |
582
|
0
|
|
|
|
|
|
return; |
583
|
|
|
|
|
|
|
} |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
sub irc_error_state { |
586
|
0
|
|
|
0
|
0
|
|
my ($self, $err, $kernel) = @_[OBJECT, ARG0, KERNEL]; |
587
|
0
|
|
|
|
|
|
$self->log("Server error occurred! $err\n"); |
588
|
0
|
|
|
|
|
|
return; |
589
|
|
|
|
|
|
|
} |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
sub irc_kicked_state { |
592
|
0
|
|
|
0
|
0
|
|
my ($self, $kernel, $heap, $session) = @_[OBJECT, KERNEL, HEAP, SESSION]; |
593
|
0
|
|
|
|
|
|
my ($nickstring, $channel, $kicked, $reason) = @_[ARG0..$#_]; |
594
|
0
|
|
|
|
|
|
my $nick = $self->nick_strip($nickstring); |
595
|
0
|
|
|
|
|
|
$_[OBJECT]->_remove_from_channel( $channel, $kicked ); |
596
|
0
|
|
|
|
|
|
$self->kicked( |
597
|
|
|
|
|
|
|
{ |
598
|
|
|
|
|
|
|
channel => $channel, |
599
|
|
|
|
|
|
|
who => $nick, |
600
|
|
|
|
|
|
|
kicked => $kicked, |
601
|
|
|
|
|
|
|
reason => $reason, |
602
|
|
|
|
|
|
|
} |
603
|
|
|
|
|
|
|
); |
604
|
0
|
|
|
|
|
|
return; |
605
|
|
|
|
|
|
|
} |
606
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
sub irc_join_state { |
608
|
0
|
|
|
0
|
0
|
|
my ($self, $nick) = @_[OBJECT, ARG0]; |
609
|
0
|
|
|
|
|
|
return; |
610
|
|
|
|
|
|
|
} |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
sub irc_nick_state { |
613
|
0
|
|
|
0
|
0
|
|
my ($self, $nick, $newnick) = @_[OBJECT, ARG0, ARG1]; |
614
|
0
|
|
|
|
|
|
$nick = $self->nick_strip($nick); |
615
|
0
|
|
|
|
|
|
$self->nick_change($nick, $newnick); |
616
|
0
|
|
|
|
|
|
return; |
617
|
|
|
|
|
|
|
} |
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
sub irc_mode_state { |
620
|
0
|
|
|
0
|
0
|
|
my ($self, $nick, $channel, $mode_changes) = @_[OBJECT, ARG0, ARG1, ARG2]; |
621
|
0
|
|
|
|
|
|
my @mode_operands = @_[ARG3..$#_]; |
622
|
0
|
|
|
|
|
|
$self->mode_change( |
623
|
|
|
|
|
|
|
{ |
624
|
|
|
|
|
|
|
channel => $channel, |
625
|
|
|
|
|
|
|
who => $self->nick_strip($nick), |
626
|
|
|
|
|
|
|
mode_changes => $mode_changes, |
627
|
|
|
|
|
|
|
mode_operands => \@mode_operands, |
628
|
|
|
|
|
|
|
} |
629
|
|
|
|
|
|
|
); |
630
|
0
|
|
|
|
|
|
return; |
631
|
|
|
|
|
|
|
} |
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
sub irc_quit_state { |
634
|
0
|
|
|
0
|
0
|
|
my ($self, $kernel, $session) = @_[OBJECT, KERNEL, SESSION]; |
635
|
0
|
|
|
|
|
|
my ($nick, $message) = @_[ARG0..$#_]; |
636
|
|
|
|
|
|
|
|
637
|
0
|
|
|
|
|
|
$nick = $self->nick_strip($nick); |
638
|
0
|
|
|
|
|
|
$self->userquit({ who => $nick, body => $message }); |
639
|
0
|
|
|
|
|
|
return; |
640
|
|
|
|
|
|
|
} |
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
sub irc_said_state { |
643
|
0
|
|
|
0
|
0
|
|
irc_received_state( 'said', 'say', @_ ); |
644
|
0
|
|
|
|
|
|
return; |
645
|
|
|
|
|
|
|
} |
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
sub irc_emoted_state { |
648
|
0
|
|
|
0
|
0
|
|
irc_received_state( 'emoted', 'emote', @_ ); |
649
|
0
|
|
|
|
|
|
return; |
650
|
|
|
|
|
|
|
} |
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
sub irc_noticed_state { |
653
|
0
|
|
|
0
|
0
|
|
irc_received_state( 'noticed', 'emote', @_ ); |
654
|
0
|
|
|
|
|
|
return; |
655
|
|
|
|
|
|
|
} |
656
|
|
|
|
|
|
|
|
657
|
|
|
|
|
|
|
sub irc_received_state { |
658
|
0
|
|
|
0
|
0
|
|
my $received = shift; |
659
|
0
|
|
|
|
|
|
my $respond = shift; |
660
|
0
|
|
|
|
|
|
my ($self, $nick, $to, $body) = @_[OBJECT, ARG0, ARG1, ARG2]; |
661
|
|
|
|
|
|
|
|
662
|
0
|
|
|
|
|
|
($nick, $to, $body) = $self->charset_decode($nick, $to, $body); |
663
|
|
|
|
|
|
|
|
664
|
0
|
|
|
|
|
|
my $return; |
665
|
0
|
|
|
|
|
|
my $mess = {}; |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
# pass the raw body through |
668
|
0
|
|
|
|
|
|
$mess->{raw_body} = $body; |
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
# work out who it was from |
671
|
0
|
|
|
|
|
|
$mess->{who} = $self->nick_strip($nick); |
672
|
0
|
|
|
|
|
|
$mess->{raw_nick} = $nick; |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
# right, get the list of places this message was |
675
|
|
|
|
|
|
|
# sent to and work out the first one that we're |
676
|
|
|
|
|
|
|
# either a memeber of is is our nick. |
677
|
|
|
|
|
|
|
# The IRC protocol allows messages to be sent to multiple |
678
|
|
|
|
|
|
|
# targets, which is pretty clever. However, noone actually |
679
|
|
|
|
|
|
|
# /does/ this, so we can get away with this: |
680
|
|
|
|
|
|
|
|
681
|
0
|
|
|
|
|
|
my $channel = $to->[0]; |
682
|
0
|
0
|
|
|
|
|
if (lc($channel) eq lc($self->nick)) { |
683
|
0
|
|
|
|
|
|
$mess->{channel} = "msg"; |
684
|
0
|
|
|
|
|
|
$mess->{address} = "msg"; |
685
|
|
|
|
|
|
|
} |
686
|
|
|
|
|
|
|
else { |
687
|
0
|
|
|
|
|
|
$mess->{channel} = $channel; |
688
|
|
|
|
|
|
|
} |
689
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
# okay, work out if we're addressed or not |
691
|
|
|
|
|
|
|
|
692
|
0
|
|
|
|
|
|
$mess->{body} = $body; |
693
|
0
|
0
|
|
|
|
|
if ($mess->{channel} ne "msg") { |
694
|
0
|
|
|
|
|
|
my $own_nick = $self->nick; |
695
|
|
|
|
|
|
|
|
696
|
0
|
0
|
|
|
|
|
if ($mess->{body} =~ s/^(\Q$own_nick\E)\s*[:,-]?\s*//i) { |
697
|
0
|
|
|
|
|
|
$mess->{address} = $1; |
698
|
|
|
|
|
|
|
} |
699
|
|
|
|
|
|
|
|
700
|
0
|
|
|
|
|
|
for my $alt_nick ($self->alt_nicks) { |
701
|
0
|
0
|
|
|
|
|
last if $mess->{address}; |
702
|
0
|
0
|
|
|
|
|
if ($mess->{body} =~ s/^(\Q$alt_nick\E)\s*[:,-]?\s*//i) { |
703
|
0
|
|
|
|
|
|
$mess->{address} = $1; |
704
|
|
|
|
|
|
|
} |
705
|
|
|
|
|
|
|
} |
706
|
|
|
|
|
|
|
} |
707
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
# strip off whitespace before and after the message |
709
|
0
|
|
|
|
|
|
$mess->{body} =~ s/^\s+//; |
710
|
0
|
|
|
|
|
|
$mess->{body} =~ s/\s+$//; |
711
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
# check if someone was asking for help |
713
|
0
|
0
|
0
|
|
|
|
if ($mess->{address} && $mess->{body} =~ /^help/i) { |
714
|
0
|
0
|
|
|
|
|
$mess->{body} = $self->help($mess) or return; |
715
|
0
|
|
|
|
|
|
$self->say($mess); |
716
|
0
|
|
|
|
|
|
return; |
717
|
|
|
|
|
|
|
} |
718
|
|
|
|
|
|
|
|
719
|
|
|
|
|
|
|
# okay, call the said/emoted method |
720
|
0
|
|
|
|
|
|
$return = $self->$received($mess); |
721
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
### what did we get back? |
723
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
# nothing? Say nothing then |
725
|
0
|
0
|
|
|
|
|
return if !defined $return; |
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
# a string? Say it how we were addressed then |
728
|
0
|
0
|
0
|
|
|
|
if (!ref $return && length $return) { |
729
|
0
|
|
|
|
|
|
$mess->{body} = $return; |
730
|
0
|
|
|
|
|
|
$self->$respond($mess); |
731
|
0
|
|
|
|
|
|
return; |
732
|
|
|
|
|
|
|
} |
733
|
|
|
|
|
|
|
} |
734
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
sub irc_chanjoin_state { |
736
|
0
|
|
|
0
|
0
|
|
my $self = $_[OBJECT]; |
737
|
0
|
|
|
|
|
|
my ($channel, $nick) = @_[ ARG1, ARG0 ]; |
738
|
0
|
|
|
|
|
|
$nick = $_[OBJECT]->nick_strip($nick); |
739
|
|
|
|
|
|
|
|
740
|
0
|
0
|
|
|
|
|
if ($self->nick eq $nick) { |
741
|
0
|
|
|
|
|
|
my @channels = $self->channels; |
742
|
0
|
0
|
|
|
|
|
push @channels, $channel unless grep { $_ eq $channel } @channels; |
|
0
|
|
|
|
|
|
|
743
|
0
|
|
|
|
|
|
$self->channels(\@channels); |
744
|
|
|
|
|
|
|
} |
745
|
0
|
|
|
|
|
|
irc_chan_received_state('chanjoin', 'say', @_); |
746
|
0
|
|
|
|
|
|
return; |
747
|
|
|
|
|
|
|
} |
748
|
|
|
|
|
|
|
|
749
|
|
|
|
|
|
|
sub irc_chanpart_state { |
750
|
0
|
|
|
0
|
0
|
|
my $self = $_[OBJECT]; |
751
|
0
|
|
|
|
|
|
my ($channel, $nick) = @_[ ARG1, ARG0 ]; |
752
|
0
|
|
|
|
|
|
$nick = $_[OBJECT]->nick_strip($nick); |
753
|
|
|
|
|
|
|
|
754
|
0
|
0
|
|
|
|
|
if ($self->nick eq $nick) { |
755
|
0
|
|
|
|
|
|
my @channels = $self->channels; |
756
|
0
|
|
|
|
|
|
@channels = grep { $_ ne $channel } @channels; |
|
0
|
|
|
|
|
|
|
757
|
0
|
|
|
|
|
|
$self->channels(\@channels); |
758
|
|
|
|
|
|
|
} |
759
|
0
|
|
|
|
|
|
irc_chan_received_state('chanpart', 'say', @_); |
760
|
0
|
|
|
|
|
|
return; |
761
|
|
|
|
|
|
|
} |
762
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
sub irc_chan_received_state { |
764
|
0
|
|
|
0
|
0
|
|
my $received = shift; |
765
|
0
|
|
|
|
|
|
my $respond = shift; |
766
|
0
|
|
|
|
|
|
my ($self, $nick, $channel) = @_[OBJECT, ARG0, ARG1]; |
767
|
|
|
|
|
|
|
|
768
|
0
|
|
|
|
|
|
my $return; |
769
|
0
|
|
|
|
|
|
my $mess = {}; |
770
|
0
|
|
|
|
|
|
$mess->{who} = $self->nick_strip($nick); |
771
|
0
|
|
|
|
|
|
$mess->{raw_nick} = $nick; |
772
|
|
|
|
|
|
|
|
773
|
0
|
|
|
|
|
|
$mess->{channel} = $channel; |
774
|
0
|
|
|
|
|
|
$mess->{body} = $received; #chanjoin or chanpart |
775
|
0
|
|
|
|
|
|
$mess->{address} = "chan"; |
776
|
|
|
|
|
|
|
|
777
|
|
|
|
|
|
|
# okay, call the chanjoin/chanpart method |
778
|
0
|
|
|
|
|
|
$return = $self->$received($mess); |
779
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
### what did we get back? |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
# nothing? Say nothing then |
783
|
0
|
0
|
|
|
|
|
return if !defined $return; |
784
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
# a string? Say it how we were addressed then |
786
|
0
|
0
|
|
|
|
|
if (!ref $return) { |
787
|
0
|
|
|
|
|
|
$mess->{body} = $return; |
788
|
0
|
|
|
|
|
|
$self->$respond($mess); |
789
|
0
|
|
|
|
|
|
return; |
790
|
|
|
|
|
|
|
} |
791
|
|
|
|
|
|
|
} |
792
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
sub fork_close_state { |
795
|
0
|
|
|
0
|
0
|
|
my ($self, $wheel_id) = @_[OBJECT, ARG0]; |
796
|
0
|
|
|
|
|
|
delete $self->{forks}{$wheel_id}; |
797
|
0
|
|
|
|
|
|
return; |
798
|
|
|
|
|
|
|
} |
799
|
|
|
|
|
|
|
|
800
|
|
|
|
0
|
0
|
|
sub fork_error_state { } |
801
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
sub tick_state { |
803
|
0
|
|
|
0
|
0
|
|
my ($self, $kernel, $heap) = @_[OBJECT, KERNEL, HEAP]; |
804
|
0
|
|
|
|
|
|
my $delay = $self->tick(); |
805
|
0
|
0
|
|
|
|
|
$self->schedule_tick($delay) if $delay; |
806
|
0
|
|
|
|
|
|
return; |
807
|
|
|
|
|
|
|
} |
808
|
|
|
|
|
|
|
|
809
|
|
|
|
|
|
|
sub names_done_state { |
810
|
0
|
|
|
0
|
0
|
|
my ($self, $kernel, $server, $message) = @_[OBJECT, KERNEL, ARG0, ARG1]; |
811
|
0
|
|
|
|
|
|
my ($channel) = split /\s/, $message; |
812
|
0
|
|
|
|
|
|
$self->got_names( |
813
|
|
|
|
|
|
|
{ |
814
|
|
|
|
|
|
|
channel => $channel, |
815
|
|
|
|
|
|
|
names => $self->channel_data($channel), |
816
|
|
|
|
|
|
|
} |
817
|
|
|
|
|
|
|
); |
818
|
0
|
|
|
|
|
|
return; |
819
|
|
|
|
|
|
|
} |
820
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
sub topic_raw_state { |
822
|
0
|
|
|
0
|
0
|
|
my ($self, $kernel, $server, $raw) = @_[OBJECT, KERNEL, ARG0, ARG1]; |
823
|
0
|
|
|
|
|
|
my ($channel, $topic) = split / :/, $raw, 2; |
824
|
0
|
|
|
|
|
|
$self->topic( |
825
|
|
|
|
|
|
|
{ |
826
|
|
|
|
|
|
|
channel => $channel, |
827
|
|
|
|
|
|
|
who => undef, |
828
|
|
|
|
|
|
|
topic => $topic, |
829
|
|
|
|
|
|
|
} |
830
|
|
|
|
|
|
|
); |
831
|
0
|
|
|
|
|
|
return; |
832
|
|
|
|
|
|
|
} |
833
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
sub topic_state { |
835
|
0
|
|
|
0
|
0
|
|
my ($self, $kernel, $nickraw, $channel, $topic) |
836
|
|
|
|
|
|
|
= @_[OBJECT, KERNEL, ARG0, ARG1, ARG2]; |
837
|
0
|
|
|
|
|
|
my $nick = $self->nick_strip($nickraw); |
838
|
0
|
|
|
|
|
|
$self->topic( |
839
|
|
|
|
|
|
|
{ |
840
|
|
|
|
|
|
|
channel => $channel, |
841
|
|
|
|
|
|
|
who => $nick, |
842
|
|
|
|
|
|
|
topic => $topic, |
843
|
|
|
|
|
|
|
} |
844
|
|
|
|
|
|
|
); |
845
|
0
|
|
|
|
|
|
return; |
846
|
|
|
|
|
|
|
} |
847
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
sub shutdown_state { |
849
|
0
|
|
|
0
|
0
|
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
850
|
0
|
|
|
|
|
|
$kernel->delay('tick'); |
851
|
0
|
|
|
|
|
|
$kernel->alias_remove($self->{ALIASNAME}); |
852
|
0
|
|
|
|
|
|
for my $fork (values %{ $self->{forks} }) { |
|
0
|
|
|
|
|
|
|
853
|
0
|
|
|
|
|
|
$fork->{wheel}->kill(); |
854
|
|
|
|
|
|
|
} |
855
|
0
|
|
|
|
|
|
return; |
856
|
|
|
|
|
|
|
} |
857
|
|
|
|
|
|
|
|
858
|
|
|
|
|
|
|
|
859
|
|
|
|
|
|
|
sub irc_raw_state { |
860
|
0
|
|
|
0
|
0
|
|
my ($self, $kernel, $raw_line) = @_[OBJECT, KERNEL, ARG0]; |
861
|
0
|
|
|
|
|
|
$self->raw_in($raw_line); |
862
|
|
|
|
|
|
|
} |
863
|
|
|
|
|
|
|
sub irc_raw_out_state { |
864
|
0
|
|
|
0
|
0
|
|
my ($self, $kernel, $raw_line) = @_[OBJECT, KERNEL, ARG0]; |
865
|
0
|
|
|
|
|
|
$self->raw_out($raw_line); |
866
|
|
|
|
|
|
|
} |
867
|
|
|
|
|
|
|
|
868
|
|
|
|
|
|
|
|
869
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
sub AUTOLOAD { |
871
|
0
|
|
|
0
|
|
|
my $self = shift; |
872
|
0
|
|
|
|
|
|
our $AUTOLOAD; |
873
|
0
|
|
|
|
|
|
$AUTOLOAD =~ s/.*:://; |
874
|
|
|
|
|
|
|
$poe_kernel->post( |
875
|
|
|
|
|
|
|
$self->{IRCNAME}, |
876
|
0
|
|
|
|
|
|
$AUTOLOAD, |
877
|
|
|
|
|
|
|
$self->charset_encode(@_), |
878
|
|
|
|
|
|
|
); |
879
|
0
|
|
|
|
|
|
return; |
880
|
|
|
|
|
|
|
} |
881
|
|
|
|
|
|
|
|
882
|
|
|
|
|
|
|
# so it won't get AUTOLOADed |
883
|
0
|
|
|
0
|
|
|
sub DESTROY { return } |
884
|
|
|
|
|
|
|
|
885
|
|
|
|
|
|
|
sub log { |
886
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
887
|
0
|
|
|
|
|
|
for (@_) { |
888
|
0
|
|
|
|
|
|
my $log_entry = $_; |
889
|
0
|
|
|
|
|
|
chomp $log_entry; |
890
|
0
|
|
|
|
|
|
print STDERR "$log_entry\n"; |
891
|
|
|
|
|
|
|
} |
892
|
0
|
|
|
|
|
|
return; |
893
|
|
|
|
|
|
|
} |
894
|
|
|
|
|
|
|
|
895
|
|
|
|
|
|
|
sub ignore_nick { |
896
|
0
|
|
|
0
|
1
|
|
local $_ = undef; |
897
|
0
|
|
|
|
|
|
my $self = shift; |
898
|
0
|
|
|
|
|
|
my $nick = shift; |
899
|
0
|
|
|
|
|
|
return grep { $nick eq $_ } @{ $self->{ignore_list} }; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
} |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
sub nick_strip { |
903
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
904
|
0
|
|
0
|
|
|
|
my $combined = shift || ""; |
905
|
0
|
|
|
|
|
|
my ($nick) = $combined =~ m/(.*?)!/; |
906
|
0
|
|
|
|
|
|
return $nick; |
907
|
|
|
|
|
|
|
} |
908
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
sub charset_decode { |
910
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
911
|
|
|
|
|
|
|
|
912
|
0
|
|
|
|
|
|
my @r; |
913
|
0
|
|
|
|
|
|
for (@_) { |
914
|
0
|
0
|
|
|
|
|
if (ref($_) eq 'ARRAY') { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
915
|
0
|
|
|
|
|
|
push @r, [ $self->charset_decode(@$_) ]; |
916
|
|
|
|
|
|
|
} |
917
|
|
|
|
|
|
|
elsif (ref($_) eq "HASH") { |
918
|
0
|
|
|
|
|
|
push @r, { $self->charset_decode(%$_) }; |
919
|
|
|
|
|
|
|
} |
920
|
|
|
|
|
|
|
elsif (ref($_)) { |
921
|
0
|
|
|
|
|
|
die "Can't decode object $_\n"; |
922
|
|
|
|
|
|
|
} |
923
|
|
|
|
|
|
|
else { |
924
|
0
|
|
|
|
|
|
push @r, decode_irc($_); |
925
|
|
|
|
|
|
|
} |
926
|
|
|
|
|
|
|
} |
927
|
|
|
|
|
|
|
#warn Dumper({ decoded => \@r }); |
928
|
0
|
|
|
|
|
|
return @r; |
929
|
|
|
|
|
|
|
} |
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
sub charset_encode { |
932
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
933
|
|
|
|
|
|
|
|
934
|
0
|
|
|
|
|
|
my @r; |
935
|
0
|
|
|
|
|
|
for (@_) { |
936
|
0
|
0
|
|
|
|
|
if (ref($_) eq 'ARRAY') { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
937
|
0
|
|
|
|
|
|
push @r, [ $self->charset_encode(@$_) ]; |
938
|
|
|
|
|
|
|
} |
939
|
|
|
|
|
|
|
elsif (ref($_) eq "HASH") { |
940
|
0
|
|
|
|
|
|
push @r, { $self->charset_encode(%$_) }; |
941
|
|
|
|
|
|
|
} |
942
|
|
|
|
|
|
|
elsif (ref($_)) { |
943
|
0
|
|
|
|
|
|
die "Can't encode object $_\n"; |
944
|
|
|
|
|
|
|
} |
945
|
|
|
|
|
|
|
else { |
946
|
0
|
|
|
|
|
|
push @r, encode($self->charset, $_); |
947
|
|
|
|
|
|
|
} |
948
|
|
|
|
|
|
|
} |
949
|
|
|
|
|
|
|
#warn Dumper({ encoded => \@r }); |
950
|
0
|
|
|
|
|
|
return @r; |
951
|
|
|
|
|
|
|
} |
952
|
|
|
|
|
|
|
|
953
|
|
|
|
|
|
|
1; |
954
|
|
|
|
|
|
|
|
955
|
|
|
|
|
|
|
=head1 NAME |
956
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
Bot::BasicBot - simple irc bot baseclass |
958
|
|
|
|
|
|
|
|
959
|
|
|
|
|
|
|
=head1 SYNOPSIS |
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
#!/usr/bin/perl |
962
|
|
|
|
|
|
|
use strict; |
963
|
|
|
|
|
|
|
use warnings; |
964
|
|
|
|
|
|
|
|
965
|
|
|
|
|
|
|
# Subclass Bot::BasicBot to provide event-handling methods. |
966
|
|
|
|
|
|
|
package UppercaseBot; |
967
|
|
|
|
|
|
|
use base qw(Bot::BasicBot); |
968
|
|
|
|
|
|
|
|
969
|
|
|
|
|
|
|
sub said { |
970
|
|
|
|
|
|
|
my $self = shift; |
971
|
|
|
|
|
|
|
my $arguments = shift; # Contains the message that the bot heard. |
972
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
# The bot will respond by uppercasing the message and echoing it back. |
974
|
|
|
|
|
|
|
$self->say( |
975
|
|
|
|
|
|
|
channel => $arguments->{channel}, |
976
|
|
|
|
|
|
|
body => uc $arguments->{body}, |
977
|
|
|
|
|
|
|
); |
978
|
|
|
|
|
|
|
|
979
|
|
|
|
|
|
|
# The bot will shut down after responding to a message. |
980
|
|
|
|
|
|
|
$self->shutdown('I have done my job here.'); |
981
|
|
|
|
|
|
|
} |
982
|
|
|
|
|
|
|
|
983
|
|
|
|
|
|
|
# Create an object of your Bot::BasicBot subclass and call its run method. |
984
|
|
|
|
|
|
|
package main; |
985
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
my $bot = UppercaseBot->new( |
987
|
|
|
|
|
|
|
server => 'irc.example.com', |
988
|
|
|
|
|
|
|
port => '6667', |
989
|
|
|
|
|
|
|
channels => ['#bottest'], |
990
|
|
|
|
|
|
|
nick => 'UppercaseBot', |
991
|
|
|
|
|
|
|
name => 'John Doe', |
992
|
|
|
|
|
|
|
ignore_list => [ 'laotse', 'georgeburdell' ], |
993
|
|
|
|
|
|
|
); |
994
|
|
|
|
|
|
|
$bot->run(); |
995
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
=head1 DESCRIPTION |
997
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
Basic bot system designed to make it easy to do simple bots, optionally |
999
|
|
|
|
|
|
|
forking longer processes (like searches) concurrently in the background. |
1000
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
There are several examples of bots using Bot::BasicBot in the examples/ |
1002
|
|
|
|
|
|
|
folder in the Bot::BasicBot tarball. |
1003
|
|
|
|
|
|
|
|
1004
|
|
|
|
|
|
|
A quick summary, though - You want to define your own package that |
1005
|
|
|
|
|
|
|
subclasses Bot::BasicBot, override various methods (documented below), |
1006
|
|
|
|
|
|
|
then call L|/new> and L|/run> on it. |
1007
|
|
|
|
|
|
|
|
1008
|
|
|
|
|
|
|
=head1 STARTING THE BOT |
1009
|
|
|
|
|
|
|
|
1010
|
|
|
|
|
|
|
=head2 C |
1011
|
|
|
|
|
|
|
|
1012
|
|
|
|
|
|
|
Creates a new instance of the class. Key/value pairs may be passed |
1013
|
|
|
|
|
|
|
which will have the same effect as calling the method of that name |
1014
|
|
|
|
|
|
|
with the value supplied. Returns a Bot::BasicBot object, that you can |
1015
|
|
|
|
|
|
|
call 'run' on later. |
1016
|
|
|
|
|
|
|
|
1017
|
|
|
|
|
|
|
eg: |
1018
|
|
|
|
|
|
|
|
1019
|
|
|
|
|
|
|
my $bot = Bot::BasicBot->new( nick => 'superbot', channels => [ '#superheroes' ] ); |
1020
|
|
|
|
|
|
|
|
1021
|
|
|
|
|
|
|
=head2 C |
1022
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
Runs the bot. Hands the control over to the POE core. |
1024
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
=head1 STOPPING THE BOT |
1026
|
|
|
|
|
|
|
|
1027
|
|
|
|
|
|
|
To shut down the bot cleanly, use the L|/shutdown> method, |
1028
|
|
|
|
|
|
|
which will (through L|/AUTOLOAD>) send an |
1029
|
|
|
|
|
|
|
L of the same name to |
1030
|
|
|
|
|
|
|
POE::Component::IRC, so it takes the same arguments: |
1031
|
|
|
|
|
|
|
|
1032
|
|
|
|
|
|
|
$bot->shutdown( $bot->quit_message() ); |
1033
|
|
|
|
|
|
|
|
1034
|
|
|
|
|
|
|
=head1 METHODS TO OVERRIDE |
1035
|
|
|
|
|
|
|
|
1036
|
|
|
|
|
|
|
In your Bot::BasicBot subclass, you want to override some of the following |
1037
|
|
|
|
|
|
|
methods to define how your bot works. These are all object methods - the |
1038
|
|
|
|
|
|
|
(implicit) first parameter to all of them will be the bot object. |
1039
|
|
|
|
|
|
|
|
1040
|
|
|
|
|
|
|
=head2 C |
1041
|
|
|
|
|
|
|
|
1042
|
|
|
|
|
|
|
called when the bot is created, as part of new(). Override to provide |
1043
|
|
|
|
|
|
|
your own init. Return a true value for a successful init, or undef if |
1044
|
|
|
|
|
|
|
you failed, in which case new() will die. |
1045
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
=head2 C |
1047
|
|
|
|
|
|
|
|
1048
|
|
|
|
|
|
|
This is the main method that you'll want to override in your subclass - |
1049
|
|
|
|
|
|
|
it's the one called by default whenever someone says anything that we |
1050
|
|
|
|
|
|
|
can hear, either in a public channel or to us in private that we |
1051
|
|
|
|
|
|
|
shouldn't ignore. |
1052
|
|
|
|
|
|
|
|
1053
|
|
|
|
|
|
|
You'll be passed a hashref that contains the arguments described below. |
1054
|
|
|
|
|
|
|
Feel free to alter the values of this hash - it won't be used later on. |
1055
|
|
|
|
|
|
|
|
1056
|
|
|
|
|
|
|
=over 4 |
1057
|
|
|
|
|
|
|
|
1058
|
|
|
|
|
|
|
=item who |
1059
|
|
|
|
|
|
|
|
1060
|
|
|
|
|
|
|
Who said it (the nick that said it) |
1061
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
=item raw_nick |
1063
|
|
|
|
|
|
|
|
1064
|
|
|
|
|
|
|
The raw IRC nick string of the person who said it. Only really useful |
1065
|
|
|
|
|
|
|
if you want more security for some reason. |
1066
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
=item channel |
1068
|
|
|
|
|
|
|
|
1069
|
|
|
|
|
|
|
The channel in which they said it. Has special value "msg" if it was in |
1070
|
|
|
|
|
|
|
a message. Actually, you can send a message to many channels at once in |
1071
|
|
|
|
|
|
|
the IRC spec, but no-one actually does this so this is just the first |
1072
|
|
|
|
|
|
|
one in the list. |
1073
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
=item body |
1075
|
|
|
|
|
|
|
|
1076
|
|
|
|
|
|
|
The body of the message (i.e. the actual text) |
1077
|
|
|
|
|
|
|
|
1078
|
|
|
|
|
|
|
=item address |
1079
|
|
|
|
|
|
|
|
1080
|
|
|
|
|
|
|
The text that indicates how we were addressed. Contains the string |
1081
|
|
|
|
|
|
|
"msg" for private messages, otherwise contains the string off the text |
1082
|
|
|
|
|
|
|
that was stripped off the front of the message if we were addressed, |
1083
|
|
|
|
|
|
|
e.g. "Nick: ". Obviously this can be simply checked for truth if you |
1084
|
|
|
|
|
|
|
just want to know if you were addressed or not. |
1085
|
|
|
|
|
|
|
|
1086
|
|
|
|
|
|
|
=back |
1087
|
|
|
|
|
|
|
|
1088
|
|
|
|
|
|
|
You should return what you want to say. This can either be a simple |
1089
|
|
|
|
|
|
|
string (which will be sent back to whoever was talking to you as a |
1090
|
|
|
|
|
|
|
message or in public depending on how they were talking) or a hashref |
1091
|
|
|
|
|
|
|
that contains values that are compatible with say (just changing |
1092
|
|
|
|
|
|
|
the body and returning the structure you were passed works very well.) |
1093
|
|
|
|
|
|
|
|
1094
|
|
|
|
|
|
|
Returning undef will cause nothing to be said. |
1095
|
|
|
|
|
|
|
|
1096
|
|
|
|
|
|
|
=head2 C |
1097
|
|
|
|
|
|
|
|
1098
|
|
|
|
|
|
|
This is a secondary method that you may wish to override. It gets called |
1099
|
|
|
|
|
|
|
when someone in channel 'emotes', instead of talking. In its default |
1100
|
|
|
|
|
|
|
configuration, it will simply pass anything emoted on channel through to |
1101
|
|
|
|
|
|
|
the C handler. |
1102
|
|
|
|
|
|
|
|
1103
|
|
|
|
|
|
|
C receives the same data hash as C. |
1104
|
|
|
|
|
|
|
|
1105
|
|
|
|
|
|
|
=head2 C |
1106
|
|
|
|
|
|
|
|
1107
|
|
|
|
|
|
|
This is like C, except for notices instead of normal messages. |
1108
|
|
|
|
|
|
|
|
1109
|
|
|
|
|
|
|
=head2 C |
1110
|
|
|
|
|
|
|
|
1111
|
|
|
|
|
|
|
Called when someone joins a channel. It receives a hashref argument |
1112
|
|
|
|
|
|
|
similar to the one received by said(). The key 'who' is the nick of the |
1113
|
|
|
|
|
|
|
user who joined, while 'channel' is the channel they joined. |
1114
|
|
|
|
|
|
|
|
1115
|
|
|
|
|
|
|
This is a do-nothing implementation, override this in your subclass. |
1116
|
|
|
|
|
|
|
|
1117
|
|
|
|
|
|
|
=head2 C |
1118
|
|
|
|
|
|
|
|
1119
|
|
|
|
|
|
|
Called when someone parts a channel. It receives a hashref argument |
1120
|
|
|
|
|
|
|
similar to the one received by said(). The key 'who' is the nick of the |
1121
|
|
|
|
|
|
|
user who parted, while 'channel' is the channel they parted. |
1122
|
|
|
|
|
|
|
|
1123
|
|
|
|
|
|
|
This is a do-nothing implementation, override this in your subclass. |
1124
|
|
|
|
|
|
|
|
1125
|
|
|
|
|
|
|
=head2 C |
1126
|
|
|
|
|
|
|
|
1127
|
|
|
|
|
|
|
Whenever we have been given a definitive list of 'who is in the channel', |
1128
|
|
|
|
|
|
|
this function will be called. It receives a hash reference as an argument. |
1129
|
|
|
|
|
|
|
The key 'channel' will be the channel we have information for, 'names' is a |
1130
|
|
|
|
|
|
|
hashref where the keys are the nicks of the users, and the values are more |
1131
|
|
|
|
|
|
|
hashes, containing the two keys 'op' and 'voice', indicating if the user is |
1132
|
|
|
|
|
|
|
a chanop or voiced respectively. |
1133
|
|
|
|
|
|
|
|
1134
|
|
|
|
|
|
|
The reply value is ignored. |
1135
|
|
|
|
|
|
|
|
1136
|
|
|
|
|
|
|
Normally, I wouldn't override this method - instead, just use the L |
1137
|
|
|
|
|
|
|
call when you want to know who's in the channel. Override this only if you |
1138
|
|
|
|
|
|
|
want to be able to do something as soon as possible. Also be aware that |
1139
|
|
|
|
|
|
|
the names list can be changed by other events - kicks, joins, etc, and this |
1140
|
|
|
|
|
|
|
method won't be called when that happens. |
1141
|
|
|
|
|
|
|
|
1142
|
|
|
|
|
|
|
=head2 C |
1143
|
|
|
|
|
|
|
|
1144
|
|
|
|
|
|
|
Called when the topic of the channel changes. It receives a hashref |
1145
|
|
|
|
|
|
|
argument. The key 'channel' is the channel the topic was set in, and 'who' |
1146
|
|
|
|
|
|
|
is the nick of the user who changed the channel, 'topic' will be the new |
1147
|
|
|
|
|
|
|
topic of the channel. |
1148
|
|
|
|
|
|
|
|
1149
|
|
|
|
|
|
|
=head2 C |
1150
|
|
|
|
|
|
|
|
1151
|
|
|
|
|
|
|
When a user changes nicks, this will be called. It receives two arguments: |
1152
|
|
|
|
|
|
|
the old nickname and the new nickname. |
1153
|
|
|
|
|
|
|
|
1154
|
|
|
|
|
|
|
=head2 C |
1155
|
|
|
|
|
|
|
|
1156
|
|
|
|
|
|
|
When a user sets channel modes, or the bot (or someone sharing its bouncer |
1157
|
|
|
|
|
|
|
connection?) sets user modes, this will be called. It receives a hashref |
1158
|
|
|
|
|
|
|
which will look like the following: |
1159
|
|
|
|
|
|
|
|
1160
|
|
|
|
|
|
|
{ |
1161
|
|
|
|
|
|
|
channel => "#channel", |
1162
|
|
|
|
|
|
|
who => "nick!user@host", |
1163
|
|
|
|
|
|
|
mode_changes => "+o+v", |
1164
|
|
|
|
|
|
|
mode_operands => ["bigpresh", "somedude"], |
1165
|
|
|
|
|
|
|
} |
1166
|
|
|
|
|
|
|
|
1167
|
|
|
|
|
|
|
=head2 C |
1168
|
|
|
|
|
|
|
|
1169
|
|
|
|
|
|
|
Called when a user is kicked from the channel. It receives a hashref which |
1170
|
|
|
|
|
|
|
will look like this: |
1171
|
|
|
|
|
|
|
|
1172
|
|
|
|
|
|
|
{ |
1173
|
|
|
|
|
|
|
channel => "#channel", |
1174
|
|
|
|
|
|
|
who => "nick", |
1175
|
|
|
|
|
|
|
kicked => "kicked", |
1176
|
|
|
|
|
|
|
reason => "reason", |
1177
|
|
|
|
|
|
|
} |
1178
|
|
|
|
|
|
|
|
1179
|
|
|
|
|
|
|
The reply value is ignored. |
1180
|
|
|
|
|
|
|
|
1181
|
|
|
|
|
|
|
=head2 C |
1182
|
|
|
|
|
|
|
|
1183
|
|
|
|
|
|
|
This is an event called every regularly. The function should return the |
1184
|
|
|
|
|
|
|
amount of time until the tick event should next be called. The default |
1185
|
|
|
|
|
|
|
tick is called 5 seconds after the bot starts, and the default |
1186
|
|
|
|
|
|
|
implementation returns '0', which disables the tick. Override this and |
1187
|
|
|
|
|
|
|
return non-zero values to have an ongoing tick event. |
1188
|
|
|
|
|
|
|
|
1189
|
|
|
|
|
|
|
Use this function if you want the bot to do something periodically, and |
1190
|
|
|
|
|
|
|
don't want to mess with 'real' POE things. |
1191
|
|
|
|
|
|
|
|
1192
|
|
|
|
|
|
|
Call the L event to schedule a tick event without waiting |
1193
|
|
|
|
|
|
|
for the next tick. |
1194
|
|
|
|
|
|
|
|
1195
|
|
|
|
|
|
|
=head2 C |
1196
|
|
|
|
|
|
|
|
1197
|
|
|
|
|
|
|
This is the other method that you should override. This is the text |
1198
|
|
|
|
|
|
|
that the bot will respond to if someone simply says help to it. This |
1199
|
|
|
|
|
|
|
should be considered a special case which you should not attempt to |
1200
|
|
|
|
|
|
|
process yourself. Saying help to a bot should have no side effects |
1201
|
|
|
|
|
|
|
whatsoever apart from returning this text. |
1202
|
|
|
|
|
|
|
|
1203
|
|
|
|
|
|
|
=head2 C |
1204
|
|
|
|
|
|
|
|
1205
|
|
|
|
|
|
|
An optional method to override, gets called after we have connected |
1206
|
|
|
|
|
|
|
to the server |
1207
|
|
|
|
|
|
|
|
1208
|
|
|
|
|
|
|
=head2 C |
1209
|
|
|
|
|
|
|
|
1210
|
|
|
|
|
|
|
Receives a hashref which will look like: |
1211
|
|
|
|
|
|
|
|
1212
|
|
|
|
|
|
|
{ |
1213
|
|
|
|
|
|
|
who => "nick that quit", |
1214
|
|
|
|
|
|
|
body => "quit message", |
1215
|
|
|
|
|
|
|
} |
1216
|
|
|
|
|
|
|
|
1217
|
|
|
|
|
|
|
=head2 C |
1218
|
|
|
|
|
|
|
|
1219
|
|
|
|
|
|
|
Receives a line of raw IRC input. Intended for cases where you're trying to do |
1220
|
|
|
|
|
|
|
something clever which the normal methods and parsing supplied can't handle. |
1221
|
|
|
|
|
|
|
|
1222
|
|
|
|
|
|
|
=head2 C |
1223
|
|
|
|
|
|
|
|
1224
|
|
|
|
|
|
|
Receives a line of raw IRC output being sent to the IRC server. |
1225
|
|
|
|
|
|
|
|
1226
|
|
|
|
|
|
|
=head1 BOT METHODS |
1227
|
|
|
|
|
|
|
|
1228
|
|
|
|
|
|
|
There are a few methods you can call on the bot object to do things. These |
1229
|
|
|
|
|
|
|
are as follows: |
1230
|
|
|
|
|
|
|
|
1231
|
|
|
|
|
|
|
=head2 C |
1232
|
|
|
|
|
|
|
|
1233
|
|
|
|
|
|
|
Takes an integer as an argument. Causes the L event to be called |
1234
|
|
|
|
|
|
|
after that many seconds (or 5 seconds if no argument is provided). Note |
1235
|
|
|
|
|
|
|
that if the tick event is due to be called already, this will override it. |
1236
|
|
|
|
|
|
|
You can't schedule multiple future events with this funtction. |
1237
|
|
|
|
|
|
|
|
1238
|
|
|
|
|
|
|
=head2 C |
1239
|
|
|
|
|
|
|
|
1240
|
|
|
|
|
|
|
This method allows you to fork arbitrary background processes. They |
1241
|
|
|
|
|
|
|
will run concurrently with the main bot, returning their output to a |
1242
|
|
|
|
|
|
|
handler routine. You should call C in response to specific |
1243
|
|
|
|
|
|
|
events in your C routine, particularly for longer running |
1244
|
|
|
|
|
|
|
processes like searches, which will block the bot from receiving or |
1245
|
|
|
|
|
|
|
sending on channel whilst they take place if you don't fork them. |
1246
|
|
|
|
|
|
|
|
1247
|
|
|
|
|
|
|
Inside the subroutine called by forkit, you can send output back to the |
1248
|
|
|
|
|
|
|
channel by printing lines (followd by C<\n>) to STDOUT. This has the same |
1249
|
|
|
|
|
|
|
effect as calling Lsay >>|say>. |
1250
|
|
|
|
|
|
|
|
1251
|
|
|
|
|
|
|
C takes the following arguments: |
1252
|
|
|
|
|
|
|
|
1253
|
|
|
|
|
|
|
=over 4 |
1254
|
|
|
|
|
|
|
|
1255
|
|
|
|
|
|
|
=item run |
1256
|
|
|
|
|
|
|
|
1257
|
|
|
|
|
|
|
A coderef to the routine which you want to run. Bear in mind that the |
1258
|
|
|
|
|
|
|
routine doesn't automatically get the text of the query - you'll need |
1259
|
|
|
|
|
|
|
to pass it in C (see below) if you want to use it at all. |
1260
|
|
|
|
|
|
|
|
1261
|
|
|
|
|
|
|
Apart from that, your C routine just needs to print its output to |
1262
|
|
|
|
|
|
|
C, and it will be passed on to your designated handler. |
1263
|
|
|
|
|
|
|
|
1264
|
|
|
|
|
|
|
=item handler |
1265
|
|
|
|
|
|
|
|
1266
|
|
|
|
|
|
|
Optional. A method name within your current package which we can |
1267
|
|
|
|
|
|
|
return the routine's data to. Defaults to the built-in method |
1268
|
|
|
|
|
|
|
C (which simply sends data to channel). |
1269
|
|
|
|
|
|
|
|
1270
|
|
|
|
|
|
|
=item callback |
1271
|
|
|
|
|
|
|
|
1272
|
|
|
|
|
|
|
Optional. A coderef to execute in place of the handler. If used, the value |
1273
|
|
|
|
|
|
|
of the handler argument is used to name the POE event. This allows using |
1274
|
|
|
|
|
|
|
closures and/or having multiple simultanious calls to forkit with unique |
1275
|
|
|
|
|
|
|
handler for each call. |
1276
|
|
|
|
|
|
|
|
1277
|
|
|
|
|
|
|
=item body |
1278
|
|
|
|
|
|
|
|
1279
|
|
|
|
|
|
|
Optional. Use this to pass on the body of the incoming message that |
1280
|
|
|
|
|
|
|
triggered you to fork this process. Useful for interactive processes |
1281
|
|
|
|
|
|
|
such as searches, so that you can act on specific terms in the user's |
1282
|
|
|
|
|
|
|
instructions. |
1283
|
|
|
|
|
|
|
|
1284
|
|
|
|
|
|
|
=item who |
1285
|
|
|
|
|
|
|
|
1286
|
|
|
|
|
|
|
The nick of who you want any response to reach (optional inside a |
1287
|
|
|
|
|
|
|
channel.) |
1288
|
|
|
|
|
|
|
|
1289
|
|
|
|
|
|
|
=item channel |
1290
|
|
|
|
|
|
|
|
1291
|
|
|
|
|
|
|
Where you want to say it to them in. This may be the special channel |
1292
|
|
|
|
|
|
|
"msg" if you want to speak to them directly |
1293
|
|
|
|
|
|
|
|
1294
|
|
|
|
|
|
|
=item address |
1295
|
|
|
|
|
|
|
|
1296
|
|
|
|
|
|
|
Optional. Setting this to a true value causes the person to be |
1297
|
|
|
|
|
|
|
addressed (i.e. to have "Nick: " prepended to the front of returned |
1298
|
|
|
|
|
|
|
message text if the response is going to a public forum. |
1299
|
|
|
|
|
|
|
|
1300
|
|
|
|
|
|
|
=item arguments |
1301
|
|
|
|
|
|
|
|
1302
|
|
|
|
|
|
|
Optional. This should be an anonymous array of values, which will be |
1303
|
|
|
|
|
|
|
passed to your C routine. Bear in mind that this is not |
1304
|
|
|
|
|
|
|
intelligent - it will blindly spew arguments at C in the order |
1305
|
|
|
|
|
|
|
that you specify them, and it is the responsibility of your C |
1306
|
|
|
|
|
|
|
routine to pick them up and make sense of them. |
1307
|
|
|
|
|
|
|
|
1308
|
|
|
|
|
|
|
=back |
1309
|
|
|
|
|
|
|
|
1310
|
|
|
|
|
|
|
=head2 C |
1311
|
|
|
|
|
|
|
|
1312
|
|
|
|
|
|
|
Say something to someone. Takes a list of key/value pairs as arguments. |
1313
|
|
|
|
|
|
|
You should pass the following arguments: |
1314
|
|
|
|
|
|
|
|
1315
|
|
|
|
|
|
|
=over 4 |
1316
|
|
|
|
|
|
|
|
1317
|
|
|
|
|
|
|
=item who |
1318
|
|
|
|
|
|
|
|
1319
|
|
|
|
|
|
|
The nick of who you are saying this to (optional inside a channel.) |
1320
|
|
|
|
|
|
|
|
1321
|
|
|
|
|
|
|
=item channel |
1322
|
|
|
|
|
|
|
|
1323
|
|
|
|
|
|
|
Where you want to say it to them in. This may be the special channel |
1324
|
|
|
|
|
|
|
"msg" if you want to speak to them directly |
1325
|
|
|
|
|
|
|
|
1326
|
|
|
|
|
|
|
=item body |
1327
|
|
|
|
|
|
|
|
1328
|
|
|
|
|
|
|
The body of the message. I.e. what you want to say. |
1329
|
|
|
|
|
|
|
|
1330
|
|
|
|
|
|
|
=item address |
1331
|
|
|
|
|
|
|
|
1332
|
|
|
|
|
|
|
Optional. Setting this to a true value causes the person to be |
1333
|
|
|
|
|
|
|
addressed (i.e. to have "Nick: " prepended to the front of the message |
1334
|
|
|
|
|
|
|
text if this message is going to a pulbic forum. |
1335
|
|
|
|
|
|
|
|
1336
|
|
|
|
|
|
|
=back |
1337
|
|
|
|
|
|
|
|
1338
|
|
|
|
|
|
|
You can also make non-OO calls to C, which will be interpreted as |
1339
|
|
|
|
|
|
|
coming from a process spawned by C. The routine will serialise |
1340
|
|
|
|
|
|
|
any data it is sent, and throw it to STDOUT, where L can |
1341
|
|
|
|
|
|
|
pass it on to a handler. |
1342
|
|
|
|
|
|
|
|
1343
|
|
|
|
|
|
|
=head2 C |
1344
|
|
|
|
|
|
|
|
1345
|
|
|
|
|
|
|
C will return data to channel, but emoted (as if you'd said "/me |
1346
|
|
|
|
|
|
|
writes a spiffy new bot" in most clients). It takes the same arguments |
1347
|
|
|
|
|
|
|
as C, listed above. |
1348
|
|
|
|
|
|
|
|
1349
|
|
|
|
|
|
|
=head2 C |
1350
|
|
|
|
|
|
|
|
1351
|
|
|
|
|
|
|
C will send a IRC notice to the channel. This is typically used by |
1352
|
|
|
|
|
|
|
bots to not break the IRC conversations flow. The message will appear as: |
1353
|
|
|
|
|
|
|
|
1354
|
|
|
|
|
|
|
-nick- message here |
1355
|
|
|
|
|
|
|
|
1356
|
|
|
|
|
|
|
It takes the same arguments as C, listed above. Example: |
1357
|
|
|
|
|
|
|
|
1358
|
|
|
|
|
|
|
$bot->notice( |
1359
|
|
|
|
|
|
|
channel => '#bot_basicbot_test', |
1360
|
|
|
|
|
|
|
body => 'This is a notice' |
1361
|
|
|
|
|
|
|
); |
1362
|
|
|
|
|
|
|
|
1363
|
|
|
|
|
|
|
=head2 C |
1364
|
|
|
|
|
|
|
|
1365
|
|
|
|
|
|
|
Takes two arguments, a hashref containing information about an incoming |
1366
|
|
|
|
|
|
|
message, and a reply message. It will reply in a privmsg if the incoming |
1367
|
|
|
|
|
|
|
one was a privmsg, in channel if not, and with prefixes if the incoming |
1368
|
|
|
|
|
|
|
one was prefixed. Mostly a shortcut method - it's roughly equivalent to |
1369
|
|
|
|
|
|
|
|
1370
|
|
|
|
|
|
|
$mess->{body} = $body; |
1371
|
|
|
|
|
|
|
$self->say($mess); |
1372
|
|
|
|
|
|
|
|
1373
|
|
|
|
|
|
|
=head2 C |
1374
|
|
|
|
|
|
|
|
1375
|
|
|
|
|
|
|
Takes no arguments. Returns the underlying |
1376
|
|
|
|
|
|
|
L object used by |
1377
|
|
|
|
|
|
|
Bot::BasicBot. Useful for accessing various state methods and for posting |
1378
|
|
|
|
|
|
|
commands to the component. For example: |
1379
|
|
|
|
|
|
|
|
1380
|
|
|
|
|
|
|
# get the list of nicks in the channel #someplace |
1381
|
|
|
|
|
|
|
my @nicks = $bot->pocoirc->channel_list("#someplace"); |
1382
|
|
|
|
|
|
|
|
1383
|
|
|
|
|
|
|
# join the channel #otherplace |
1384
|
|
|
|
|
|
|
$bot->pocoirc->yield('join', '#otherplace'); |
1385
|
|
|
|
|
|
|
|
1386
|
|
|
|
|
|
|
=head2 C |
1387
|
|
|
|
|
|
|
|
1388
|
|
|
|
|
|
|
Takes a channel names as a parameter, and returns a hash of hashes. The |
1389
|
|
|
|
|
|
|
keys are the nicknames in the channel, the values are hashes containing |
1390
|
|
|
|
|
|
|
the keys "voice" and "op", indicating whether these users are voiced or |
1391
|
|
|
|
|
|
|
opped in the channel. This method is only here for backwards compatibility. |
1392
|
|
|
|
|
|
|
You'll probably get more use out of |
1393
|
|
|
|
|
|
|
L's methods (which |
1394
|
|
|
|
|
|
|
this method is merely a wrapper for). You can access the |
1395
|
|
|
|
|
|
|
POE::Component::IRC::State object through Bot::BasicBot's C |
1396
|
|
|
|
|
|
|
method. |
1397
|
|
|
|
|
|
|
|
1398
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
1399
|
|
|
|
|
|
|
|
1400
|
|
|
|
|
|
|
Get or set methods. Changing most of these values when connected |
1401
|
|
|
|
|
|
|
won't cause sideffects. e.g. changing the server will not |
1402
|
|
|
|
|
|
|
cause a disconnect and a reconnect to another server. |
1403
|
|
|
|
|
|
|
|
1404
|
|
|
|
|
|
|
Attributes that accept multiple values always return lists and |
1405
|
|
|
|
|
|
|
either accept an arrayref or a complete list as an argument. |
1406
|
|
|
|
|
|
|
|
1407
|
|
|
|
|
|
|
The usual way of calling these is as keys to the hash passed to the |
1408
|
|
|
|
|
|
|
'new' method. |
1409
|
|
|
|
|
|
|
|
1410
|
|
|
|
|
|
|
=head2 C |
1411
|
|
|
|
|
|
|
|
1412
|
|
|
|
|
|
|
The server we're going to connect to. Defaults to |
1413
|
|
|
|
|
|
|
"irc.perl.org". |
1414
|
|
|
|
|
|
|
|
1415
|
|
|
|
|
|
|
=head2 C |
1416
|
|
|
|
|
|
|
|
1417
|
|
|
|
|
|
|
The port we're going to use. Defaults to "6667" |
1418
|
|
|
|
|
|
|
|
1419
|
|
|
|
|
|
|
=head2 C |
1420
|
|
|
|
|
|
|
|
1421
|
|
|
|
|
|
|
The server password for the server we're going to connect to. Defaults to |
1422
|
|
|
|
|
|
|
undef. |
1423
|
|
|
|
|
|
|
|
1424
|
|
|
|
|
|
|
=head2 C |
1425
|
|
|
|
|
|
|
|
1426
|
|
|
|
|
|
|
A boolean to indicate whether or not the server we're going to connect to |
1427
|
|
|
|
|
|
|
is an SSL server. Defaults to 0. |
1428
|
|
|
|
|
|
|
|
1429
|
|
|
|
|
|
|
=head2 C |
1430
|
|
|
|
|
|
|
|
1431
|
|
|
|
|
|
|
The local address to use, for multihomed boxes. Defaults to undef (use whatever |
1432
|
|
|
|
|
|
|
source IP address the system deigns is appropriate). |
1433
|
|
|
|
|
|
|
|
1434
|
|
|
|
|
|
|
=head2 C |
1435
|
|
|
|
|
|
|
|
1436
|
|
|
|
|
|
|
A boolean to indicate whether IPv6 should be used. Defaults to undef (use |
1437
|
|
|
|
|
|
|
IPv4). |
1438
|
|
|
|
|
|
|
|
1439
|
|
|
|
|
|
|
=head2 C |
1440
|
|
|
|
|
|
|
|
1441
|
|
|
|
|
|
|
The nick we're going to use. Defaults to five random letters |
1442
|
|
|
|
|
|
|
and numbers followed by the word "bot" |
1443
|
|
|
|
|
|
|
|
1444
|
|
|
|
|
|
|
=head2 C |
1445
|
|
|
|
|
|
|
|
1446
|
|
|
|
|
|
|
Alternate nicks that this bot will be known by. These are not nicks |
1447
|
|
|
|
|
|
|
that the bot will try if it's main nick is taken, but rather other |
1448
|
|
|
|
|
|
|
nicks that the bot will recognise if it is addressed in a public |
1449
|
|
|
|
|
|
|
channel as the nick. This is useful for bots that are replacements |
1450
|
|
|
|
|
|
|
for other bots...e.g, your bot can answer to the name "infobot: " |
1451
|
|
|
|
|
|
|
even though it isn't really. |
1452
|
|
|
|
|
|
|
|
1453
|
|
|
|
|
|
|
=head2 C |
1454
|
|
|
|
|
|
|
|
1455
|
|
|
|
|
|
|
The username we'll claim to have at our ip/domain. By default this |
1456
|
|
|
|
|
|
|
will be the same as our nick. |
1457
|
|
|
|
|
|
|
|
1458
|
|
|
|
|
|
|
=head2 C |
1459
|
|
|
|
|
|
|
|
1460
|
|
|
|
|
|
|
The name that the bot will identify itself as. Defaults to |
1461
|
|
|
|
|
|
|
"$nick bot" where $nick is the nick that the bot uses. |
1462
|
|
|
|
|
|
|
|
1463
|
|
|
|
|
|
|
=head2 C |
1464
|
|
|
|
|
|
|
|
1465
|
|
|
|
|
|
|
The channels we're going to connect to. |
1466
|
|
|
|
|
|
|
|
1467
|
|
|
|
|
|
|
=head2 C |
1468
|
|
|
|
|
|
|
|
1469
|
|
|
|
|
|
|
The quit message. Defaults to "Bye". |
1470
|
|
|
|
|
|
|
|
1471
|
|
|
|
|
|
|
=head2 C |
1472
|
|
|
|
|
|
|
|
1473
|
|
|
|
|
|
|
The list of irc nicks to ignore B messages from (normally |
1474
|
|
|
|
|
|
|
other bots.) Useful for stopping bot cascades. |
1475
|
|
|
|
|
|
|
|
1476
|
|
|
|
|
|
|
=head2 C |
1477
|
|
|
|
|
|
|
|
1478
|
|
|
|
|
|
|
IRC has no defined character set for putting high-bit chars into channel. |
1479
|
|
|
|
|
|
|
This attribute sets the encoding to be used for outgoing messages. Defaults |
1480
|
|
|
|
|
|
|
to 'utf8'. |
1481
|
|
|
|
|
|
|
|
1482
|
|
|
|
|
|
|
=head2 C |
1483
|
|
|
|
|
|
|
|
1484
|
|
|
|
|
|
|
Set to '1' to disable the built-in flood protection of POE::Compoent::IRC |
1485
|
|
|
|
|
|
|
|
1486
|
|
|
|
|
|
|
=head2 C |
1487
|
|
|
|
|
|
|
|
1488
|
|
|
|
|
|
|
Tells Bot::BasicBot to B run the L at the end |
1489
|
|
|
|
|
|
|
of L|/run>, in case you want to do that yourself. |
1490
|
|
|
|
|
|
|
|
1491
|
|
|
|
|
|
|
=head2 C |
1492
|
|
|
|
|
|
|
|
1493
|
|
|
|
|
|
|
A hashref of WEBIRC params - keys C, C, C and C. Unless |
1494
|
|
|
|
|
|
|
the network you are connecting to trusts you enough to give you a WEBIRC config |
1495
|
|
|
|
|
|
|
block & password, this won't be of any use to you. |
1496
|
|
|
|
|
|
|
|
1497
|
|
|
|
|
|
|
=head1 OTHER METHODS |
1498
|
|
|
|
|
|
|
|
1499
|
|
|
|
|
|
|
=head2 C |
1500
|
|
|
|
|
|
|
|
1501
|
|
|
|
|
|
|
Bot::BasicBot implements AUTOLOAD for sending arbitrary states to the |
1502
|
|
|
|
|
|
|
underlying L component. So for a |
1503
|
|
|
|
|
|
|
C<$bot> object, sending |
1504
|
|
|
|
|
|
|
|
1505
|
|
|
|
|
|
|
$bot->foo("bar"); |
1506
|
|
|
|
|
|
|
|
1507
|
|
|
|
|
|
|
is equivalent to |
1508
|
|
|
|
|
|
|
|
1509
|
|
|
|
|
|
|
$poe_kernel->post(BASICBOT_ALIAS, "foo", "bar"); |
1510
|
|
|
|
|
|
|
|
1511
|
|
|
|
|
|
|
=head2 C |
1512
|
|
|
|
|
|
|
|
1513
|
|
|
|
|
|
|
Logs the message. This method merely prints to STDERR - If you want smarter |
1514
|
|
|
|
|
|
|
logging, override this method - it will have simple text strings passed in |
1515
|
|
|
|
|
|
|
@_. |
1516
|
|
|
|
|
|
|
|
1517
|
|
|
|
|
|
|
=head2 C |
1518
|
|
|
|
|
|
|
|
1519
|
|
|
|
|
|
|
Takes a nick name as an argument. Return true if this nick should be |
1520
|
|
|
|
|
|
|
ignored. Ignores anything in the ignore list |
1521
|
|
|
|
|
|
|
|
1522
|
|
|
|
|
|
|
=head2 C |
1523
|
|
|
|
|
|
|
|
1524
|
|
|
|
|
|
|
Takes a nick and hostname (of the form "nick!hostname") and |
1525
|
|
|
|
|
|
|
returns just the nick |
1526
|
|
|
|
|
|
|
|
1527
|
|
|
|
|
|
|
=head2 C |
1528
|
|
|
|
|
|
|
|
1529
|
|
|
|
|
|
|
Converts a string of bytes from IRC (uses |
1530
|
|
|
|
|
|
|
L|IRC::Utils/decode_irc> from L |
1531
|
|
|
|
|
|
|
internally) and returns a Perl string. |
1532
|
|
|
|
|
|
|
|
1533
|
|
|
|
|
|
|
It can also takes a list (or arrayref or hashref) of strings, and return |
1534
|
|
|
|
|
|
|
a list of strings |
1535
|
|
|
|
|
|
|
|
1536
|
|
|
|
|
|
|
=head2 C |
1537
|
|
|
|
|
|
|
|
1538
|
|
|
|
|
|
|
Converts a list of perl strings into a list of byte sequences, using |
1539
|
|
|
|
|
|
|
the bot's charset. See L|/charset_decode>. |
1540
|
|
|
|
|
|
|
|
1541
|
|
|
|
|
|
|
=head1 HELP AND SUPPORT |
1542
|
|
|
|
|
|
|
|
1543
|
|
|
|
|
|
|
If you have any questions or issues, you can drop by in #poe or |
1544
|
|
|
|
|
|
|
#bot-basicbot @ irc.perl.org, where I (Hinrik) am usually around. |
1545
|
|
|
|
|
|
|
|
1546
|
|
|
|
|
|
|
=head1 AUTHOR |
1547
|
|
|
|
|
|
|
|
1548
|
|
|
|
|
|
|
David Precious (BIGPRESH) C<< >> is the |
1549
|
|
|
|
|
|
|
current maintainer. |
1550
|
|
|
|
|
|
|
|
1551
|
|
|
|
|
|
|
Tom Insam Etom@jerakeen.orgE was the original author. |
1552
|
|
|
|
|
|
|
|
1553
|
|
|
|
|
|
|
This program is free software; you can redistribute it |
1554
|
|
|
|
|
|
|
and/or modify it under the same terms as Perl itself. |
1555
|
|
|
|
|
|
|
|
1556
|
|
|
|
|
|
|
=head1 CREDITS |
1557
|
|
|
|
|
|
|
|
1558
|
|
|
|
|
|
|
The initial version of Bot::BasicBot was written by Mark Fowler, |
1559
|
|
|
|
|
|
|
and many thanks are due to him. |
1560
|
|
|
|
|
|
|
|
1561
|
|
|
|
|
|
|
Nice code for dealing with emotes thanks to Jo Walsh. |
1562
|
|
|
|
|
|
|
|
1563
|
|
|
|
|
|
|
Various patches from Tom Insam, including much improved rejoining, |
1564
|
|
|
|
|
|
|
AUTOLOAD stuff, better interactive help, and a few API tidies. |
1565
|
|
|
|
|
|
|
|
1566
|
|
|
|
|
|
|
Maintainership for a while was in the hands of Simon Kent |
1567
|
|
|
|
|
|
|
Esimon@hitherto.netE. Don't know what he did. :-) |
1568
|
|
|
|
|
|
|
|
1569
|
|
|
|
|
|
|
I (Tom Insam) received patches for tracking joins and parts from Silver, |
1570
|
|
|
|
|
|
|
sat on them for two months, and have finally applied them. Thanks, dude. |
1571
|
|
|
|
|
|
|
He also sent me changes for the tick event API, which made sense. |
1572
|
|
|
|
|
|
|
|
1573
|
|
|
|
|
|
|
In November 2010, maintainership moved to Hinrik Ern |
1574
|
|
|
|
|
|
|
SigurEsson (L). |
1575
|
|
|
|
|
|
|
|
1576
|
|
|
|
|
|
|
In April 2017, maintainership moved to David Precious |
1577
|
|
|
|
|
|
|
(L). |
1578
|
|
|
|
|
|
|
|
1579
|
|
|
|
|
|
|
=head1 SEE ALSO |
1580
|
|
|
|
|
|
|
|
1581
|
|
|
|
|
|
|
If you want to write/run a more flexible bot which supports module loading, |
1582
|
|
|
|
|
|
|
authentication, data storage etc, consider the subclass |
1583
|
|
|
|
|
|
|
L. |
1584
|
|
|
|
|
|
|
|
1585
|
|
|
|
|
|
|
Also see L, L |
1586
|
|
|
|
|
|
|
|
1587
|
|
|
|
|
|
|
Possibly Infobot, at http://www.infobot.org |
1588
|
|
|
|
|
|
|
|
1589
|
|
|
|
|
|
|
=cut |