diff options
Diffstat (limited to 'api/v1/ac.php')
-rw-r--r-- | api/v1/ac.php | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/api/v1/ac.php b/api/v1/ac.php new file mode 100644 index 0000000..0964fd9 --- /dev/null +++ b/api/v1/ac.php @@ -0,0 +1,225 @@ +<?php + +new autocomplete(); + +class autocomplete{ + + public function __construct(){ + + header("Content-Type: application/json"); + + $this->scrapers = [ + "brave" => "https://search.brave.com/api/suggest?q={searchTerms}", + "ddg" => "https://duckduckgo.com/ac/?q={searchTerms}&type=list", + "yandex" => "https://suggest.yandex.com/suggest-ff.cgi?part={searchTerms}&uil=en&v=3&sn=5&lr=21276&yu=4861394161661655015", + "google" => "https://www.google.com/complete/search?client=mobile-gws-lite&q={searchTerms}", + "qwant" => "https://api.qwant.com/v3/suggest/?q={searchTerms}&client=opensearch", + "yep" => "https://api.yep.com/ac/?query={searchTerms}", + "marginalia" => "https://search.marginalia.nu/suggest/?partial={searchTerms}", + "yt" => "https://suggestqueries-clients6.youtube.com/complete/search?client=youtube&q={searchTerms}", + "sc" => "https://api-v2.soundcloud.com/search/queries?q={searchTerms}&client_id=iMxZgT5mfGstBj8GWJbYMvpzelS8ne0E&limit=10&offset=0&linked_partitioning=1&app_version=1693487844&app_locale=en" + ]; + + /* + Sanitize input + */ + if(!isset($_GET["s"])){ + + $this->do404("Missing search(s) parameter"); + } + + if(is_string($_GET["s"]) === false){ + + $this->do404("Invalid search(s) parameter"); + } + + if(strlen($_GET["s"]) > 500){ + + $this->do404("Search(s) exceeds the 500 char length"); + } + + if( + isset($_GET["scraper"]) && + is_string($_GET["scraper"]) === false + ){ + + $_GET["scraper"] = "brave"; // default option + } + + /* + Get $scraper + */ + if(!isset($_GET["scraper"])){ + + if(isset($_COOKIE["scraper_ac"])){ + + $scraper = $_COOKIE["scraper_ac"]; + }else{ + + $scraper = "brave"; // default option + } + }else{ + + $scraper = $_GET["scraper"]; + } + + if($scraper == "disabled"){ + + // this shouldnt happen, but let's handle it anyways + $this->doempty(); + } + + // make sure it exists + if(!isset($this->scrapers[$scraper])){ + + $scraper = "brave"; // default option + } + + // return results + + switch($scraper){ + + case "google": + case "yt": + // handle google cause they want to be a special snowflake :( + $js = $this->get($this->scrapers[$scraper], $_GET["s"]); + + preg_match( + '/\((\[.*\])\)/', + $js, + $js + ); + + if(!isset($js[1])){ + + $this->doempty(); + } + + $js = json_decode($js[1]); + $json = []; + + foreach($js[1] as $item){ + + $json[] = strip_tags($item[0]); + } + + echo json_encode( + [ + $_GET["s"], + $json + ] + ); + break; + + case "sc": + // soundcloud + $js = $this->get($this->scrapers[$scraper], $_GET["s"]); + + $js = json_decode($js, true); + + if(!isset($js["collection"])){ + + $this->doempty(); + } + + $json = []; + foreach($js["collection"] as $item){ + + $json[] = $item["query"]; + } + + echo json_encode( + [ + $_GET["s"], + $json + ] + ); + break; + + case "marginalia": + $json = $this->get($this->scrapers[$scraper], $_GET["s"]); + + $json = json_decode($json, true); + if($json === null){ + + + $this->doempty(); + } + + echo json_encode( + [ + $_GET["s"], + $json + ] + ); + break; + + default: + // if it respects the openSearch protocol + $json = json_decode($this->get($this->scrapers[$scraper], $_GET["s"]), true); + + echo json_encode( + [ + $_GET["s"], + $json[1] // ensure it contains valid key 0 + ] + ); + break; + } + } + + private function get($url, $query){ + + $curlproc = curl_init(); + + $url = str_replace("{searchTerms}", urlencode($query), $url); + + curl_setopt($curlproc, CURLOPT_URL, $url); + + curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding + curl_setopt($curlproc, CURLOPT_HTTPHEADER, + ["User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/116.0", + "Accept: application/json, text/javascript, */*; q=0.01", + "Accept-Language: en-US,en;q=0.5", + "Accept-Encoding: gzip", + "DNT: 1", + "Connection: keep-alive", + "Sec-Fetch-Dest: empty", + "Sec-Fetch-Mode: cors", + "Sec-Fetch-Site: same-site"] + ); + + 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); + + $data = curl_exec($curlproc); + + if(curl_errno($curlproc)){ + + throw new Exception(curl_error($curlproc)); + } + + curl_close($curlproc); + return $data; + } + + private function do404($error){ + + echo json_encode(["error" => $error]); + die(); + } + + private function doempty(){ + + echo json_encode( + [ + $_GET["s"], + [] + ] + ); + die(); + } +} |