File Coverage

blib/lib/FilmAffinity/UserRating.pm
Criterion Covered Total %
statement 28 30 93.3
branch n/a
condition n/a
subroutine 10 10 100.0
pod n/a
total 38 40 95.0


line stmt bran cond sub pod time code
1             package FilmAffinity::UserRating;
2              
3 1     1   15631 use 5.006;
  1         3  
  1         30  
4 1     1   5 use strict;
  1         1  
  1         24  
5 1     1   4 use warnings;
  1         4  
  1         22  
6              
7 1     1   1008 use Encode;
  1         8260  
  1         63  
8 1     1   534 use Readonly;
  1         2360  
  1         46  
9 1     1   510 use Text::Trim;
  1         431  
  1         50  
10 1     1   514 use LWP::RobotUA;
  1         110187  
  1         36  
11 1     1   814 use HTML::TreeBuilder;
  1         26335  
  1         9  
12 1     1   731 use HTML::TreeBuilder::XPath;
  1         26521  
  1         11  
13              
14 1     1   259 use Moose;
  0            
  0            
15             use MooseX::Privacy;
16              
17             use FilmAffinity::Utils qw/buildRobot demoronize/;
18              
19             =head1 NAME
20              
21             FilmAffinity::UserRating - Perl interface to FilmAffinity
22              
23             =head1 VERSION
24              
25             Version 0.09
26              
27             =cut
28              
29             our $VERSION = '0.09';
30              
31             =head1 SYNOPSIS
32              
33             Get filmaffinity voted movies from a user
34              
35             use FilmAffinity::UserRating;
36              
37             my $parser = FilmAffinity::UserRating->new( userID => '123456' );
38              
39             my $ref_movies = $parser->parse();
40              
41             Via the command-line program filmaffinity-get-ratings.pl
42              
43             =head1 DESCRIPTION
44              
45             =head2 Overview
46              
47             FilmAffinity::UserRating is a Perl interface to FilmAffinity. You can use
48             this module to retrieve your rated movies.
49              
50             =head2 Constructor
51              
52             =over 4
53              
54             =item new()
55              
56             Object's constructor. You should pass as parameter the userID
57              
58             my $parser = FilmAffinity::UserRating->new( userID => '123456' );
59              
60             =back
61              
62             =head2 Options
63              
64             =over 4
65              
66             =item delay
67              
68             Set the minimum delay between requests to the server, in seconds.
69              
70             my $parser = FilmAffinity::UserRating->new(
71             userID => '123456',
72             delay => 20,
73             );
74              
75             By default, the delay is 5 seconds
76              
77             =back
78              
79             =head1 ACCESSORS
80              
81             =head2 $parser->userID
82              
83             get userID
84              
85             =cut
86              
87             has userID => (
88             is => 'ro',
89             isa => 'Int',
90             required => 1,
91             );
92              
93             =head2 $parser->username
94              
95             get username
96              
97             =cut
98              
99             has username => (
100             is => 'ro',
101             isa => 'Str',
102             writer => 'p_username',
103             );
104              
105             =head2 $parser->movies
106              
107             get movies
108              
109             =cut
110              
111             has movies => (
112             is => 'rw',
113             isa => 'HashRef[Str]',
114             default => sub { {} },
115             );
116              
117             has ua => (
118             is => 'rw',
119             isa => 'LWP::RobotUA',
120             traits => [qw/Private/],
121             );
122              
123             Readonly my $SECONDS => 5;
124             my $RATING_URL = 'http://www.filmaffinity.com/en/userratings.php?orderby=2&';
125             my $XPATH_ID = '//div[@class="user-ratings-movie-item"]/div/@data-movie-id';
126             my $XPATH_TITLE = '//div[@class="mc-title"]/a';
127             my $XPATH_RATING = '//div[@class="ur-mr-rat"]';
128              
129             sub BUILD {
130             my ($self, $args) = @_;
131              
132             $self->ua( buildRobot( $args->{delay} || $SECONDS ) );
133              
134             return;
135             }
136              
137             =head1 SUBROUTINES/METHODS
138              
139             =head2 $parser->parse()
140              
141             This function parses all rating pages of filmaffinity from a user.
142              
143             my $ref_movies = $parser->parse();
144              
145             =cut
146              
147             sub parse {
148             my $self = shift;
149              
150             my ($next, $page) = (1, 1);
151             while ( $next ){
152             my $url = $self->p_buildUrl( $page );
153             my $response = $self->ua->get($url);
154             if ($response->is_success){
155             my $content = $response->decoded_content();
156             $self->parseString($content);
157             $next = $self->p_isNextPage($content);
158             $page++;
159             } else {
160             $next = 0;
161             }
162             }
163             return $self->movies;
164             }
165              
166             =head2 $parser->parseString($content)
167              
168             This function parses a page of filmaffinity that is available as
169             a single string in memory.
170              
171             $parser->parseString($content);
172              
173             =cut
174              
175             sub parseString {
176             my ($self, $content) = @_;
177              
178             $content = demoronize($content);
179             $content = decode('iso8859-1', $content);
180              
181             my $tree = HTML::TreeBuilder->new();
182             $tree->parse($content);
183             $self->p_username($tree->findvalue( '//span[@id="nick"]' ));
184              
185             my @ids = $tree->findnodes_as_strings( $XPATH_ID );
186             my @titles = $tree->findnodes_as_strings( $XPATH_TITLE );
187             my @ratings = $tree->findnodes_as_strings( $XPATH_RATING );
188              
189             $self->p_buildMovieInfo(\@ids, \@titles, \@ratings);
190              
191             $tree->delete();
192             return;
193             }
194              
195             private_method p_buildUrl => sub {
196             my ($self, $page) = @_;
197              
198             return $RATING_URL.'p='.$page.'&user_id='.$self->userID;
199             };
200              
201             private_method p_buildMovieInfo => sub {
202             my ($self, $ref_ids, $ref_titles, $ref_ratings) = @_;
203              
204             for my $i (0..(@{$ref_titles}-1)){
205             $self->movies->{${$ref_ids}[$i]} = {
206             'title' => demoronize(${$ref_titles}[$i]),
207             'rating' => ${$ref_ratings}[$i],
208             }
209             }
210             };
211              
212             private_method p_isNextPage => sub {
213             my ($self, $content) = @_;
214              
215             if ($content =~ m/>&gt;&gt;<\/a><\/div><\/div>/xms){
216             return 1;
217             }
218             return 0;
219             };
220              
221             =head1 AUTHOR
222              
223             William Belle, C<< <william.belle at gmail.com> >>
224              
225             =head1 BUGS AND LIMITATIONS
226              
227             Please report any bugs or feature requests to C<bug-filmaffinity-userrating at rt.cpan.org>, or through
228             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=FilmAffinity-UserRating>. I will be notified, and then you'll
229             automatically be notified of progress on your bug as I make changes.
230              
231             =head1 SUPPORT
232              
233             You can find documentation for this module with the perldoc command.
234              
235             perldoc FilmAffinity::UserRating
236              
237              
238             You can also look for information at:
239              
240             =over 4
241              
242             =item * RT: CPAN's request tracker (report bugs here)
243              
244             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=FilmAffinity-UserRating>
245              
246             =item * AnnoCPAN: Annotated CPAN documentation
247              
248             L<http://annocpan.org/dist/FilmAffinity-UserRating>
249              
250             =item * CPAN Ratings
251              
252             L<http://cpanratings.perl.org/d/FilmAffinity-UserRating>
253              
254             =item * Search CPAN
255              
256             L<http://search.cpan.org/dist/FilmAffinity-UserRating/>
257              
258             =back
259              
260             =head1 SEE ALSO
261              
262             L<http://www.filmaffinity.com>
263              
264             =head1 LICENSE AND COPYRIGHT
265              
266             Copyright 2013 William Belle.
267              
268             This program is free software; you can redistribute it and/or modify it
269             under the terms of either: the GNU General Public License as published
270             by the Free Software Foundation; or the Artistic License.
271              
272             See http://dev.perl.org/licenses/ for more information.
273              
274             =cut
275              
276             1; # End of FilmAffinity::UserRating