Fix exprimental push on reference warnings
[www-search-torrentz.git] / lib / WWW / Search / Torrentz / Result.pm
1 package WWW::Search::Torrentz::Result;
2
3 use 5.014000;
4 use strict;
5 use warnings;
6 use parent qw/WWW::SearchResult/;
7
8 our $VERSION = '0.001002';
9
10 use HTML::TreeBuilder;
11 use URI::Escape qw/uri_escape/;
12
13 sub new{
14 my ($class, %args) = @_;
15 my $self = $class->SUPER::new(@_);
16 $self->{parsed} = 0;
17
18 $self->_elem($_ => $args{$_}) for qw/title verified age size seeders leechers infohash/;
19 $self->{ua} = $args{ua};
20 $self->add_url("https://torrentz.eu/$args{infohash}");
21 $self
22 }
23
24 sub infohash { shift->_elem(infohash => @_) }
25 sub verified { shift->_elem(verified => @_) }
26 sub age { shift->_elem(age => @_) }
27 sub size { shift->_elem(size => @_) }
28 sub seeders { shift->_elem(seeders => @_) }
29 sub leechers { shift->_elem(leechers => @_) }
30
31 sub magnet{
32 my ($self, $full) = @_;
33 my $infohash = $self->infohash;
34 my $title = uri_escape $self->title;
35 my $uri = "magnet:?xt=urn:btih:$infohash&dn=$title";
36
37 $uri .= join '', map { "&tr=$_"} map { uri_escape $_ } $self->trackers if $full;
38
39 $uri
40 }
41
42 sub parse_page {
43 my $self = $_[0];
44 my $tree = HTML::TreeBuilder->new;
45 $tree->utf8_mode(1);
46 $tree->parse($self->{ua}->get($self->url)->content);
47 $tree->eof;
48
49 my $trackers = $tree->look_down(class => 'trackers');
50 $self->{trackers} //= [];
51 for my $tracker ($trackers->find('dl')) {
52 push @{$self->{trackers}}, $tracker->find('a')->as_text;
53 }
54
55 my $files = $tree->look_down(class => 'files');
56 $self->{files} //= [];
57 $self->parse_directory(scalar $files->find('li'), '');
58
59 $self->{parsed} = 1;
60 }
61
62 sub parse_directory{
63 my ($self, $directory, $prefix) = @_;
64 $prefix .= $directory->as_text . '/';
65 my $contents_ul = $directory->right->find('ul');
66 return unless defined $contents_ul; # Empty directory
67 my @children = $contents_ul->content_list;
68 my $skip = 0;
69 for my $child (@children) {
70 if ($skip) {
71 $skip = 0;
72 next;
73 }
74
75 if (defined $child->attr('class') && $child->attr('class') eq 't') {
76 $self->parse_directory($child, $prefix);
77 $skip = 1;
78 } else {
79 $child->objectify_text;
80 my ($filename, $size) = $child->find('~text');
81 push @{$self->{files}}, +{
82 path => $prefix.$filename->attr('text'),
83 size => $size->attr('text')
84 }
85 }
86 }
87 }
88
89 sub trackers{
90 my $self = $_[0];
91 $self->parse_page unless $self->{parsed};
92 @{$self->{trackers}}
93 }
94
95 sub files{
96 my $self = $_[0];
97 $self->parse_page unless $self->{parsed};
98 @{$self->{files}}
99 }
100
101 sub torrent{
102 my $self = $_[0];
103 my $torrage = 'http://torrage.com/torrent/' . uc $self->infohash . '.torrent';
104 my $torrent = $self->{ua}->get($torrage)->content;
105
106 $torrent; # TODO: if this is undef, download metadata with magnet link
107 }
108
109 1;
110 __END__
111
112 =encoding utf-8
113
114 =head1 NAME
115
116 WWW::Search::Torrentz::Result - a result of a WWW::Search::Torrentz search
117
118 =head1 SYNOPSIS
119
120 my $result = $search->next_result;
121 say 'URL: ' . $result->url;
122 say 'Title: ' . $result->title;
123 say 'Infohash: ' . $result->infohash;
124 say 'Verified: ' . $result->verified;
125 say 'Age: ' . $result->age;
126 say 'Size: ' . $result->size;
127 say 'Seeders: ' . $result->seeders;
128 say 'Leechers: ' . $result->leechers;
129 say 'Magnet link: ' . $result->magnet;
130 say 'Magnet link with trackers: ' . $result->magnet(1);
131 my @tracker_list = $result->trackers;
132 my @file_list = $result->files;
133 my $torrent_file = $result->torrent;
134
135 =head1 DESCRIPTION
136
137 WWW::Search::Torrentz::Result is the result of a WWW::Search::Torrentz search.
138
139 Useful methods:
140
141 =over
142
143 =item B<url>
144
145 Returns a link to the torrent details page.
146
147 =item B<title>
148
149 Returns the torrent's title.
150
151 =item B<infohash>
152
153 Returns the infohash of the torrent, a 40 character hex string.
154
155 =item B<verified>
156
157 Returns the verification level of this torrent, or 0 if the torrent not verified. Higher is better.
158
159 =item B<age>
160
161 Returns the torrent's age, as returned by Torrentz. Usually a string such as '4 days', 'yesterday', 'today', '2 months'.
162
163 =item B<size>
164
165 Returns the torrent's size, as returned by Torrentz. A string such as '151 MB', '25 GB'.
166
167 =item B<seeders>
168
169 Returns the number of seeders this torrent has, as returned by Torrentz.
170
171 =item B<leechers>
172
173 Returns the number of leechers this torrent has, as returned by Torrentz.
174
175 =item B<magnet>([I<include_trackers>])
176
177 Returns a magnet link that describes this torrent.
178
179 If I<include_trackers> is true, the magnet link will include the tracker list. This calls B<parse_page> if not called already.
180
181 =item B<trackers>
182
183 Returns a list of trackers for this torrent. Calls B<parse_page> if not called already.
184
185 =item B<files>
186
187 Returns a list of files this torrent includes. Calls B<parse_page> if not called already.
188
189 Each element is a hashref with two keys. C<path> is the file path and C<size> is the file size, as returned by Torrentz.
190
191 =item B<parse_page>
192
193 Downloads the details page for this torrent and extracts the tracker and file list. It is called automatically by other methods when necessary, you shouldn't have to call it yourself.
194
195 =item B<torrent>
196
197 Downloads this torrent file from Torrage. If found, it returns the contents of the torrent file. Otherwise it returns undef.
198
199 =back
200
201 =head1 SEE ALSO
202
203 =head1 AUTHOR
204
205 Marius Gavrilescu, E<lt>marius@ieval.roE<gt>
206
207 =head1 COPYRIGHT AND LICENSE
208
209 Copyright (C) 2013 by Marius Gavrilescu
210
211 This library is free software; you can redistribute it and/or modify
212 it under the same terms as Perl itself, either Perl version 5.18.1 or,
213 at your option, any later version of Perl 5 you may have available.
214
215
216 =cut
This page took 0.032465 seconds and 4 git commands to generate.