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