File Coverage

blib/lib/WebService/Browshot.pm
Criterion Covered Total %
statement 38 220 17.2
branch 1 50 2.0
condition 4 83 4.8
subroutine 11 41 26.8
pod 23 32 71.8
total 77 426 18.0


line stmt bran cond sub pod time code
1             package WebService::Browshot;
2              
3 1     1   138155 use 5.006006;
  1         3  
4 1     1   6 use strict;
  1         2  
  1         37  
5 1     1   5 use warnings;
  1         2  
  1         63  
6              
7 1     1   1171 use LWP::UserAgent;
  1         81676  
  1         49  
8 1     1   1120 use JSON;
  1         14382  
  1         6  
9 1     1   775 use URI::Encode qw(uri_encode);
  1         22442  
  1         88  
10 1     1   10 use File::Basename;
  1         2  
  1         103  
11 1     1   5 use File::Path qw(make_path);
  1         7  
  1         78  
12              
13             $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
14 1     1   1063 use IO::Socket::SSL;
  1         97792  
  1         9  
15             IO::Socket::SSL::set_ctx_defaults(
16             SSL_verifycn_scheme => 'www',
17             SSL_verify_mode => 0,
18             verify_mode => 0,
19             );
20              
21             our $VERSION = '1.29.0';
22              
23             =head1 NAME
24              
25             WebService::Browshot - Perl extension for Browshot (L), a web service to create screenshots of web pages.
26              
27             =head1 SYNOPSIS
28              
29             use WebService::Browshot;
30            
31             my $browshot = WebService::Browshot->new(key => 'my_key');
32             my $screenshot = $browshot->screenshot_create(url => 'http://www.google.com/');
33             [...]
34             $browshot->screenshot_thumbnail_file(id => $screenshot->{id}, file => 'google.png');
35              
36             =head1 DESCRIPTION
37              
38             Browshot (L) is a web service to easily make screenshots of web pages in any screen size, as any device: iPhone, iPad, Android, Nook, PC, etc. Browshot has full Flash, JavaScript, CSS, & HTML5 support.
39              
40             The latest API version is detailed at L. WebService::Browshot follows the API documentation very closely: the function names are similar to the URLs used (screenshot/create becomes C, instance/list becomes C, etc.), the request arguments are exactly the same, etc.
41              
42             The library version matches closely the API version it handles: WebService::Browshot 1.0.0 is the first release for the API 1.0, WebService::Browshot 1.1.1 is the second release for the API 1.1, etc.
43              
44             WebService::Browshot can handle most the API updates within the same major version, e.g. WebService::Browshot 1.0.0 should be compatible with the API 1.1 or 1.2.
45              
46             The source code is available on github at L.
47              
48              
49             =head1 METHODS
50              
51             =over 4
52              
53             =head2 new()
54              
55             my $browshot = WebService::Browshot->new(key => 'my_key', base => 'http://api.browshot.com/api/v1/', debug => 1]);
56              
57             Create a new WebService::Browshot object. You must pass your API key (go to you Dashboard to find your API key).
58              
59             Arguments:
60              
61             =over 4
62              
63             =item key
64              
65             Required. API key.
66              
67             =item base
68              
69             Optional. Base URL for all API requests. You should use the default base provided by the library. Be careful if you decide to use HTTP instead of HTTPS as your API key could be sniffed and your account could be used without your consent.
70              
71             =item debug
72              
73             Optional. Set to 1 to print debug output to the standard output. 0 (disabled) by default.
74              
75             =item timeout
76              
77             Optional. Set the request timeout - in seconds - against the API. Defaults to 90s.
78              
79             =back
80              
81             C contains the last error message, it is NEVER reset, i.e last_error may not be empty after a successful API call if an earlier call failed.
82              
83             =cut
84              
85             sub new {
86 1     1 1 185998 my ($self, %args) = @_;
87              
88 1         8 my $ua = LWP::UserAgent->new();
89 1   50     2807 $ua->timeout($args{'timeout'} || 90);
90 1         17 $ua->env_proxy;
91 1         3981 $ua->max_redirect(32); # for the simple API only
92 1         19 $ua->agent("WebService::Browshot $VERSION");
93 1         59 $ua->ssl_opts( verify_hostnames => 0 );
94              
95             my $browshot = {
96             _key => $args{key} || '',
97             _base => $args{base} || 'https://api.browshot.com/api/v1/',
98 1   50     38 _debug => $args{debug} || 0,
      50        
      50        
99              
100             _retry => 2,
101             last_error => '',
102              
103             _ua => $ua,
104             };
105              
106 1         5 return bless($browshot, $self);
107             }
108              
109              
110             =head2 api_version()
111              
112             Return the API version handled by the library. Note that this library can usually handle new arguments in requests without requiring an update.
113              
114             =cut
115              
116             sub api_version {
117 1     1 1 7 my ($self, %args) = @_;
118              
119 1 50       7 if ($VERSION =~ /^(\d+\.\d+)\.\d/) {
120 1         6 return $1;
121             }
122              
123 0           return $VERSION;
124             }
125              
126              
127              
128             =head2 simple()
129              
130             $browshot->simple(url => 'http://mobilito.net')
131              
132             Retrieve a screenshot in one function. Note: by default, screenshots are cached for 24 hours. You can tune this value with the cache=X parameter.
133              
134             Return an array (status code, PNG). See L for the list of possible status codes.
135              
136             Arguments:
137              
138             See L for the full list of possible arguments.
139              
140             =over 4
141              
142             =item url
143              
144             Required. URL of the website to create a screenshot of.
145              
146             =back
147              
148             =cut
149              
150             sub simple {
151 0     0 1   my ($self, %args) = @_;
152              
153 0           my $url = $self->make_url(action => 'simple', parameters => { %args });
154 0           my $res = $self->{_ua}->get($url);
155              
156             # $self->info($res->message);
157             # $self->info($res->request->as_string);
158             # $self->info($res->as_string);
159            
160 0           return ($res->code, $res->decoded_content);
161             }
162              
163             =head2 simple_file()
164              
165             $browshot->simple_file(url => 'http://mobilito.net', file => '/tmp/mobilito.png')
166              
167             Retrieve a screenshot and save it locally in one function. Note: by default, screenshots are cached for 24 hours. You can tune this value with the cache=X parameter.
168              
169             Return an array (status code, file name). The file name is empty if the screenshot was not retrieved. See L for the list of possible status codes.
170              
171             Arguments:
172              
173             See L for the full list of possible arguments.
174              
175             =over 4
176              
177             =item url
178              
179             Required. URL of the website to create a screenshot of.
180              
181             =item file
182              
183             Required. Local file name to write to.
184              
185             =back
186              
187             =cut
188              
189             sub simple_file {
190 0     0 1   my ($self, %args) = @_;
191 0   0       my $file = $args{file} || $self->error("Missing file in simple_file");
192            
193 0 0         if (-d $file) {
194 0           $self->error("You must specify a file path, not a folder, to save the screenshot");
195 0           return (400, '');
196             }
197              
198 0           my $url = $self->make_url(action => 'simple', parameters => { %args });
199 0           my $res = $self->{_ua}->get($url);
200              
201 0           my $content = $res->decoded_content;
202              
203 0 0         if ($content ne '') {
204 0 0         open TARGET, "> $file" or $self->error("Cannot open $file for writing: $!");
205 0           binmode TARGET;
206 0           print TARGET $content;
207 0           close TARGET;
208              
209 0           return ($res->code, $file);
210             }
211             else {
212 0           $self->error("No thumbnail retrieved");
213 0           return ($res->code, '');
214             }
215             }
216              
217             =head2 instance_list()
218              
219             Return the list of instances as a hash reference. See L for the response format.
220              
221             =cut
222              
223             sub instance_list {
224 0     0 1   my ($self, %args) = @_;
225            
226 0           return $self->return_reply(action => 'instance/list');
227             }
228              
229             =head2 instance_info()
230              
231             $browshot->instance_info(id => 2)
232              
233             Return the details of an instance. See L for the response format.
234              
235             Arguments:
236              
237             =over 4
238              
239             =item id
240              
241             Required. Instance ID
242              
243             =back
244              
245             =cut
246              
247             sub instance_info {
248 0     0 1   my ($self, %args) = @_;
249 0   0       my $id = $args{id} || $self->error("Missing id in instance_info");
250              
251 0           return $self->return_reply(action => 'instance/info', parameters => { id => $id });
252             }
253              
254             =head2 browser_list()
255              
256             Return the list of browsers as a hash reference. See L for the response format.
257              
258             =cut
259              
260             sub browser_list {
261 0     0 1   my ($self, %args) = @_;
262            
263 0           return $self->return_reply(action => 'browser/list');
264             }
265              
266             =head2 browser_info()
267              
268             $browshot->browser_info(id => 2)
269              
270             Return the details of a browser. See L for the response format.
271              
272             Arguments:
273              
274             =over 4
275              
276             =item id
277              
278             Required. Browser ID
279              
280             =back
281              
282             =cut
283              
284             sub browser_info {
285 0     0 1   my ($self, %args) = @_;
286 0   0       my $id = $args{id} || $self->error("Missing id in browser_info");
287              
288 0           return $self->return_reply(action => 'browser/info', parameters => { id => $id });
289             }
290              
291              
292             =head2 screenshot_create()
293              
294             $browshot->screenshot_create(url => 'http://wwww.google.com/', instance_id => 3, size => 'page')
295              
296             Request a screenshot. See L for the response format.
297             Note: by default, screenshots are cached for 24 hours. You can tune this value with the cache=X parameter.
298              
299             Arguments:
300              
301             See L for the full list of possible arguments.
302              
303             =over 4
304              
305             =item url
306              
307             Required. URL of the website to create a screenshot of.
308              
309             =item instance_id
310              
311             Optional. Instance ID to use for the screenshot.
312              
313             =item size
314              
315             Optional. Screenshot size.
316              
317             =back
318              
319             =cut
320              
321             sub screenshot_create {
322 0     0 1   my ($self, %args) = @_;
323             # my $url = $args{url} || $self->error("Missing url in screenshot_create");
324             # my $instance_id = $args{instance_id};
325             # my $screen = $args{screen};
326             # my $size = $args{size} || "screen";
327             # my $cache = $args{cache};
328             # my $priority = $args{priority};
329              
330 0 0         $self->error("Missing url in screenshot_create") if (! defined($args{url}));
331             # $args{size} = "screen" if (! defined($args{size}));
332              
333 0           return $self->return_reply(action => 'screenshot/create', parameters => { %args });
334             }
335              
336             =head2 screenshot_info()
337              
338             $browshot->screenshot_info(id => 568978)
339              
340             Get information about a screenshot requested previously. See L for the response format.
341              
342             Arguments:
343              
344             =over 4
345              
346             =item id
347              
348             Required. Screenshot ID.
349              
350             =back
351              
352             =cut
353              
354             sub screenshot_info {
355 0     0 1   my ($self, %args) = @_;
356 0   0       my $id = $args{id} || $self->error("Missing id in screenshot_info");
357              
358              
359 0           return $self->return_reply(action => 'screenshot/info', parameters => { %args });
360             }
361              
362             =head2 screenshot_list()
363              
364             $browshot->screenshot_list(limit => 50)
365              
366             Get details about screenshots requested. See L for the response format.
367              
368             Arguments:
369              
370             =over 4
371              
372             =item limit
373              
374             Optional. Maximum number of screenshots to retrieve.
375              
376             =back
377              
378             =cut
379              
380             sub screenshot_list {
381 0     0 1   my ($self, %args) = @_;
382              
383 0           return $self->return_reply(action => 'screenshot/list', parameters => { %args });
384             }
385              
386             =head2 screenshot_search()
387              
388             $browshot->screenshot_search(url => 'google.com')
389              
390             Get details about screenshots requested. See L for the response format.
391              
392             Arguments:
393              
394             =over 4
395              
396             =item url
397              
398             Required. URL string to look for.
399              
400             =back
401              
402             =cut
403              
404             sub screenshot_search {
405 0     0 1   my ($self, %args) = @_;
406 0   0       my $url = $args{url} || $self->error("Missing url in screenshot_search");
407              
408 0           return $self->return_reply(action => 'screenshot/search', parameters => { %args });
409             }
410              
411             =head2 screenshot_host()
412              
413             $browshot->screenshot_host(id => 12345, hosting => 'browshot')
414              
415             Host a screenshot or thumbnail. See L for the response format.
416              
417             Arguments:
418              
419             =over 4
420              
421             =item id
422              
423             Required. Screenshot ID.
424              
425             =back
426              
427             =cut
428              
429             sub screenshot_host {
430 0     0 1   my ($self, %args) = @_;
431 0   0       my $id = $args{id} || $self->error("Missing id in screenshot_host");
432              
433 0           return $self->return_reply(action => 'screenshot/host', parameters => { %args });
434             }
435              
436              
437             =head2 screenshot_thumbnail()
438              
439             $browshot->screenshot_thumbnail(id => 52942, width => 500)
440              
441             Retrieve the screenshot, or a thumbnail. See L for the response format.
442              
443             Return an empty string if the image could not be retrieved.
444              
445             Arguments:
446              
447             See L for the full list of possible arguments.
448              
449             =over 4
450              
451             =item id
452              
453             Required. Screenshot ID.
454              
455             =item width
456              
457             Optional. Maximum width of the thumbnail.
458              
459             =item height
460              
461             Optional. Maximum height of the thumbnail.
462              
463             =back
464              
465             =cut
466             sub screenshot_thumbnail {
467 0     0 1   my ($self, %args) = @_;
468              
469 0 0 0       if (exists($args{url}) && $args{url} =~ /image\/(\d+)\?/i && ! exists($args{id})) {
    0 0        
470             # get ID from url
471 0           $args{id} = $1;
472              
473 0 0 0       if ($args{url} =~ /&width=(\d+)\?/i && ! exists($args{width})) {
474 0           $args{width} = $1;
475             }
476 0 0 0       if ($args{url} =~ /&height=(\d+)\?/i && ! exists($args{height})) {
477 0           $args{height} = $1;
478             }
479            
480             }
481             elsif(! exists($args{id}) ) {
482 0           $self->error("Missing id and url in screenshot_thumbnail");
483 0           return '';
484             }
485              
486              
487 0           my $url = $self->make_url(action => 'screenshot/thumbnail', parameters => { %args });
488 0           my $res = $self->{_ua}->get($url);
489              
490 0 0         if ($res->is_success) {
491 0           return $res->decoded_content; # raw image file content
492             }
493             else {
494 0           $self->error("Error in thumbnail request: " . $res->as_string);
495 0           return '';
496             }
497             }
498              
499              
500             =head2 screenshot_thumbnail_file()
501              
502             $browshot->screenshot_thumbnail_file(id => 123456, height => 500, file => '/tmp/google.png')
503              
504             Retrieve the screenshot, or a thumbnail, and save it to a file. See L for the response format.
505              
506             Return an empty string if the image could not be retrieved or not saved. Returns the file name if successful.
507              
508             Arguments:
509              
510             See L for the full list of possible arguments.
511              
512             =over 4
513              
514             =item url
515              
516             Required. URL of the screenshot (screenshot_url value retrieved from C or C). You will get the full image if no other argument is specified.
517              
518             =item file
519              
520             Required. Local file name to write to.
521              
522             =item width
523              
524             Optional. Maximum width of the thumbnail.
525              
526             =item height
527              
528             Optional. Maximum height of the thumbnail.
529              
530             =back
531              
532             =cut
533             sub screenshot_thumbnail_file {
534 0     0 1   my ($self, %args) = @_;
535 0   0       my $file = $args{file} || $self->error("Missing file in screenshot_thumbnail_file");
536              
537 0           delete($args{file});
538 0           my $content = $self->screenshot_thumbnail(%args);
539              
540 0           my $dir = dirname($file);
541 0 0         if (! -d $dir) {
542 0           make_path($dir)
543             }
544              
545 0 0         if ($content ne '') {
546 0 0         open TARGET, "> $file" or $self->error("Cannot open $file for writing: $!");
547 0           binmode TARGET;
548 0           print TARGET $content;
549 0           close TARGET;
550              
551 0           return $file;
552             }
553             else {
554 0           $self->error("No thumbnail retrieved");
555 0           return '';
556             }
557             }
558              
559             =head2 screenshot_share()
560              
561             $browshot->screenshot_share(id => 12345, note => 'This is my screenshot')
562              
563             Share a screenshot. See L for the response format.
564              
565             Arguments:
566              
567             =over 4
568              
569             =item id
570              
571             Required. Screenshot ID.
572              
573             =item note
574              
575             Optional. Public note to add to the screenshot.
576              
577             =back
578              
579             =cut
580              
581             sub screenshot_share {
582 0     0 1   my ($self, %args) = @_;
583 0   0       my $id = $args{id} || $self->error("Missing id in screenshot_share");
584              
585 0           return $self->return_reply(action => 'screenshot/share', parameters => { %args });
586             }
587              
588              
589             =head2 screenshot_delete()
590              
591             $browshot->screenshot_delete(id => 12345, data => 'url,metadata')
592              
593             Delete details of a screenshot. See L for the response format.
594              
595             Arguments:
596              
597             =over 4
598              
599             =item id
600              
601             Required. Screenshot ID.
602              
603             =item data
604              
605             Optional. Information to delete.
606              
607             =back
608              
609             =cut
610              
611             sub screenshot_delete {
612 0     0 1   my ($self, %args) = @_;
613 0   0       my $id = $args{id} || $self->error("Missing id in screenshot_delete");
614              
615 0           return $self->return_reply(action => 'screenshot/delete', parameters => { %args });
616             }
617              
618             =head2 screenshot_html()
619              
620             $browshot->screenshot_html(id => 12345)
621              
622             Get the HTML code of the rendered page. See L for the response format.
623              
624             Arguments:
625              
626             =over 4
627              
628             =item id
629              
630             Required. Screenshot ID.
631              
632             =back
633              
634             =cut
635              
636             sub screenshot_html {
637 0     0 1   my ($self, %args) = @_;
638 0   0       my $id = $args{id} || $self->error("Missing id in screenshot_html");
639              
640 0           return $self->return_string(action => 'screenshot/html', parameters => { %args });
641             }
642              
643             =head2 screenshot_multiple()
644              
645             $browshot->screenshot_multiple(urls => ['http://mobilito.net/'], instances => [22, 30])
646              
647             Request multiple screenshots. See L for the response format.
648              
649             Arguments:
650              
651             =over 4
652              
653             =item urls
654              
655             Required. One or more URLs.
656              
657             =item instances
658              
659             Required. One or more instance_id.
660              
661             =back
662              
663             =cut
664              
665             sub screenshot_multiple {
666 0     0 1   my ($self, %args) = @_;
667             # my $urls = $args{urls} || $self->error("Missing urls in screenshot_multiple");
668             # my $instances = $args{instances} || $self->error("Missing instances in screenshot_multiple");
669              
670 0           return $self->return_reply(action => 'screenshot/multiple', parameters => { %args });
671             }
672              
673              
674             =head2 batch_create()
675              
676             $browshot->batch_create(file => '/my/file/urls.txt', instance_id => 65)
677              
678             Request multiple screenshots from a text file. See L for the response format.
679              
680             Arguments:
681              
682             =over 4
683              
684             =item file
685              
686             Required. Path to the text file which contains the list of URLs.
687              
688             =item instance_id
689              
690             Required. instance_id to use for all screenshots.
691              
692             =back
693              
694             =cut
695              
696             sub batch_create {
697 0     0 1   my ($self, %args) = @_;
698 0   0       my $file = $args{file} || $self->error("Missing file in batch_create");
699 0   0       my $instance_id = $args{instance_id} || $self->error("Missing instance_id in batch_create");
700              
701 0           delete $args{file};
702 0           return $self->return_post_reply(action => 'batch/create', parameters => { %args }, file => $file);
703             }
704              
705             =head2 batch_info()
706              
707             $browshot->batch_info(id => 5)
708              
709             Get information about a screenshot batch requested previously. See L for the response format.
710              
711             Arguments:
712              
713             =over 4
714              
715             =item id
716              
717             Required. Batch ID.
718              
719             =back
720              
721             =cut
722              
723             sub batch_info {
724 0     0 1   my ($self, %args) = @_;
725 0   0       my $id = $args{id} || $self->error("Missing id in batch_info");
726              
727 0           return $self->return_reply(action => 'batch/info', parameters => { %args });
728             }
729              
730              
731             =head2 crawl_create()
732              
733             $browshot->crawl_create(domain => 'blitapp.com', url => 'https://blitapp.com/', max => 50, instance_id => 65)
734              
735             Crawl a domain and screenshot all pages. See L for the response format.
736              
737             Arguments:
738              
739             =over 4
740              
741             =item domain
742              
743             Required. Domain to crawl.
744              
745             =item url
746              
747             Required. URl to start with.
748              
749             =item instance_id
750              
751             Required. instance_id to use for all screenshots.
752              
753             =back
754              
755             =cut
756              
757             sub crawl_create {
758 0     0 1   my ($self, %args) = @_;
759 0   0       my $domain = $args{domain} || $self->error("Missing domain in crawl_create");
760 0   0       my $url = $args{url} || $self->error("Missing url in crawl_create");
761 0   0       my $instance_id = $args{instance_id} || $self->error("Missing instance_id in crawl_create");
762              
763 0           return $self->return_reply(action => 'crawl/create', parameters => { %args });
764             }
765              
766             =head2 crawl__info()
767              
768             $browshot->crawl__info(id => 5)
769              
770             Get information about a crawl_ requested previously. See L for the response format.
771              
772             Arguments:
773              
774             =over 4
775              
776             =item id
777              
778             Required. Crawl ID.
779              
780             =back
781              
782             =cut
783              
784             sub crawl_info {
785 0     0 0   my ($self, %args) = @_;
786 0   0       my $id = $args{id} || $self->error("Missing id in crawl_info");
787              
788 0           return $self->return_reply(action => 'crawl/info', parameters => { %args });
789             }
790              
791             =head2 account_info()
792              
793             Return information about the user account. See L for the response format.
794              
795             =cut
796              
797             sub account_info {
798 0     0 1   my ($self, %args) = @_;
799            
800 0           return $self->return_reply(action => 'account/info', parameters => { %args });
801             }
802              
803              
804             # Private methods
805              
806             sub return_string {
807 0     0 0   my ($self, %args) = @_;
808              
809 0           my $url = $self->make_url(%args);
810            
811 0           my $res;
812 0           my $try = 0;
813              
814             do {
815 0           $self->info("Try $try");
816 0           eval {
817 0           $res = $self->{_ua}->get($url);
818             };
819 0 0         $self->error($@) if ($@);
820 0           $try++;
821             }
822 0   0       until($try < $self->{_retry} && defined $@);
823              
824 0 0         if (! $res->is_success) {
825 0           $self->error("Server sent back an error: " . $res->code);
826             }
827            
828 0           return $res->decoded_content;
829             }
830              
831             sub return_post_string {
832 0     0 0   my ($self, %args) = @_;
833 0   0       my $file = $args{'file'} || '';
834              
835 0           delete $args{'file'};
836 0           my $url = $self->make_url(%args);
837            
838 0           my $res;
839 0           my $try = 0;
840              
841             do {
842 0           $self->info("Try $try");
843 0           eval {
844             $res = $self->{_ua}->post(
845 0           $url,
846             Content_Type => 'form-data',
847             Content => [
848             file => [$file],
849             ]
850             );
851             };
852 0 0         $self->error($res->request->as_string) if ($@);
853 0 0         $self->error($@) if ($@);
854 0           $try++;
855             }
856 0   0       until($try < $self->{_retry} && defined $@);
857              
858 0 0         if (! $res->is_success) {
859 0           $self->error("Server sent back an error: " . $res->code);
860 0           $self->info($res->request->as_string);
861 0           $self->info($res->as_string);
862             }
863            
864 0           return $res->decoded_content;
865             }
866              
867             sub return_reply {
868 0     0 0   my ($self, %args) = @_;
869              
870 0           my $content = $self->return_string(%args);
871              
872 0           my $info;
873 0           eval {
874 0           $info = decode_json($content);
875             };
876 0 0         if ($@) {
877 0           $self->error("Invalid server response: " . $@);
878 0           return $self->generic_error($@);
879             }
880              
881 0           return $info;
882             }
883              
884             sub return_post_reply {
885 0     0 0   my ($self, %args) = @_;
886              
887 0           my $content = $self->return_post_string(%args);
888              
889 0           my $info;
890 0           eval {
891 0           $info = decode_json($content);
892             };
893 0 0         if ($@) {
894 0           $self->error("Invalid server response: " . $@);
895 0           return $self->generic_error($@);
896             }
897              
898 0           return $info;
899             }
900              
901             sub make_url {
902 0     0 0   my ($self, %args) = @_;
903 0   0       my $action = $args{action} || '';
904 0   0       my $parameters = $args{parameters} || { };
905              
906 0           my $url = $self->{_base} . "$action?key=" . uri_encode($self->{_key}, 1);
907              
908              
909 0 0         if (exists $parameters->{urls}) {
910 0           foreach my $uri (@{ $parameters->{urls} }) {
  0            
911 0           $url .= '&url=' . uri_encode($uri, 1);
912             }
913 0           delete $parameters->{urls};
914             }
915              
916 0 0         if (exists $parameters->{instances}) {
917 0           foreach my $instance_id (@{ $parameters->{instances} }) {
  0            
918 0           $url .= '&instance_id=' . uri_encode($instance_id, 1);
919             }
920 0           delete $parameters->{instances};
921             }
922              
923 0           foreach my $key (keys %$parameters) {
924 0 0         $url .= '&' . uri_encode($key) . '=' . uri_encode($parameters->{$key}, 1) if (defined $parameters->{$key});
925             }
926              
927 0           $self->info($url);
928 0           return $url;
929             }
930              
931             sub info {
932 0     0 0   my ($self, $message) = @_;
933              
934 0 0         if ($self->{_debug}) {
935 0           print $message, "\n";
936             }
937              
938 0           return '';
939             }
940              
941             sub error {
942 0     0 0   my ($self, $message) = @_;
943              
944 0           $self->{last_error} = $message;
945              
946 0 0         if ($self->{_debug}) {
947 0           print $message, "\n";
948             }
949              
950 0           return '';
951             }
952              
953             sub generic_error {
954 0     0 0   my ($self, $message) = @_;
955              
956              
957 0           return { error => 1, message => $message };
958             }
959              
960             =head1 CHANGES
961              
962             =over 4
963              
964             =item 1.24.0
965              
966             C creates the directory structure as needed.
967              
968             =item 1.16.0
969              
970             Check if the file is not a folder in simple_file
971              
972             =item 1.14.1
973              
974             Remove deprecated API calls.
975              
976             =item 1.14.0
977              
978             Add C and C for API 1.14.
979              
980             =item 1.13.0
981              
982             Add C and C for API 1.13.
983              
984             =item 1.12
985              
986             Add C for API 1.12.
987              
988             =item 1.11.1
989              
990             Return Browshot response in case of error if the reply is valid JSON.
991              
992             =item 1.11
993              
994             Compatible with API 1.11. Optional HTTP timeout.
995              
996             =item 1.10
997              
998             Add C for API 1.10.
999              
1000             =item 1.9.4
1001              
1002             Fix status code in error messages.
1003              
1004             =item 1.9.3
1005              
1006             Keep backward compatibility for C.
1007              
1008             =item 1.9.0
1009              
1010             Add C for API 1.9.
1011              
1012             =item 1.8.0
1013              
1014             Update C to use new API.
1015              
1016             =item 1.7.0
1017              
1018             Update C to handle additional parameters
1019              
1020             =item 1.5.1
1021              
1022             Use binmode to create valid PNG files on Windows.
1023              
1024             =item 1.4.1
1025              
1026             Fix URI encoding.
1027              
1028             =item 1.4.0
1029              
1030             Add C and C methods.
1031              
1032             =item 1.3.1
1033              
1034             Retry requests (up to 2 times) to browshot.com in case of error
1035              
1036             =back
1037              
1038             =head1 SEE ALSO
1039              
1040             See L for the API documentation.
1041              
1042             Create a free account at L to get your free API key.
1043              
1044             Go to L to find your API key after you registered.
1045              
1046             =head1 AUTHOR
1047              
1048             Julien Sobrier, Ejulien@sobrier.netE
1049              
1050             =head1 COPYRIGHT AND LICENSE
1051              
1052             Copyright (C) 2015 by Julien Sobrier
1053              
1054             This library is free software; you can redistribute it and/or modify
1055             it under the same terms as Perl itself, either Perl version 5.8.8 or,
1056             at your option, any later version of Perl 5 you may have available.
1057              
1058              
1059             =cut
1060              
1061             1;