Rarbg-torrentapi

Perl Module to interact with https://torrentapi.org
git clone https://git.e1e0.net/Rarbg-torrentapi.git
Log | Files | Refs | README | LICENSE

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