snapshot.class.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. <?php
  2. /**
  3. * Insipid
  4. * Personal web-bookmark-system
  5. *
  6. * Copyright 2016-2023 Johannes Keßler
  7. *
  8. * Development starting from 2011: Johannes Keßler
  9. * https://www.bananas-playground.net/projekt/insipid/
  10. *
  11. * creator:
  12. * Luke Reeves <luke@neuro-tech.net>
  13. *
  14. * This program is free software: you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License as published by
  16. * the Free Software Foundation, either version 3 of the License, or
  17. * (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program. If not, see http://www.gnu.org/licenses/gpl-3.0.
  26. *
  27. */
  28. /**
  29. * class Snapshot
  30. * create from given ULR a Screenshot for storage
  31. * right now it uses google pagespeedonline for a simple snapshot
  32. *
  33. *
  34. */
  35. class Snapshot {
  36. /**
  37. * @var string
  38. */
  39. private string $_googlePageSpeed = 'https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=';
  40. /**
  41. * Snapshot constructor
  42. */
  43. public function __constructor(): void {}
  44. /**
  45. * call given url with google PageSpeed API
  46. * to receive image data
  47. *
  48. * @param String $url URL to take a thumbnail from
  49. * @param string $filename
  50. * @return boolean
  51. */
  52. public function doSnapshot(string $url, string $filename): bool {
  53. $ret = false;
  54. if(!empty($url) && is_writable(dirname($filename))) {
  55. if(DEBUG) {
  56. Summoner::sysLog("DEBUG try to save to $filename with $this->_googlePageSpeed for $url");
  57. }
  58. $theCall = Summoner::curlCall($this->_googlePageSpeed.urlencode($url).'&screenshot=true');
  59. if(!empty($theCall['status'])) {
  60. $jsonData = json_decode($theCall['message'],true);
  61. if(DEBUG) {
  62. Summoner::sysLog("DEBUG Call result data: ".Summoner::cleanForLog($jsonData));
  63. }
  64. if(!empty($jsonData) && isset($jsonData['lighthouseResult']['fullPageScreenshot']['screenshot']['data'])) {
  65. $imageData = $jsonData['lighthouseResult']['fullPageScreenshot']['screenshot']['data'];
  66. $source = fopen($imageData, 'r');
  67. $destination = fopen($filename, 'w');
  68. if(stream_copy_to_stream($source, $destination)) {
  69. $ret = $filename;
  70. }
  71. fclose($source);
  72. fclose($destination);
  73. } elseif(DEBUG) {
  74. Summoner::sysLog("DEBUG invalid json data. Path ['lighthouseResult']['fullPageScreenshot']['screenshot']['data'] not found in : ".Summoner::cleanForLog($jsonData));
  75. }
  76. } elseif(DEBUG) {
  77. Summoner::sysLog("DEBUG curl call failed ".Summoner::cleanForLog($theCall));
  78. }
  79. } else {
  80. Summoner::sysLog("ERROR URL $url is empty or target $filename is not writeable.");
  81. }
  82. return $ret;
  83. }
  84. /**
  85. * use configured COMPLETE_PAGE_SCREENSHOT_COMMAND to create a whole page screenshot
  86. * of the given link and store it locally
  87. *
  88. * Uses browserless.io and needs settings in config.php
  89. *
  90. * @param String $url URL to take the screenshot from
  91. * @param string $filename
  92. * @return boolean
  93. */
  94. public function wholePageSnapshot(string $url, string $filename): bool {
  95. $ret = false;
  96. if(!empty($url) && is_writable(dirname($filename))) {
  97. $postdata = json_encode(array(
  98. 'url' => $url,
  99. 'waitFor' => COMPLETE_PAGE_SCREEENSHOT_BROWSERLESS_TIMEOUT,
  100. 'options' => array(
  101. 'fullPage' => true,
  102. 'type' => "jpeg",
  103. 'quality' => COMPLETE_PAGE_SCREEENSHOT_BROWSERLESS_IMAGE_QUALITY
  104. )
  105. ));
  106. if(DEBUG) Summoner::sysLog("DEBUG browserless json data ".Summoner::cleanForLog($postdata));
  107. $fh = fopen($filename, 'w+');
  108. $api_url = COMPLETE_PAGE_SCREENSHOT_BROWSERLESS_API.COMPLETE_PAGE_SCREENSHOT_BROWSERLESS_API_KEY;
  109. $ch = curl_init($api_url);
  110. curl_setopt($ch, CURLOPT_FILE, $fh);
  111. //curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  112. curl_setopt($ch, CURLOPT_POST, 1);
  113. curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
  114. curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Cache-Control: no-cache'));
  115. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
  116. curl_setopt($ch, CURLOPT_TIMEOUT, 30);
  117. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  118. curl_setopt($ch, CURLOPT_MAXREDIRS, 2);
  119. // DEBUG ONLY
  120. //$curl_log = fopen(ABSOLUTE_PATH."/curl.log", 'w');
  121. //curl_setopt($ch, CURLOPT_VERBOSE, true);
  122. //curl_setopt($ch, CURLOPT_STDERR, $curl_log);
  123. if(!empty($port)) {
  124. curl_setopt($ch, CURLOPT_PORT, $port);
  125. }
  126. $do = curl_exec($ch);
  127. curl_close($ch);
  128. fclose($fh);
  129. if(DEBUG) Summoner::sysLog("DEBUG return ".Summoner::cleanForLog($do));
  130. // DEBUG ONLY
  131. //fclose($curl_log);
  132. $ret = true;
  133. } else {
  134. Summoner::sysLog("ERROR URL $url is empty or target $filename is not writeable.");
  135. }
  136. return $ret;
  137. }
  138. }