Advertisement
Guest User

browshot.pm

a guest
Mar 28th, 2012
55
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.72 KB | None | 0 0
  1. package WebService::Browshot;
  2.  
  3. use 5.006006;
  4. use strict;
  5. use warnings;
  6.  
  7. use LWP::UserAgent;
  8. use JSON;
  9. use URI::Encode qw(uri_encode);
  10.  
  11. our $VERSION = '1.6.0';
  12.  
  13. =head1 NAME
  14.  
  15. WebService::Browshot - Perl extension for Browshot (L<http://www.browshot.com/>), a web service to create website screenshots.
  16.  
  17. =head1 SYNOPSIS
  18.  
  19. use WebService::Browshot;
  20.  
  21. my $browshot = WebService::Browshot->new(key => 'my_key');
  22. my $screenshot = $browshot->screenshot_create(url => 'http://www.google.com/');
  23. [...]
  24. $browshot->screenshot_thumbnail_file(id => $screenshot->{id}, file => 'google.png');
  25.  
  26. =head1 DESCRIPTION
  27.  
  28. Browshot (L<http://www.browshot.com/>) 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.
  29.  
  30. The latest API version is detailed at L<http://browshot.com/api/documentation>. WebService::Browshot follows the API documentation very closely: the function names are similar to the URLs used (screenshot/create becomes C<screenshot_create()>, instance/list becomes C<instance_list()>, etc.), the request arguments are exactly the same, etc.
  31.  
  32. 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.
  33.  
  34. 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.
  35.  
  36. The source code is available on github at L<https://github.com/juliensobrier/browshot-perl>.
  37.  
  38.  
  39. =head1 METHODS
  40.  
  41. =over 4
  42.  
  43. =head2 new()
  44.  
  45. my $browshot = WebService::Browshot->new(key => 'my_key', base => 'http://api.browshot.com/api/v1/', debug => 1]);
  46.  
  47. Create a new WebService::Browshot object. You must pass your API key (go to you Dashboard to find your API key).
  48.  
  49. Arguments:
  50.  
  51. =over 4
  52.  
  53. =item key
  54.  
  55. Required. API key.
  56.  
  57. =item base
  58.  
  59. 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.
  60.  
  61. =item debug
  62.  
  63. Optional. Set to 1 to print debug output to the standard output. 0 (disabled) by default.
  64.  
  65. =back
  66.  
  67. =cut
  68.  
  69. sub new {
  70. my ($self, %args) = @_;
  71.  
  72. my $ua = LWP::UserAgent->new();
  73. $ua->timeout(90);
  74. $ua->env_proxy;
  75. $ua->max_redirect(32); # for the simple API only
  76. $ua->agent("WebService::Browshot $VERSION");
  77.  
  78. my $browshot = {
  79. _key => $args{key} || '',
  80. _base => $args{base} || 'https://api.browshot.com/api/v1/',
  81. _debug => $args{debug} || 0,
  82.  
  83. _retry => 2,
  84. last_error => '',
  85.  
  86. _ua => $ua,
  87. };
  88.  
  89. return bless($browshot, $self);
  90. }
  91.  
  92.  
  93. =head2 api_version()
  94.  
  95. Return the API version handled by the library. Note that this library can usually handle new arguments in requests without requiring an update.
  96.  
  97. =cut
  98.  
  99. sub api_version {
  100. my ($self, %args) = @_;
  101.  
  102. if ($VERSION =~ /^(\d+\.\d+)\.\d/) {
  103. return $1;
  104. }
  105.  
  106. return $VERSION;
  107. }
  108.  
  109.  
  110.  
  111. =head2 simple()
  112.  
  113. $browshot->simple(url => 'http://mobilito.net')
  114.  
  115. Retrieve a screenshot in one function.
  116.  
  117. Return an aray (status code, PNG). See L<http://browshot.com/api/documentation#simple> for the list of possible status codes.
  118.  
  119. Arguments:
  120.  
  121. See L<http://browshot.com/api/documentation#simple> for the full list of possible arguments.
  122.  
  123. =over 4
  124.  
  125. =item url
  126.  
  127. Required. URL of the website to create a screenshot of.
  128.  
  129. =back
  130.  
  131. =cut
  132.  
  133. sub simple {
  134. my ($self, %args) = @_;
  135.  
  136. my $url = $self->make_url(action => 'simple', parameters => { %args });
  137. my $res = $self->{_ua}->get($url);
  138.  
  139. # $self->info($res->message);
  140. # $self->info($res->request->as_string);
  141. # $self->info($res->as_string);
  142.  
  143. return ($res->code, $res->decoded_content);
  144. }
  145.  
  146. =head2 simple_file()
  147.  
  148. $browshot->simple_file(url => 'http://mobilito.net', file => '/tmp/mobilito.png')
  149.  
  150. Retrieve a screenshot and save it localy in one function.
  151.  
  152. Return an aray (status code, file name). The file name is empty if the screenshot wasa not retrieved. See L<http://browshot.com/api/documentation#simple> for the list of possible status codes.
  153.  
  154. Arguments:
  155.  
  156. See L<http://browshot.com/api/documentation#simple> for the full list of possible arguments.
  157.  
  158. =over 4
  159.  
  160. =item url
  161.  
  162. Required. URL of the website to create a screenshot of.
  163.  
  164. =item file
  165.  
  166. Required. Local file name to write to.
  167.  
  168. =back
  169.  
  170. =cut
  171.  
  172. sub simple_file {
  173. my ($self, %args) = @_;
  174. my $file = $args{file} || $self->error("Missing file in simple_file");
  175.  
  176. my $url = $self->make_url(action => 'simple', parameters => { %args });
  177. my $res = $self->{_ua}->get($url);
  178.  
  179. my $content = $res->decoded_content;
  180.  
  181. if ($content ne '') {
  182. open TARGET, "> $file" or $self->error("Cannot open $file for writing: $!");
  183. binmode TARGET;
  184. print TARGET $content;
  185. close TARGET;
  186.  
  187. return ($res->code, $file);
  188. }
  189. else {
  190. $self->error("No thumbnail retrieved");
  191. return ($res->code, '');
  192. }
  193. }
  194.  
  195. =head2 instance_list()
  196.  
  197. Return the list of instances as a hash reference. See L<http://browshot.com/api/documentation#instance_list> for the response format.
  198.  
  199. =cut
  200.  
  201. sub instance_list {
  202. my ($self, %args) = @_;
  203.  
  204. return $self->return_reply(action => 'instance/list');
  205. }
  206.  
  207. =head2 instance_create()
  208.  
  209. Create a private instance. See L<http://browshot.com/api/documentation#instance_create> for the response format.
  210.  
  211. =cut
  212.  
  213. sub instance_create {
  214. my ($self, %args) = @_;
  215.  
  216. return $self->return_reply(action => 'instance/create', parameters => { %args });
  217. }
  218.  
  219. =head2 instance_info()
  220.  
  221. $browshot->instance_info(id => 2)
  222.  
  223. Return the details of an instance. See L<http://browshot.com/api/documentation#instance_info> for the response format.
  224.  
  225. Arguments:
  226.  
  227. =over 4
  228.  
  229. =item id
  230.  
  231. Required. Instance ID
  232.  
  233. =back
  234.  
  235. =cut
  236.  
  237. sub instance_info {
  238. my ($self, %args) = @_;
  239. my $id = $args{id} || $self->error("Missing id in instance_info");
  240.  
  241. return $self->return_reply(action => 'instance/info', parameters => { id => $id });
  242. }
  243.  
  244. =head2 browser_list()
  245.  
  246. Return the list of browsers as a hash reference. See L<http://browshot.com/api/documentation#browser_list> for the response format.
  247.  
  248. =cut
  249.  
  250. sub browser_list {
  251. my ($self, %args) = @_;
  252.  
  253. return $self->return_reply(action => 'browser/list');
  254. }
  255.  
  256. =head2 browser_info()
  257.  
  258. $browshot->browser_info(id => 2)
  259.  
  260. Return the details of a browser. See L<http://browshot.com/api/documentation#browser_info> for the response format.
  261.  
  262. Arguments:
  263.  
  264. =over 4
  265.  
  266. =item id
  267.  
  268. Required. Browser ID
  269.  
  270. =back
  271.  
  272. =cut
  273.  
  274. sub browser_info {
  275. my ($self, %args) = @_;
  276. my $id = $args{id} || $self->error("Missing id in browser_info");
  277.  
  278. return $self->return_reply(action => 'browser/info', parameters => { id => $id });
  279. }
  280.  
  281. =head2 browser_create()
  282.  
  283. Create a custom browser. See L<http://browshot.com/api/documentation#browser_create> for the response format.
  284.  
  285. =cut
  286.  
  287. sub browser_create {
  288. my ($self, %args) = @_;
  289.  
  290. return $self->return_reply(action => 'browser/create', parameters => { %args });
  291. }
  292.  
  293. =head2 screenshot_create()
  294.  
  295. $browshot->screenshot_create(url => 'http://wwww.google.com/', instance_id => 3, size => 'page')
  296.  
  297. Request a screenshot. See L<http://browshot.com/api/documentation#screenshot_create> for the response format.
  298.  
  299. Arguments:
  300.  
  301. See L<http://browshot.com/api/documentation#screenshot_create> 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. 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. $self->error("Missing url in screenshot_create") if (! defined($args{url}));
  331. # $args{size} = "screen" if (! defined($args{size}));
  332.  
  333. 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<http://browshot.com/api/documentation#screenshot_info> 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. my ($self, %args) = @_;
  356. my $id = $args{id} || $self->error("Missing id in screenshot_info");
  357.  
  358.  
  359. return $self->return_reply(action => 'screenshot/info', parameters => { id => $id });
  360. }
  361.  
  362. =head2 screenshot_list()
  363.  
  364. $browshot->screenshot_list(limit => 50)
  365.  
  366. Get details about screenshots requested. See L<http://browshot.com/api/documentation#screenshot_list> 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. my ($self, %args) = @_;
  382.  
  383. return $self->return_reply(action => 'screenshot/list', parameters => { %args });
  384. }
  385.  
  386. =head2 screenshot_thumbnail()
  387.  
  388. $browshot->screenshot_thumbnail(url => 'https://ww.browshot.com/screenshot/image/52942?key=my_key', width => 500)
  389.  
  390. Retrieve the screenshot, or a thumbnail. See L<http://browshot.com/api/documentation#thumbnails> for the response format.
  391.  
  392. Return an empty string if the image could not be retrieved.
  393.  
  394. Arguments:
  395.  
  396. See L<http://browshot.com/api/documentation#thumbnails> for the full list of possible arguments.
  397.  
  398. =over 4
  399.  
  400. =item url
  401.  
  402. Required. URL of the screenshot (screenshot_url value retrieved from C<screenshot_create()> or C<screenshot_info()>). You will get the full image if no other argument is specified.
  403.  
  404. =item width
  405.  
  406. Optional. Maximum width of the thumbnail.
  407.  
  408. =item height
  409.  
  410. Optional. Maximum height of the thumbnail.
  411.  
  412. =back
  413.  
  414. =cut
  415. sub screenshot_thumbnail {
  416. my ($self, %args) = @_;
  417. my $url = $args{url} || $self->error("Missing url in screenshot_thumbnail");
  418. my $width = $args{width};
  419. my $height = $args{height};
  420. my $zoom = $args{zoom};
  421. my $ratio = $args{ratio};
  422.  
  423.  
  424. $url .= '&width=' . uri_encode($width) if (defined $width);
  425. $url .= '&height=' . uri_encode($height) if (defined $height);
  426. $url .= '&zoom=' . uri_encode($zoom) if (defined $zoom);
  427. $url .= '&ratio=' . uri_encode($ratio) if (defined $ratio);
  428.  
  429. my $res = $self->{_ua}->get($url);
  430. if ($res->is_success) {
  431. return $res->decoded_content; # raw image file content
  432. }
  433. else {
  434. $self->error("Error in thumbnail request: " . $res->as_string);
  435. return '';
  436. }
  437. }
  438.  
  439. =head2 screenshot_thumbnail_file()
  440.  
  441. $browshot->screenshot_thumbnail_file(url => 'https://ww.browshot.com/screenshot/image/52942?key=my_key', height => 500, file => '/tmp/google.png')
  442.  
  443. Retrieve the screenshot, or a thumbnail, and save it to a file. See L<http://browshot.com/api/documentation#thumbnails> for the response format.
  444.  
  445. Return an empty string if the image could not be retrieved or not saved. Returns the file name if successful.
  446.  
  447. Arguments:
  448.  
  449. See L<http://browshot.com/api/documentation#thumbnails> for the full list of possible arguments.
  450.  
  451. =over 4
  452.  
  453. =item url
  454.  
  455. Required. URL of the screenshot (screenshot_url value retrieved from C<screenshot_create()> or C<screenshot_info()>). You will get the full image if no other argument is specified.
  456.  
  457. =item file
  458.  
  459. Required. Local file name to write to.
  460.  
  461. =item width
  462.  
  463. Optional. Maximum width of the thumbnail.
  464.  
  465. =item height
  466.  
  467. Optional. Maximum height of the thumbnail.
  468.  
  469. =back
  470.  
  471. =cut
  472. sub screenshot_thumbnail_file {
  473. my ($self, %args) = @_;
  474. my $file = $args{file} || $self->error("Missing file in screenshot_thumbnail_file");
  475.  
  476. my $content = $self->screenshot_thumbnail(%args);
  477.  
  478. if ($content ne '') {
  479. open TARGET, "> $file" or $self->error("Cannot open $file for writing: $!");
  480. binmode TARGET;
  481. print TARGET $content;
  482. close TARGET;
  483.  
  484. return $file;
  485. }
  486. else {
  487. $self->error("No thumbnail retrieved");
  488. return '';
  489. }
  490. }
  491.  
  492. =head2 account_info()
  493.  
  494. Return information about the user account. See L<http://browshot.com/api/documentation#account_info> for the response format.
  495.  
  496. =cut
  497.  
  498. sub account_info {
  499. my ($self, %args) = @_;
  500.  
  501. return $self->return_reply(action => 'account/info');
  502. }
  503.  
  504.  
  505. # Private methods
  506.  
  507. sub return_reply {
  508. my ($self, %args) = @_;
  509. # my $action = $args{action};
  510. # my $parameters = $args{parameters};
  511.  
  512. my $url = $self->make_url(%args);
  513.  
  514. my $res;
  515. my $try = 0;
  516.  
  517. do {
  518. $self->info("Try $try");
  519. eval {
  520. $res = $self->{_ua}->get($url);
  521. };
  522. $self->error($@) if ($@);
  523. $try++;
  524. }
  525. until($try < $self->{_retry} && defined $@);
  526.  
  527. if ($res->is_success) {
  528. my $info;
  529. eval {
  530. $info = decode_json($res->decoded_content);
  531. };
  532. if ($@) {
  533. $self->error("Invalid server response: " . $@);
  534. return $self->generic_error($@);
  535. }
  536.  
  537. return $info;
  538. }
  539. else {
  540. $self->error("Server sent back an error: " . $res->status_code);
  541. return $self->generic_error($res->as_string);
  542. }
  543. }
  544.  
  545. sub make_url {
  546. my ($self, %args) = @_;
  547. my $action = $args{action} || '';
  548. my $parameters = $args{parameters} || { };
  549.  
  550. my $url = $self->{_base} . "$action?key=" . uri_encode($self->{_key}, 1);
  551.  
  552. foreach my $key (keys %$parameters) {
  553. $url .= '&' . uri_encode($key) . '=' . uri_encode($parameters->{$key}, 1) if (defined $parameters->{$key});
  554. }
  555.  
  556. $self->info($url);
  557. return $url;
  558. }
  559.  
  560. sub info {
  561. my ($self, $message) = @_;
  562.  
  563. if ($self->{_debug}) {
  564. print $message, "\n";
  565. }
  566.  
  567. return '';
  568. }
  569.  
  570. sub error {
  571. my ($self, $message) = @_;
  572.  
  573. $self->{last_error} = $message;
  574.  
  575. if ($self->{_debug}) {
  576. print $message, "\n";
  577. }
  578.  
  579. return '';
  580. }
  581.  
  582. sub generic_error {
  583. my ($self, $message) = @_;
  584.  
  585.  
  586. return { error => 1, message => $message };
  587. }
  588.  
  589. =head1 CHANGES
  590.  
  591. =over 4
  592.  
  593. =item 1.5.1
  594.  
  595. Use binmode to create valid PNG files on Windows.
  596.  
  597. =item 1.4.1
  598.  
  599. Fix URI encoding.
  600.  
  601. =item 1.4.0
  602.  
  603. Add C<simple> and C<simple_file> methods.
  604.  
  605. =item 1.3.1
  606.  
  607. Retry requests (up to 2 times) to browshot.com in case of error
  608.  
  609. =back
  610.  
  611. =head1 SEE ALSO
  612.  
  613. See L<http://browshot.com/api/documentation> for the API documentation.
  614.  
  615. Create a free account at L<http://browshot.com/login> to get your free API key.
  616.  
  617. Go to L<http://browshot.com/dashboard> to find your API key after you registered.
  618.  
  619. =head1 AUTHOR
  620.  
  621. Julien Sobrier, E<lt>julien@sobrier.netE<gt>
  622.  
  623. =head1 COPYRIGHT AND LICENSE
  624.  
  625. Copyright (C) 2012 by Julien Sobrier
  626.  
  627. This library is free software; you can redistribute it and/or modify
  628. it under the same terms as Perl itself, either Perl version 5.8.8 or,
  629. at your option, any later version of Perl 5 you may have available.
  630.  
  631.  
  632. =cut
  633.  
  634. 1;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement