File Coverage

blib/lib/WWW/Zooomr/Scraper.pm
Criterion Covered Total %
statement 33 125 26.4
branch 0 52 0.0
condition 0 10 0.0
subroutine 10 22 45.4
pod 7 7 100.0
total 50 216 23.1


line stmt bran cond sub pod time code
1             package WWW::Zooomr::Scraper;
2 2     2   56957 use strict;
  2         6  
  2         80  
3 2     2   11 use warnings;
  2         5  
  2         52  
4 2     2   13 use Carp;
  2         8  
  2         299  
5 2     2   1697 use version; our $VERSION = qv('0.3.1');
  2         5520  
  2         15  
6 2     2   2022 use English qw( -no_match_vars );
  2         9856  
  2         12  
7 2     2   3526 use WWW::Mechanize;
  2         425108  
  2         85  
8              
9 2     2   1749 use Path::Class qw( file );
  2         68525  
  2         188  
10              
11             my @fields;
12             my %defaults = (
13             login_page => 'http://www.zooomr.com/login/',
14             upload_page => 'http://www.zooomr.com/photos/upload/?noflash=okiwill',
15             logout_page => 'http://www.zooomr.com/logout/',
16             );
17              
18             BEGIN { # Generate simple accessors
19 2     2   18 no warnings;
  2         4  
  2         69  
20 2     2   10 no strict;
  2         11  
  2         238  
21 2     2   16 @fields = qw(
22             updater
23             agent username password
24             login_page upload_page logout_page
25             );
26              
27 2         4 for my $param_name (@fields) {
28 14         65 *{__PACKAGE__ . '::get_' . $param_name} = sub {
29 0     0   0 return $_[0]->{$param_name};
30 14         45 };
31 14         2291 *{__PACKAGE__ . '::set_' . $param_name} = sub {
32 0     0     my $previous = $_[0]->{$param_name};
33 0           $_[0]->{$param_name} = $_[1];
34 0           return $previous;
35 14         48 };
36             } ## end for my $param_name (@fields)
37             } ## end BEGIN
38              
39             sub new {
40 0     0 1   my $package = shift;
41 0 0         my $config = ref($_[0]) ? $_[0] : {@_};
42              
43 0           my $self = bless {%defaults}, $package;
44 0           $self->reconfig($config);
45              
46 0           return $self;
47             } ## end sub new
48              
49             sub reconfig {
50 0     0 1   my $self = shift;
51 0 0         my $config = ref($_[0]) ? $_[0] : {@_};
52              
53 0           for my $param_name (@fields) {
54 0 0         next unless exists $config->{$param_name};
55 0           $self->{$param_name} = $config->{$param_name};
56             }
57              
58 0 0         $self->set_agent(WWW::Mechanize->new(autocheck => 1, stack_depth => 1, ))
59             unless defined $self->get_agent();
60              
61 0   0       $self->update_proxy(exists($config->{proxy}) && $config->{proxy});
62              
63 0 0         $self->load_cookies_from($config->{cookie})
64             if exists $config->{cookie};
65             } ## end sub reconfig
66              
67             sub update_proxy {
68 0     0 1   my ($self, $proxy) = @_;
69 0           my $ua = $self->get_agent();
70 0           $ua->env_proxy();
71 0 0         $ua->proxy('http', $proxy) if $proxy;
72 0           return $proxy;
73             } ## end sub update_proxy
74              
75             sub load_cookies_from {
76 0     0 1   my $self = shift;
77 0           my ($filename) = @_;
78              
79 0           require HTTP::Cookies::Mozilla;
80 0           my $jar = HTTP::Cookies::Mozilla->new(autosave => 0);
81 0 0         $jar->load($filename)
82             or croak "could not load cookie file $filename\n";
83              
84             # Set photostream_sort_mode to 'recent', trying to be robust
85             # getting all the stuff from the currently saved cookie
86 0           my @args;
87             $jar->scan(
88             sub {
89 0     0     my ($domain, $name) = @_[4, 1];
90 0 0         return unless $name eq 'photostream_sort_mode';
91 0 0         return unless $domain =~ /zooomr/i;
92 0           @args = @_;
93             },
94 0           );
95 0           $args[2] = 'recent'; # value
96 0           $jar->set_cookie(@args);
97              
98 0           $self->get_agent()->cookie_jar($jar);
99              
100 0           return;
101             } ## end sub load_cookies_from
102              
103             sub login {
104 0     0 1   my $self = shift;
105 0 0         my $args = ref($_[0]) ? $_[0] : {@_};
106              
107 0 0         $self->set_username($args->{username}) if exists $args->{username};
108 0 0         $self->set_password($args->{password}) if exists $args->{password};
109              
110 0           my $ua = $self->get_agent();
111 0 0         $ua->get($self->get_login_page())
112             or croak "couldn't get login page\n";
113 0 0         $ua->form_with_fields(qw( username password ))
114             or croak "no login form\n";
115 0           $ua->set_fields(
116             username => $self->get_username(),
117             password => $self->get_password(),
118             );
119 0 0         $ua->click()
120             or croak "no button to click\n";
121              
122 0           return;
123             } ## end sub login
124              
125             sub logout {
126 0     0 1   my $self = shift;
127 0           return $self->get_agent()->get($self->get_logout_page());
128             }
129              
130             sub _config_or_default {
131 0     0     my $self = shift;
132 0           my $href = shift;
133             map {
134 0 0         if (exists $href->{$_})
  0 0          
135             {
136 0           $href->{$_};
137             }
138             elsif (my $method = $self->can('get_' . $_)) {
139 0           scalar($self->$method());
140             }
141             else {
142 0           undef;
143             }
144             } @_;
145             } ## end sub _config_or_default
146              
147             sub upload {
148 0     0 1   my $self = shift;
149 0 0         my $config = ref($_[0]) ? $_[0] : {@_};
150              
151 0           my ($updater) = $self->_config_or_default($config, 'updater');
152 0           my $filename = $config->{filename};
153 0           my $ua = $self->get_agent();
154              
155 0           (my $barename = file($filename)->basename()) =~ s{\.\w+\z}{}mxs;
156              
157 0           my $updating;
158 0           my $uri = eval {
159 0 0         $ua->get($self->get_upload_page())
160             or croak "couldn't get upload page\n";
161              
162 0 0         $ua->form_with_fields(qw( Filedata labels is_public ))
163             or croak "no form with fields required for upload\n";
164 0   0       $ua->set_fields(
      0        
165             labels => $config->{tags} || '',
166             is_public => $config->{public} || 0,
167             Filedata => $filename,
168             );
169 0           $ua->tick('is_friend', 1, $config->{friends});
170 0           $ua->tick('is_family', 1, $config->{family});
171              
172 0 0         if ($updater) {
173 0           local $HTTP::Request::Common::DYNAMIC_FILE_UPLOAD;
174 0           $HTTP::Request::Common::DYNAMIC_FILE_UPLOAD = 1;
175 0           my $request = $ua->current_form()->click(); # Get request
176              
177 0           my $total = scalar($request->content_length());
178 0           $updater->post(
179             'start_file',
180             filename => $filename,
181             barename => $barename,
182             file_counter => $config->{file_counter},
183             file_octets => $total,
184             );
185 0           $updating = 1;
186              
187 0           my $workhorse = $request->content();
188 0           my $done = 0;
189             $request->content(
190             sub {
191 0     0     my $data_chunk = $workhorse->();
192 0 0         return unless defined $data_chunk;
193              
194 0           $done += length $data_chunk;
195 0           $updater->post('update_file', sent_octets => $done);
196              
197 0           return $data_chunk;
198             },
199 0           );
200              
201 0           $ua->request($request);
202             } ## end if ($updater)
203             else {
204 0           $ua->click();
205             }
206              
207             # Check the photo is there
208 0 0         my $link = $ua->find_link(text => $barename)
209             or croak "upload completed but no photo\n";
210 0 0         $updater->post(
211             'end_file',
212             filename => $filename,
213             uri => $link->url_abs(),
214             outcome => 'success'
215             ) if $updater;
216 0           $link->url_abs();
217             };
218 0 0         return $uri if $uri;
219              
220             # Complete stuff in updater before failing
221 0 0 0       $updater->post(
222             'end_file',
223             filename => $filename,
224             uri => undef,
225             outcome => 'failure',
226             ) if $updater && $updating;
227 0           croak $@;
228             } ## end sub upload
229              
230             __END__