pixabay.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. <?php
  2. class pixabay{
  3. public function __construct(){
  4. include "lib/backend.php";
  5. $this->backend = new backend("pixabay");
  6. }
  7. public function getfilters($page){
  8. return [
  9. "nsfw" => [
  10. "display" => "NSFW",
  11. "option" => [
  12. "yes" => "Yes",
  13. "no" => "No"
  14. ]
  15. ],
  16. "time" => [
  17. "display" => "Time posted",
  18. "option" => [
  19. "any" => "Any time",
  20. "1d" => "< 24 hours",
  21. "3d" => "< 72 hours",
  22. "1w" => "< 7 days",
  23. "6m" => "< 6 months",
  24. "1y" => "< 12 months"
  25. ]
  26. ],
  27. "category" => [
  28. "display" => "Category",
  29. "option" => [
  30. "images" => "All images",
  31. "photos" => "Photos",
  32. "illustrations" => "Illustrations",
  33. "vectors" => "Vectors",
  34. "gifs" => "GIFs"
  35. ]
  36. ],
  37. "content_type" => [
  38. "display" => "Authenticity",
  39. "option" => [
  40. "authentic" => "Authentic only",
  41. "show_all" => "Authentic + AI slop",
  42. "ai" => "AI slop only"
  43. ]
  44. ],
  45. "order" => [
  46. "display" => "Sort by",
  47. "option" => [
  48. "relevance" => "Most relevant",
  49. "latest" => "Latest",
  50. "ec" => "Editor's choice",
  51. "trending" => "Trending"
  52. ]
  53. ],
  54. "orientation" => [
  55. "display" => "Orientation",
  56. "option" => [
  57. "any" => "Any orientation",
  58. "vertical" => "Vertical",
  59. "horizontal" => "Horizontal"
  60. ]
  61. ],
  62. "color" => [
  63. "display" => "Color",
  64. "option" => [
  65. "any" => "Any color",
  66. "transparent" => "Transparent",
  67. "grayscale" => "Grayscale",
  68. "red" => "Red",
  69. "orange" => "Orange",
  70. "yellow" => "Yellow",
  71. "green" => "Green",
  72. "turquoise" => "Turquoise",
  73. "blue" => "Blue",
  74. "brown" => "Brown",
  75. "black" => "Black",
  76. "gray" => "Gray",
  77. "white" => "White",
  78. "pink" => "Pink",
  79. "lilac" => "Lilac"
  80. ]
  81. ]
  82. ];
  83. }
  84. private function get($proxy, $url, $get = [], $nsfw = true){
  85. $curlproc = curl_init();
  86. if($get !== []){
  87. $get = http_build_query($get);
  88. $url .= "?" . $get;
  89. }
  90. curl_setopt($curlproc, CURLOPT_URL, $url);
  91. curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding
  92. curl_setopt($curlproc, CURLOPT_HTTPHEADER,
  93. ["User-Agent: " . config::USER_AGENT . " Pixabay",
  94. "Accept: application/json",
  95. "Accept-Language: en-US,en;q=0.9",
  96. "Accept-Encoding: gzip, deflate, br, zstd",
  97. "Referer: {$url}",
  98. "Cookie: " . ($nsfw ? "g_rated=off" : "g_rated=1"),
  99. "DNT: 1",
  100. "Sec-GPC: 1",
  101. "Connection: keep-alive",
  102. "Sec-Fetch-Dest: empty",
  103. "Sec-Fetch-Mode: no-cors",
  104. "Sec-Fetch-Site: same-origin",
  105. "x-fetch-bootstrap: 1",
  106. "Alt-Used: pixabay.com",
  107. "Priority: u=0",
  108. "Pragma: no-cache",
  109. "Cache-Control: no-cache"]
  110. );
  111. curl_setopt($curlproc, CURLOPT_RETURNTRANSFER, true);
  112. curl_setopt($curlproc, CURLOPT_SSL_VERIFYHOST, 2);
  113. curl_setopt($curlproc, CURLOPT_SSL_VERIFYPEER, true);
  114. curl_setopt($curlproc, CURLOPT_CONNECTTIMEOUT, 30);
  115. curl_setopt($curlproc, CURLOPT_TIMEOUT, 30);
  116. $this->backend->assign_proxy($curlproc, $proxy);
  117. $data = curl_exec($curlproc);
  118. if(curl_errno($curlproc)){
  119. throw new Exception(curl_error($curlproc));
  120. }
  121. curl_close($curlproc);
  122. return $data;
  123. }
  124. public function image($get){
  125. if($get["npt"]){
  126. [$npt, $proxy] =
  127. $this->backend->get(
  128. $get["npt"],
  129. "images"
  130. );
  131. $npt = json_decode($npt, true);
  132. }else{
  133. $search = $get["s"];
  134. if(strlen($search) === 0){
  135. throw new Exception("Search term is empty!");
  136. }
  137. $proxy = $this->backend->get_ip();
  138. $npt = [
  139. "s" => $search,
  140. "pagi" => 1,
  141. "category" => $get["category"]
  142. ];
  143. // filters
  144. if($get["content_type"] != "show_all"){
  145. $npt["content_type"] = $get["content_type"];
  146. }
  147. if($get["order"] != "relevance"){
  148. $npt["order"] = $get["order"];
  149. }
  150. $npt["nsfw"] = $get["nsfw"] == "yes" ? true : false;
  151. if($get["orientation"] != "any"){
  152. $npt["orientation"] = $get["orientation"];
  153. }
  154. if($get["color"] != "any"){
  155. $npt["colors"] = $get["color"];
  156. }
  157. if($get["time"] != "any"){
  158. $npt["date"] = $get["time"];
  159. }
  160. }
  161. $out = [
  162. "status" => "ok",
  163. "npt" => null,
  164. "image" => []
  165. ];
  166. // https://pixabay.com/images/search/japan/?pagi=1
  167. $npt_pass = $npt;
  168. unset($npt_pass["s"]);
  169. unset($npt_pass["category"]);
  170. unset($npt_pass["nsfw"]);
  171. try{
  172. $json =
  173. $this->get(
  174. $proxy,
  175. "https://pixabay.com/{$npt["category"]}/search/" . rawurlencode($npt["s"]) . "/",
  176. $npt_pass,
  177. $npt["nsfw"]
  178. );
  179. }catch(Exception $error){
  180. throw new Exception("Failed to fetch JSON");
  181. }
  182. $json = json_decode($json, true);
  183. if($json === null){
  184. throw new Exception("Failed to decode JSON");
  185. }
  186. if(!isset($json["page"]["results"])){
  187. throw new Exception("Pixabay API did not return a results object");
  188. }
  189. //print_r($json);
  190. foreach($json["page"]["results"] as $image){
  191. if(
  192. !(
  193. $image["mediaType"] == "photo" ||
  194. $image["mediaType"] == "animation"
  195. )
  196. ){
  197. continue;
  198. }
  199. // handle images that supply canvaRetouchUrl
  200. if(
  201. isset($image["canvaRetouchUrl"]) &&
  202. $image["canvaRetouchUrl"] !== null
  203. ){
  204. parse_str(
  205. parse_url(
  206. $image["canvaRetouchUrl"],
  207. PHP_URL_QUERY
  208. ),
  209. $base
  210. );
  211. if(!isset($base["image-url"])){
  212. // should not happen
  213. continue;
  214. }
  215. // get extension
  216. $base = $base["image-url"];
  217. $parsed_base = parse_url($base);
  218. $ext =
  219. explode(
  220. ".",
  221. $parsed_base["path"]
  222. );
  223. $ext = $ext[count($ext) - 1];
  224. // restructure url
  225. $base =
  226. explode(
  227. "_",
  228. $base
  229. );
  230. unset($base[count($base) - 1]);
  231. $base = implode("_", $base);
  232. $ratio_1x = $this->imgratio((int)$image["width"], (int)$image["height"], 180);
  233. $ratio_2x = $this->imgratio((int)$image["width"], (int)$image["height"], 1920);
  234. $source = [
  235. [
  236. "url" => "{$base}_1920.{$ext}",
  237. "width" => $ratio_2x[0],
  238. "height" => $ratio_2x[1]
  239. ],
  240. [
  241. "url" => "{$base}_180.{$ext}",
  242. "width" => $ratio_1x[0],
  243. "height" => $ratio_1x[1]
  244. ]
  245. ];
  246. }else{
  247. // get intended sizes if canva is not set
  248. // get 1x
  249. $source_1x = null;
  250. if(isset($image["sources"]["image_1x"])){ $source_1x = $image["sources"]["image_1x"]; }
  251. elseif(isset($image["sources"]["1x"])){ $source_1x = $image["sources"]["1x"]; }
  252. if($source_1x === null){ continue; } // should not happen
  253. preg_match(
  254. '/_([0-9]+)\./',
  255. $image["sources"]["1x"],
  256. $size_1x
  257. );
  258. $size_1x = (int)$size_1x[1];
  259. // get 2x
  260. $source_2x = null;
  261. if(isset($image["sources"]["gif_2x"])){ $source_2x = $image["sources"]["gif_2x"]; }
  262. elseif(isset($image["sources"]["2x"])){ $source_2x = $image["sources"]["2x"]; }
  263. if($source_2x === null){ continue; } // should not happen
  264. preg_match(
  265. '/_([0-9]+)\./',
  266. $source_2x,
  267. $size_2x
  268. );
  269. $size_2x = (int)$size_2x[1];
  270. // compute ratios
  271. $ratio_1x = $this->imgratio((int)$image["width"], (int)$image["height"], $size_1x);
  272. $ratio_2x = $this->imgratio((int)$image["width"], (int)$image["height"], $size_2x);
  273. // handle images that only give normal thumbnails
  274. $source = [
  275. [
  276. "url" => $source_2x,
  277. "width" => $ratio_2x[0],
  278. "height" => $ratio_2x[1]
  279. ],
  280. [
  281. "url" => $source_1x,
  282. "width" => $ratio_1x[0],
  283. "height" => $ratio_1x[1]
  284. ]
  285. ];
  286. }
  287. $ratio_1x = $this->imgratio((int)$image["width"], (int)$image["height"], 180);
  288. $ratio_2x = $this->imgratio((int)$image["width"], (int)$image["height"], 1920);
  289. $out["image"][] = [
  290. "title" => $image["name"],
  291. "source" => $source,
  292. "url" => "https://pixabay.com" . $image["href"]
  293. ];
  294. }
  295. // add next page
  296. if((int)$json["page"]["page"] < (int)$json["page"]["pages"]){
  297. $npt["pagi"]++;
  298. $out["npt"] =
  299. $this->backend->store(
  300. json_encode($npt),
  301. "images",
  302. $proxy
  303. );
  304. }
  305. return $out;
  306. }
  307. private function imgratio($width, $height, $max_width){
  308. $ratio = $max_width / $width;
  309. $new_height = floor($height * $ratio);
  310. return [
  311. $max_width,
  312. $new_height
  313. ];
  314. }
  315. }