File Coverage

blib/lib/WWW/SubDB.pm
Criterion Covered Total %
statement 9 11 81.8
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 13 15 86.6


line stmt bran cond sub pod time code
1             package WWW::SubDB;
2              
3 1     1   12648 use 5.006;
  1         2  
4 1     1   3 use strict;
  1         1  
  1         19  
5 1     1   3 use warnings;
  1         4  
  1         20  
6 1     1   298 use Mouse;
  0            
  0            
7             use LWP::UserAgent;
8             use HTTP::Request;
9             use HTTP::Request::Common;
10             use Digest::MD5 qw(md5_hex);
11             use Params::Validate qw(:all);
12              
13              
14             has '_endpoint' => (
15             isa => 'Str',
16             is =>'ro',
17             lazy_build => 1,
18             );
19              
20             has 'error' => (
21             isa => 'Maybe[Str]',
22             is => 'rw',
23             default => undef,
24             );
25              
26             has '_user_agent' => (
27             isa => 'Str',
28             is => 'ro',
29             default => 'SubDB/1.0 (WWW::SubDB/0.1;)'
30             );
31              
32             has 'http_status' => (
33             isa => 'Maybe[Str]',
34             is =>'rw',
35             default => undef,
36             );
37              
38             has 'debug' => (
39             isa => 'Int',
40             is => 'rw',
41             default => 0
42             );
43              
44              
45             sub _build__endpoint {
46             my($self) = @_;
47             return 'http://sandbox.thesubdb.com/' if ($self->debug);
48             return 'http://api.thesubdb.com/';
49             }
50              
51              
52              
53              
54              
55             =head1 NAME
56              
57             WWW::SubDB - Interface to thesubdb.com API
58              
59             =head1 VERSION
60              
61             Version 0.01
62              
63             =cut
64              
65             our $VERSION = '0.01';
66              
67              
68             =head1 SYNOPSIS
69              
70             This module is an interface to L API. It allows to search and download subtitles based on movie file hashes.
71              
72             use WWW::SubDB;
73              
74             my $subdb = WWW::SubDB->new();
75             ...
76              
77              
78             =head1 SUBROUTINES/METHODS
79              
80             =head2 new
81              
82             my $subdb = WWW::SubDB->new()
83              
84             my $subdb = WWW::SubDB->new( debug => 1 )
85              
86             Initializes the object, with debug = 1, the sandbox SubDB API will be used
87              
88             =cut
89              
90              
91              
92             =head2 languages
93              
94             my $lang = $subdb->languages()
95              
96             Returns the list of languages supported by SubDB. The result is a string with languages separated by (,). Ex: en,es,fr,it,nl,pl,pt,ro,sv,tr
97              
98             =cut
99              
100              
101             =head2 search
102              
103             my $file = 'movie.mp4'
104              
105             my $result = $subdb->languages($file [,$versions])
106              
107              
108             Returns a list of available subtitle languages for a given file. if $versions is set to 1, returns the number of available versions for each language. If there are no subtitles available, it will return undef.
109              
110              
111             =cut
112              
113              
114             sub languages {
115             my ($self) = @_;
116             my $request = HTTP::Request->new('GET', $self->_endpoint .'?action=languages');
117             return $self->_do_request($request);
118             }
119              
120             sub search {
121             my ($self, $file, $versions) = @_;
122             shift @_;
123             validate_pos(@_, { type => SCALAR }, { type => SCALAR , optional => 1 });
124             $versions ||= 0;
125              
126             return undef if (!$self->_valid_file($file));
127              
128             my $file_hash = $self->_file_hash($file);
129             my $url = $self->_endpoint . '?action=search&hash=' . $file_hash;
130             if ( $versions ) {
131             $url .='&versions';
132             }
133             my $request = HTTP::Request->new('GET', $url );
134             return $self->_do_request($request);
135             }
136              
137             =head2 download
138              
139             my $file = 'movie.mp4';
140             my $langs = 'en,pt';
141             my $subtitle = $subdb->download($file, $langs);
142              
143             Return the subtitle for a given movie. It will return the first language found according to $langs. Will return undef if not found.
144              
145              
146             =cut
147              
148             sub download {
149             my ($self, $file, @langs) = @_;
150             shift @_;
151             validate_pos(@_, { type => SCALAR }, { type => SCALAR } );
152             my $lang = join(',', @langs);
153             return undef if (!$self->_valid_file($file));
154             my $file_hash = $self->_file_hash($file);
155             my $url = $self->_endpoint . '?action=download&hash=' . $file_hash .'&language=' . $lang;
156             my $request = HTTP::Request->new('GET', $url );
157             return $self->_do_request($request);
158              
159             }
160              
161             =head2 upload
162              
163             my $file = 'movie.mp4';
164             my $subtitle = 'movie.srt';
165              
166             my $uploaded = $subdb->upload($file, $subtitle);
167              
168              
169             Will upload the subtitle file for the the given movie file.
170              
171              
172             =cut
173              
174             =head2 http_status
175              
176             $subdb->http_status()
177              
178             Will show the last HTTP status code
179              
180             =cut
181              
182             =head2 error
183              
184             $subdb->error()
185              
186             Will show the last HTTP status line in case there was an error
187              
188             =cut
189              
190             sub upload {
191             my ($self, $file, $subtitle_file) = @_;
192              
193             return undef if (!$self->_valid_file);
194             my $file_hash = $self->_file_hash($file);
195             my $request = POST $self->_endpoint .'?action=upload', Content_Type => 'form-data', Content => [ hash => $file_hash, file => [$subtitle_file, 'subtitle.srt', 'Content-type' => 'application/octet-stream'] ] ;
196             return $self->_do_request($request);
197             }
198              
199              
200             sub _valid_file {
201             my ($self, $file) = @_;
202             if (!-e $file) {
203             $self->_file_error( $file . ' not found');
204             return 0;
205             }
206             if (!open(my $fh, "<", $file)) {
207             $self->_file_error($file .' ' . $!);
208             return 0;
209             }
210             return 1;
211             }
212              
213             sub _file_error {
214             my ($self, $error) =@_;
215             $self->http_status('400');
216             $self->error($error);
217             return 1;
218             }
219              
220              
221              
222              
223             sub _file_hash {
224             my ($self, $f) = @_;
225              
226             my @stat = stat ($f);
227             my $f_size = $stat[7];
228             my $nbytes = 64*1024;
229              
230             my $data;
231             my $r;
232             open(my $fh , "<", $f);
233             read($fh, $r, $nbytes);
234             $data .=$r;
235             seek($fh,$f_size-$nbytes, 0);
236             read($fh, $r, $nbytes );
237             $data .= $r;
238             close($fh);
239              
240             return md5_hex($data);
241              
242             }
243              
244             sub _do_request {
245             my ($self, $request) = @_;
246             $self->http_status('');
247             $self->error(undef);
248              
249             $request->header('User-Agent' => $self->_user_agent);
250              
251             my $ua = LWP::UserAgent->new();
252             my $response = $ua->request($request);
253             $self->http_status($response->code);
254             if ($response->is_success) {
255             return $response->decoded_content;
256             } else {
257             $self->error($response->status_line);
258             return undef;
259             }
260             }
261              
262              
263             =head1 AUTHOR
264              
265             Bruno Martins, C<< <=bscmartins at gmail.com> >>
266              
267             L
268              
269             L
270              
271             =head1 BUGS
272              
273             Please report any bugs or feature requests at L
274              
275             =head1 SUPPORT
276              
277             You can find documentation for this module with the perldoc command.
278              
279             perldoc WWW::SubDB
280              
281              
282             =cut
283              
284              
285             =head1 LICENSE AND COPYRIGHT
286              
287             Copyright 2016 Bruno Martins.
288              
289             This program is free software; you can redistribute it and/or modify it
290             under the terms of either: the GNU General Public License as published
291             by the Free Software Foundation; or the Artistic License.
292              
293             See http://dev.perl.org/licenses/ for more information.
294              
295              
296             =cut
297              
298             1; # End of WWW::SubDB