From 8954d1aea59b8a1162c77e5cf3c835051a091e28 Mon Sep 17 00:00:00 2001 From: lolcat Date: Sun, 5 Apr 2026 23:44:26 -0400 Subject: [PATCH] added pixabay --- lib/frontend.php | 1 + scraper/pixabay.php | 396 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 397 insertions(+) create mode 100644 scraper/pixabay.php diff --git a/lib/frontend.php b/lib/frontend.php index e38d5dc..da3b626 100644 --- a/lib/frontend.php +++ b/lib/frontend.php @@ -994,6 +994,7 @@ class frontend{ "pinterest" => "Pinterest", "cara" => "Cara", "flickr" => "Flickr", + "pixabay" => "Pixabay", "fivehpx" => "500px", "vsco" => "VSCO", "imgur" => "Imgur", diff --git a/scraper/pixabay.php b/scraper/pixabay.php new file mode 100644 index 0000000..0565fe8 --- /dev/null +++ b/scraper/pixabay.php @@ -0,0 +1,396 @@ +backend = new backend("pixabay"); + } + + public function getfilters($page){ + + return [ + "nsfw" => [ + "display" => "NSFW", + "option" => [ + "yes" => "Yes", + "no" => "No" + ] + ], + "time" => [ + "display" => "Time posted", + "option" => [ + "any" => "Any time", + "1d" => "< 24 hours", + "3d" => "< 72 hours", + "1w" => "< 7 days", + "6m" => "< 6 months", + "1y" => "< 12 months" + ] + ], + "category" => [ + "display" => "Category", + "option" => [ + "images" => "All images", + "photos" => "Photos", + "illustrations" => "Illustrations", + "vectors" => "Vectors", + "gifs" => "GIFs" + ] + ], + "content_type" => [ + "display" => "Authenticity", + "option" => [ + "authentic" => "Authentic only", + "show_all" => "Authentic + AI slop", + "ai" => "AI slop only" + ] + ], + "order" => [ + "display" => "Sort by", + "option" => [ + "relevance" => "Most relevant", + "latest" => "Latest", + "ec" => "Editor's choice", + "trending" => "Trending" + ] + ], + "orientation" => [ + "display" => "Orientation", + "option" => [ + "any" => "Any orientation", + "vertical" => "Vertical", + "horizontal" => "Horizontal" + ] + ], + "color" => [ + "display" => "Color", + "option" => [ + "any" => "Any color", + "transparent" => "Transparent", + "grayscale" => "Grayscale", + "red" => "Red", + "orange" => "Orange", + "yellow" => "Yellow", + "green" => "Green", + "turquoise" => "Turquoise", + "blue" => "Blue", + "brown" => "Brown", + "black" => "Black", + "gray" => "Gray", + "white" => "White", + "pink" => "Pink", + "lilac" => "Lilac" + ] + ] + ]; + } + + private function get($proxy, $url, $get = [], $nsfw = true){ + + $curlproc = curl_init(); + + if($get !== []){ + $get = http_build_query($get); + $url .= "?" . $get; + } + + curl_setopt($curlproc, CURLOPT_URL, $url); + + curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding + curl_setopt($curlproc, CURLOPT_HTTPHEADER, + ["User-Agent: " . config::USER_AGENT . " Pixabay", + "Accept: application/json", + "Accept-Language: en-US,en;q=0.9", + "Accept-Encoding: gzip, deflate, br, zstd", + "Referer: {$url}", + "Cookie: " . ($nsfw ? "g_rated=off" : "g_rated=1"), + "DNT: 1", + "Sec-GPC: 1", + "Connection: keep-alive", + "Sec-Fetch-Dest: empty", + "Sec-Fetch-Mode: no-cors", + "Sec-Fetch-Site: same-origin", + "x-fetch-bootstrap: 1", + "Alt-Used: pixabay.com", + "Priority: u=0", + "Pragma: no-cache", + "Cache-Control: no-cache"] + ); + + curl_setopt($curlproc, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curlproc, CURLOPT_SSL_VERIFYHOST, 2); + curl_setopt($curlproc, CURLOPT_SSL_VERIFYPEER, true); + curl_setopt($curlproc, CURLOPT_CONNECTTIMEOUT, 30); + curl_setopt($curlproc, CURLOPT_TIMEOUT, 30); + + $this->backend->assign_proxy($curlproc, $proxy); + + $data = curl_exec($curlproc); + + if(curl_errno($curlproc)){ + + throw new Exception(curl_error($curlproc)); + } + + curl_close($curlproc); + return $data; + } + + public function image($get){ + + if($get["npt"]){ + + [$npt, $proxy] = + $this->backend->get( + $get["npt"], + "images" + ); + + $npt = json_decode($npt, true); + }else{ + + $search = $get["s"]; + if(strlen($search) === 0){ + + throw new Exception("Search term is empty!"); + } + + $proxy = $this->backend->get_ip(); + + $npt = [ + "s" => $search, + "pagi" => 1, + "category" => $get["category"] + ]; + + // filters + if($get["content_type"] != "show_all"){ + + $npt["content_type"] = $get["content_type"]; + } + + if($get["order"] != "relevance"){ + + $npt["order"] = $get["order"]; + } + + $npt["nsfw"] = $get["nsfw"] == "yes" ? true : false; + + if($get["orientation"] != "any"){ + + $npt["orientation"] = $get["orientation"]; + } + + if($get["color"] != "any"){ + + $npt["colors"] = $get["color"]; + } + + if($get["time"] != "any"){ + + $npt["date"] = $get["time"]; + } + } + + $out = [ + "status" => "ok", + "npt" => null, + "image" => [] + ]; + + // https://pixabay.com/images/search/japan/?pagi=1 + + $npt_pass = $npt; + unset($npt_pass["s"]); + unset($npt_pass["category"]); + unset($npt_pass["nsfw"]); + + try{ + $json = + $this->get( + $proxy, + "https://pixabay.com/{$npt["category"]}/search/" . rawurlencode($npt["s"]) . "/", + $npt_pass, + $npt["nsfw"] + ); + + }catch(Exception $error){ + + throw new Exception("Failed to fetch JSON"); + } + + $json = json_decode($json, true); + + if($json === null){ + + throw new Exception("Failed to decode JSON"); + } + + if(!isset($json["page"]["results"])){ + + throw new Exception("Pixabay API did not return a results object"); + } + + //print_r($json); + + foreach($json["page"]["results"] as $image){ + + if( + !( + $image["mediaType"] == "photo" || + $image["mediaType"] == "animation" + ) + ){ + + continue; + } + + // handle images that supply canvaRetouchUrl + if( + isset($image["canvaRetouchUrl"]) && + $image["canvaRetouchUrl"] !== null + ){ + + parse_str( + parse_url( + $image["canvaRetouchUrl"], + PHP_URL_QUERY + ), + $base + ); + + if(!isset($base["image-url"])){ + + // should not happen + continue; + } + + // get extension + $base = $base["image-url"]; + + $parsed_base = parse_url($base); + + $ext = + explode( + ".", + $parsed_base["path"] + ); + + $ext = $ext[count($ext) - 1]; + + // restructure url + $base = + explode( + "_", + $base + ); + + unset($base[count($base) - 1]); + $base = implode("_", $base); + + $ratio_1x = $this->imgratio((int)$image["width"], (int)$image["height"], 180); + $ratio_2x = $this->imgratio((int)$image["width"], (int)$image["height"], 1920); + + $source = [ + [ + "url" => "{$base}_1920.{$ext}", + "width" => $ratio_2x[0], + "height" => $ratio_2x[1] + ], + [ + "url" => "{$base}_180.{$ext}", + "width" => $ratio_1x[0], + "height" => $ratio_1x[1] + ] + ]; + }else{ + + // get intended sizes if canva is not set + // get 1x + $source_1x = null; + if(isset($image["sources"]["image_1x"])){ $source_1x = $image["sources"]["image_1x"]; } + elseif(isset($image["sources"]["1x"])){ $source_1x = $image["sources"]["1x"]; } + + if($source_1x === null){ continue; } // should not happen + + preg_match( + '/_([0-9]+)\./', + $image["sources"]["1x"], + $size_1x + ); + + $size_1x = (int)$size_1x[1]; + + // get 2x + $source_2x = null; + if(isset($image["sources"]["gif_2x"])){ $source_2x = $image["sources"]["gif_2x"]; } + elseif(isset($image["sources"]["2x"])){ $source_2x = $image["sources"]["2x"]; } + + if($source_2x === null){ continue; } // should not happen + + preg_match( + '/_([0-9]+)\./', + $source_2x, + $size_2x + ); + + $size_2x = (int)$size_2x[1]; + + // compute ratios + $ratio_1x = $this->imgratio((int)$image["width"], (int)$image["height"], $size_1x); + $ratio_2x = $this->imgratio((int)$image["width"], (int)$image["height"], $size_2x); + + // handle images that only give normal thumbnails + $source = [ + [ + "url" => $source_2x, + "width" => $ratio_2x[0], + "height" => $ratio_2x[1] + ], + [ + "url" => $source_1x, + "width" => $ratio_1x[0], + "height" => $ratio_1x[1] + ] + ]; + } + + $ratio_1x = $this->imgratio((int)$image["width"], (int)$image["height"], 180); + $ratio_2x = $this->imgratio((int)$image["width"], (int)$image["height"], 1920); + + $out["image"][] = [ + "title" => $image["name"], + "source" => $source, + "url" => "https://pixabay.com" . $image["href"] + ]; + } + + // add next page + if((int)$json["page"]["page"] < (int)$json["page"]["pages"]){ + + $npt["pagi"]++; + + $out["npt"] = + $this->backend->store( + json_encode($npt), + "images", + $proxy + ); + } + + return $out; + } + + private function imgratio($width, $height, $max_width){ + + $ratio = $max_width / $width; + $new_height = floor($height * $ratio); + + return [ + $max_width, + $new_height + ]; + } +}