torrentapi.pm (7047B)
1 package Rarbg::torrentapi; 2 3 use strict; 4 use 5.008_005; 5 our $VERSION = 'v0.2.0'; 6 use LWP::UserAgent; 7 use JSON; 8 use Carp; 9 use Rarbg::torrentapi::Res; 10 use Rarbg::torrentapi::Error; 11 use Moose; 12 13 our $BASEURL = 'https://torrentapi.org/pubapi_v2.php?'; 14 our $REQUEST_LIMIT = 2; # The api has a 1req/2s limit. 15 16 has [qw(search_string search_imdb search_themoviedb search_tvdb category)] => ( 17 is => 'rw', 18 isa => 'Str' 19 ); 20 21 has limit => ( 22 is => 'rw', 23 isa => 'Int', 24 default => 25 25 ); 26 27 has sort => ( 28 is => 'rw', 29 isa => 'Str', 30 default => 'last' 31 ); 32 33 has [qw(min_seeders min_leechers)] => ( 34 is => 'rw', 35 isa => 'Int' 36 ); 37 38 has ranked => ( 39 is => 'rw', 40 isa => 'Int', 41 default => 0 42 ); 43 44 has mode => ( 45 is => 'rw', 46 isa => 'Str', 47 default => 'list' 48 ); 49 50 has app_id => ( 51 is => 'rw', 52 isa => 'Str', 53 default => 'p5-Rarbg-torrentapi' 54 ); 55 56 has _format => ( 57 is => 'ro', 58 isa => 'Str', 59 default => 'json_extended' 60 ); 61 62 has _ua => ( 63 is => 'ro', 64 default => sub { 65 LWP::UserAgent->new( agent => 'curl/7.44.0' ); 66 } 67 ); 68 69 has _token => ( 70 is => 'rw', 71 isa => 'Str', 72 default => sub { 73 my $self = shift; 74 $self->_renew_token(); 75 }, 76 required => 1, 77 lazy => 1 78 ); 79 80 has _token_time => ( 81 is => 'rw', 82 isa => 'Int', 83 default => -1, 84 ); 85 86 has _last_request => ( 87 is => 'rw', 88 isa => 'Int', 89 default => -1 90 ); 91 92 sub _renew_token { 93 my $self = shift; 94 $self->_last_request(time); 95 my $url = $BASEURL . "get_token=get_token&app_id=" . $self->app_id; 96 my $res_json = $self->_ua->get($url); 97 if ( $res_json->is_success ) { 98 $self->_token_time(time); 99 my $res = decode_json( $res_json->decoded_content ); 100 return $res->{token}; 101 } 102 else { 103 confess "Cannot get token " . $res_json->status_line; 104 } 105 } 106 107 sub _token_valid { 108 my $self = shift; 109 ( time - $self->_token_time ) < 890; 110 } 111 112 sub _make_request { 113 my $self = shift; 114 sleep $REQUEST_LIMIT if $self->_last_request != -1 && time - $self->_last_request < $REQUEST_LIMIT; 115 unless ( $self->_token_valid ) { 116 $self->_token( $self->_renew_token ); 117 sleep $REQUEST_LIMIT; 118 } 119 $self->_last_request(time); 120 my $url = $BASEURL; 121 foreach my $attribute ( $self->meta->get_attribute_list ) { 122 next if $attribute =~ /^_/; 123 if ( $self->$attribute ) { 124 $url .= "$attribute=" . $self->$attribute . "&"; 125 } 126 } 127 $url .= "format=" . $self->_format . "&"; 128 $url .= "ranked=" . $self->ranked . "&"; 129 $url .= "token=" . $self->_token; 130 my $res_json = $self->_ua->get($url); 131 if ( $res_json->is_success ) { 132 my $tresults = decode_json( $res_json->decoded_content ); 133 my @res; 134 if ( $tresults->{torrent_results} 135 && scalar( @{ $tresults->{torrent_results} } ) ) 136 { 137 foreach my $t ( @{ $tresults->{torrent_results} } ) { 138 my $t_obj = Rarbg::torrentapi::Res->new($t); 139 push @res, $t_obj; 140 } 141 return \@res; 142 } 143 else { 144 return Rarbg::torrentapi::Error->new($tresults); 145 } 146 } 147 else { 148 confess "Cannot execute Call " . $res_json->status_line; 149 } 150 } 151 152 foreach my $method (qw/list search/) { 153 __PACKAGE__->meta->add_method( 154 $method, 155 sub { 156 my $self = shift; 157 my $args = shift; 158 foreach my $key ( keys %{$args} ) { 159 $self->$key( $args->{$key} ); 160 } 161 $self->mode("$method"); 162 return $self->_make_request; 163 } 164 ); 165 } 166 167 no Moose; 168 __PACKAGE__->meta->make_immutable; 169 1; 170 __END__ 171 172 =encoding utf-8 173 174 =head1 NAME 175 176 Rarbg::torrentapi - Wrapper around Rarbg torrentapi (L<https://torrentapi.org/apidocs_v2.txt>) 177 178 =head1 SYNOPSIS 179 180 use Rarbg::torrentapi; 181 my $tapi = Rarbg::torrentapi->new(); 182 183 # list lastest torrents 184 my $last_added = $tapi->list(); 185 186 # list torrents sorted by seeders 187 my $last_added = $tapi->list({ 188 sort => 'seeders', 189 limit => 50, 190 category => 'tv' 191 }); 192 193 # search by string 194 # You can use all attributes also 195 my $search = $tapi->search({ 196 search_string => 'the beatles', 197 category => '23;24;25;26', 198 min_seeders => 20 199 }); 200 201 # search by imdb id 202 my $search = $tapi->search({ 203 search_imdb => 'tt123456' 204 }); 205 206 # search by themoviedb id 207 my $search = $tapi->search({ 208 search_themoviedb => '123456' 209 }); 210 211 # search by tvdb id 212 my $search = $tapi->search({ 213 search_tvdb => '123456' 214 }); 215 216 217 =head1 DESCRIPTION 218 219 Rarbg::torrentapi is a simple wrapper around Rarbg's torrentapi. 220 221 =head1 ATTRIBUTES 222 223 Those attributes can be used on all public methods. In fact you can use them also when creating the object. Some of them make more sense at creation time, some others when calling the method. It's your call. 224 225 The only difference is that you should pass them as an anonymous hash if you pass them to a method. 226 227 You can find more info about their values at L<https://torrentapi.org/apidocs_v2.txt> 228 229 =head2 search_string 230 231 =head2 search_imdb 232 233 This is the Imdb id (http://imdb.com) in the form 'tt123456' 234 235 =head2 search_themoviedb 236 237 =head2 search_tvdb 238 239 =head2 category 240 241 Category can be quite confusing. 242 It accepts 'tv' and 'movies'. But, for the rest of categories only accepts its id numbers (or a semi-colon separated list of them). 243 244 =over 4 245 246 =item * XXX (18+) => 4 247 248 =item * Movies/XVID => 14 249 250 =item * Movies/XVID/720 => 48 251 252 =item * Movies/x264 => 17 253 254 =item * Movies/x264/1080 => 44 255 256 =item * Movies/x264/720 => 45 257 258 =item * Movies/x264/3D => 47 259 260 =item * Movies/x264/4k => 50 261 262 =item * Movies/x265/4k => 51 263 264 =item * Movies/x264/4k/HDR => 52 265 266 =item * Movies/Full BD => 42 267 268 =item * Movies/BD Remux => 46 269 270 =item * TV Episodes => 18 271 272 =item * TV HD Episodes => 41 273 274 =item * TV UHD Episodes => 49 275 276 =item * Movies/MP3 => 23 277 278 =item * Movies/FLAC => 25 279 280 =item * Games/PC ISO => 27 281 282 =item * Games/PC RIP => 28 283 284 =item * Games/PS3 => 40 285 286 =item * Games/XBOX-360 => 32 287 288 =item * Software/PC ISO => 33 289 290 =item * Games/PS4 => 53 291 292 =back 293 294 =head2 limit 295 296 It can be 25, 50 or 100. 297 298 =head2 sort 299 300 It can be seeders, leechers or last 301 302 =head2 min_seeders 303 304 =head2 min_leechers 305 306 =head2 ranked 307 308 This marks if you want to get all indexed torrents or just the ones from rarbg team. 309 Defaults to all (0). 310 311 =head1 METHODS 312 313 =head2 new 314 315 Just a simple constructor. 316 317 =head2 search 318 319 Makes a call to the API in 'search' mode. It returns either a Rarbg::torrentapi::Error or an array of L<Rarbg::torrentapi::Res>. 320 321 =head2 list 322 323 Makes a call to the API in 'list' mode. It returns either a Rarbg::torrentapi::Error or an array of L<Rarbg::torrentapi::Res>. 324 325 =head1 AUTHORS 326 327 Paco Esteban E<lt>paco@onna.beE<gt> 328 Baptiste C. L<https://github.com/baptistecdr> 329 330 =head1 COPYRIGHT 331 332 Copyright 2015- Paco Esteban 333 334 =head1 LICENSE 335 336 This library is free software; you can redistribute it and/or modify 337 it under the same terms as Perl itself. 338 339 =cut