line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package WWW::Yahoo::Groups; |
2
|
12
|
|
|
12
|
|
533664
|
use strict; |
|
12
|
|
|
|
|
34
|
|
|
12
|
|
|
|
|
2104
|
|
3
|
12
|
|
|
12
|
|
77
|
use warnings FATAL => 'all'; |
|
12
|
|
|
|
|
26
|
|
|
12
|
|
|
|
|
1297
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 NAME |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
WWW::Yahoo::Groups - Automated access to Yahoo! Groups archives. |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 SYNOPSIS |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
my $y = WWW::Yahoo::Groups->new(); |
12
|
|
|
|
|
|
|
$y->login( $user => $pass ); |
13
|
|
|
|
|
|
|
$y->list( 'Jade_Pagoda' ); |
14
|
|
|
|
|
|
|
my $email = $y->fetch_message( 2345 ); |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
# Error catching |
17
|
|
|
|
|
|
|
my $email = eval { $y->fetch_message( 93848 ) }; |
18
|
|
|
|
|
|
|
if ( $@ and ref $@ and $@->isa('X::WWW::Yahoo::Groups') ) |
19
|
|
|
|
|
|
|
{ |
20
|
|
|
|
|
|
|
warn "Problem: ".$@->error; |
21
|
|
|
|
|
|
|
} |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=head1 DESCRIPTION |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
C retrieves messages from the archive of Yahoo |
26
|
|
|
|
|
|
|
Groups. It provides a simple OO interface to logging in and retrieving |
27
|
|
|
|
|
|
|
said messages which you may then do with as you will. |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=head2 Things it does |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
=over 4 |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=item * |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
B It lets you login. |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=item * |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
B It notes that it got one and |
40
|
|
|
|
|
|
|
progresses straight to the message. |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=item * |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
B It just goes straight on. |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=item * |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
B We get the source which happens to be the raw stuff. |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=item * |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
B Could be improved, but it will generally barf if it |
53
|
|
|
|
|
|
|
doesn't understand something. |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=item * |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
B I've found that some groups' archives have |
58
|
|
|
|
|
|
|
unusually corrupted headers. Evidently it would be beneficial to |
59
|
|
|
|
|
|
|
restore these headers. As far as I can tell, it comes from not |
60
|
|
|
|
|
|
|
being a moderator on the lists in question. |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=back |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=head1 USAGE |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
Try to be a well behaved bot and C for a few seconds (at least) |
67
|
|
|
|
|
|
|
after doing things. It's considered polite. There's an |
68
|
|
|
|
|
|
|
L method that should be useful for this. |
69
|
|
|
|
|
|
|
Recently, this has been set to a default of 1 second. Feel free to tweak |
70
|
|
|
|
|
|
|
if necessary. |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
If you're used to seeing munged email addresses when you view |
73
|
|
|
|
|
|
|
the message archive (i.e. you're not a moderator or owner of |
74
|
|
|
|
|
|
|
the group) then you'll be pleased to know that |
75
|
|
|
|
|
|
|
C can demunge those email addresses. |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
All exceptions are subclasses of C, itself a |
78
|
|
|
|
|
|
|
subclass of C. See L for |
79
|
|
|
|
|
|
|
details. |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=head1 OTHER DOCUMENTATION |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=head2 I, by Kevin Hemenway and Tara Calishain |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
I from O'Reilly |
86
|
|
|
|
|
|
|
(L) is a great book for anyone |
87
|
|
|
|
|
|
|
wanting to know more about screen-scraping and spidering. |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
There is a WWW::Yahoo::Groups based hack by Andy Lester: |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=over 4 |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=item 44 Archiving Yahoo! Groups Messages with WWW::Yahoo::Groups |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=item |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=back |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
and two hacks, not related to this module, by me, Iain Truskett: |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=over 4 |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=item 19 Scraping with HTML::TreeBuilder |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
=item 57 Related Amazon.com Products with Alexa |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=back |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
=cut |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
our $VERSION = '1.91'; |
112
|
|
|
|
|
|
|
|
113
|
12
|
|
|
12
|
|
75
|
use Carp; |
|
12
|
|
|
|
|
35
|
|
|
12
|
|
|
|
|
1294
|
|
114
|
12
|
|
|
12
|
|
16611
|
use HTTP::Cookies; |
|
12
|
|
|
|
|
236383
|
|
|
12
|
|
|
|
|
412
|
|
115
|
12
|
|
|
12
|
|
11520
|
use HTML::Entities; |
|
12
|
|
|
|
|
154417
|
|
|
12
|
|
|
|
|
1580
|
|
116
|
12
|
|
|
12
|
|
15829
|
use Params::Validate qw( :all ); |
|
12
|
|
|
|
|
188877
|
|
|
12
|
|
|
|
|
3128
|
|
117
|
12
|
|
|
12
|
|
8839
|
use WWW::Yahoo::Groups::Mechanize; |
|
12
|
|
|
|
|
48
|
|
|
12
|
|
|
|
|
72112
|
|
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
require WWW::Yahoo::Groups::Errors; |
120
|
|
|
|
|
|
|
Params::Validate::validation_options( |
121
|
|
|
|
|
|
|
WWW::Yahoo::Groups::Errors->import() |
122
|
|
|
|
|
|
|
); |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=head1 METHODS |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
=head2 Constructor |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=head3 new |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
Create a new C robot. |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
my $y = WWW::Yahoo::Groups->new(); |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
It can take a has of named arguments. Two arguments are defined: |
135
|
|
|
|
|
|
|
C and C. They correspond to the methods of the same |
136
|
|
|
|
|
|
|
name. |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
my $y = WWW::Yahoo::Groups->new( |
139
|
|
|
|
|
|
|
debug => 1, |
140
|
|
|
|
|
|
|
autosleep => 4, |
141
|
|
|
|
|
|
|
); |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=cut |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub new |
146
|
|
|
|
|
|
|
{ |
147
|
12
|
|
|
12
|
1
|
1351
|
my $class = shift; |
148
|
12
|
|
|
|
|
85
|
my %args = ( debug => 0, autosleep => 1, @_ ); |
149
|
12
|
|
|
|
|
50
|
my $self = bless {}, $class; |
150
|
12
|
|
|
|
|
147
|
my $w = WWW::Yahoo::Groups::Mechanize->new(); |
151
|
12
|
|
|
|
|
76
|
$self->agent($w); |
152
|
12
|
|
|
|
|
65
|
$self->debug( $args{debug} ); |
153
|
12
|
|
|
|
|
65
|
$self->autosleep( $args{ autosleep } ); |
154
|
12
|
|
|
|
|
78
|
return bless $self, $class; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=head2 Options |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=head3 debug |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
Enable/disable/read debugging mode. |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
$y->debug(0); # Disable |
164
|
|
|
|
|
|
|
$y->debug(1); # Enable |
165
|
|
|
|
|
|
|
warn "Debugging!" if $y->debug(); |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
The C method of the current L object will |
168
|
|
|
|
|
|
|
be invoked with the truth of the argument. This usually means |
169
|
|
|
|
|
|
|
L. |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=cut |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
sub debug |
174
|
|
|
|
|
|
|
{ |
175
|
12
|
|
|
12
|
1
|
25
|
my $self = shift; |
176
|
12
|
50
|
|
|
|
57
|
if (@_) { |
177
|
12
|
50
|
|
|
|
46
|
my $true = ($_[0] ? 1 : 0); |
178
|
12
|
|
|
|
|
32
|
$self->{__PACKAGE__.'-debug'} = $true; |
179
|
12
|
|
|
|
|
38
|
$self->agent->debug( $true ); |
180
|
|
|
|
|
|
|
} |
181
|
12
|
|
|
|
|
36
|
$self->{__PACKAGE__.'-debug'}; |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=head3 autosleep |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
If given a parameter, it sets the numbers of seconds to sleep. |
187
|
|
|
|
|
|
|
Otherwise, it returns the number. Defaults to 1 second. |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
$y->autosleep( 5 ); # Set it to 5. |
190
|
|
|
|
|
|
|
sleep ( $y->autosleep() ); |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
May throw C if given invalid parameters. |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
This is used by L. If C is set, then C will |
195
|
|
|
|
|
|
|
C for the specified period after every fetch. |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
Implemented by the object returned by L. By default this |
198
|
|
|
|
|
|
|
means L. |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=cut |
201
|
|
|
|
|
|
|
|
202
|
19
|
|
|
19
|
1
|
4956
|
sub autosleep { my $self = shift; $self->agent->autosleep(@_) } |
|
19
|
|
|
|
|
71
|
|
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=head2 Logging in and out |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=head3 login |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
Logs the robot into the Yahoo! Groups system. |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
$y->login( $user => $passwd ); |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
May throw: |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=over 4 |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=item * |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
C if it cannot fetch any of the |
219
|
|
|
|
|
|
|
appropriate pages. |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
=item * |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
C if given invalid parameters. |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
=item * |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
C if unable to log in for some reason |
228
|
|
|
|
|
|
|
(error will be given the text of the Yahoo error). |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
=item * |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
C if the object is already |
233
|
|
|
|
|
|
|
logged in. I intend to make this exception redundant, perhaps by |
234
|
|
|
|
|
|
|
just making C a null-op is we're already logged in, or by calling |
235
|
|
|
|
|
|
|
L and then relogging in. |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=back |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
=cut |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
sub login |
242
|
|
|
|
|
|
|
{ |
243
|
14
|
|
|
14
|
1
|
9691
|
my $self = shift; |
244
|
14
|
|
|
|
|
27
|
my %p; |
245
|
14
|
|
|
|
|
353
|
@p{qw( user pass )} = validate_pos( @_, |
246
|
|
|
|
|
|
|
{ type => SCALAR, }, # user |
247
|
|
|
|
|
|
|
{ type => SCALAR, }, # pass |
248
|
|
|
|
|
|
|
); |
249
|
9
|
|
|
|
|
59
|
my $w = $self->agent(); |
250
|
9
|
|
|
|
|
24
|
my $rv = eval { |
251
|
9
|
50
|
|
|
|
73
|
X::WWW::Yahoo::Groups::AlreadyLoggedIn->throw( |
252
|
|
|
|
|
|
|
"You must logout before you can log in again.") |
253
|
|
|
|
|
|
|
if $self->loggedin; |
254
|
|
|
|
|
|
|
|
255
|
9
|
|
|
|
|
60
|
$w->get('http://groups.yahoo.com/'); |
256
|
9
|
|
|
|
|
220
|
$w->follow('Sign In'); |
257
|
0
|
|
|
|
|
0
|
$w->field( login => $p{user} ); |
258
|
0
|
|
|
|
|
0
|
$w->field( passwd => $p{pass} ); |
259
|
0
|
|
|
|
|
0
|
$w->click(); |
260
|
0
|
0
|
|
|
|
0
|
if (my ($error) = $w->res->content =~ m! |
261
|
|
|
|
|
|
|
\Q\E |
262
|
|
|
|
|
|
|
\s+ |
263
|
|
|
|
|
|
|
(.*?) |
264
|
|
|
|
|
|
|
\s+ |
265
|
|
|
|
|
|
|
\Q |