ac.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. <?php
  2. include "../../data/config.php";
  3. new autocomplete();
  4. class autocomplete{
  5. public function __construct(){
  6. header("Content-Type: application/json");
  7. $this->scrapers = [
  8. "brave" => "https://search.brave.com/api/suggest?q={searchTerms}",
  9. "ddg" => "https://duckduckgo.com/ac/?q={searchTerms}&type=list",
  10. "yandex" => "https://suggest.yandex.com/suggest-ff.cgi?part={searchTerms}&uil=en&v=3&sn=5&lr=21276&yu=4861394161661655015",
  11. "google" => "https://www.google.com/complete/search?client=mobile-gws-lite&q={searchTerms}",
  12. "qwant" => "https://api.qwant.com/v3/suggest/?q={searchTerms}&client=opensearch",
  13. "yep" => "https://api.yep.com/ac/?query={searchTerms}",
  14. "marginalia" => "https://search.marginalia.nu/suggest/?partial={searchTerms}",
  15. "yt" => "https://suggestqueries-clients6.youtube.com/complete/search?client=youtube&q={searchTerms}",
  16. "sc" => "",
  17. "startpage" => "https://www.startpage.com/suggestions?q={searchTerms}&format=opensearch&segment=startpage.defaultffx&lui=english",
  18. "kagi" => "https://kagi.com/api/autosuggest?q={searchTerms}",
  19. "ghostery" => "https://ghosterysearch.com/suggest?q={searchTerms}"
  20. ];
  21. /*
  22. Sanitize input
  23. */
  24. if(!isset($_GET["s"])){
  25. $this->do404("Missing search(s) parameter");
  26. }
  27. if(is_string($_GET["s"]) === false){
  28. $this->do404("Invalid search(s) parameter");
  29. }
  30. if(strlen($_GET["s"]) > 500){
  31. $this->do404("Search(s) exceeds the 500 char length");
  32. }
  33. /*
  34. Get $scraper
  35. */
  36. if(!isset($_GET["scraper"])){
  37. if(isset($_COOKIE["scraper_ac"])){
  38. $scraper = $_COOKIE["scraper_ac"];
  39. }else{
  40. $scraper = "brave"; // default option
  41. }
  42. }else{
  43. $scraper = $_GET["scraper"];
  44. }
  45. if($scraper == "disabled"){
  46. // this shouldnt happen, but let's handle it anyways
  47. $this->doempty();
  48. }
  49. // make sure it exists
  50. if(!isset($this->scrapers[$scraper])){
  51. $scraper = "brave"; // default option
  52. }
  53. // return results
  54. switch($scraper){
  55. case "google":
  56. case "yt":
  57. // handle google cause they want to be a special snowflake :(
  58. $js = $this->get($this->scrapers[$scraper], $_GET["s"]);
  59. preg_match(
  60. '/\((\[.*\])\)/',
  61. $js,
  62. $js
  63. );
  64. if(!isset($js[1])){
  65. $this->doempty();
  66. }
  67. $js = json_decode($js[1]);
  68. $json = [];
  69. foreach($js[1] as $item){
  70. $json[] = htmlspecialchars_decode(strip_tags($item[0]));
  71. }
  72. echo json_encode(
  73. [
  74. $_GET["s"],
  75. $json
  76. ],
  77. JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_IGNORE
  78. );
  79. break;
  80. case "sc":
  81. // soundcloud
  82. chdir("../../");
  83. include "scraper/sc.php";
  84. $sc = new sc();
  85. $token = $sc->get_token("raw_ip::::");
  86. $js = $this->get(
  87. "https://api-v2.soundcloud.com/search/queries?q={searchTerms}&client_id=" . $token . "&limit=10&offset=0&linked_partitioning=1&app_version=1693487844&app_locale=en",
  88. $_GET["s"]
  89. );
  90. $js = json_decode($js, true);
  91. if(!isset($js["collection"])){
  92. $this->doempty();
  93. }
  94. $json = [];
  95. foreach($js["collection"] as $item){
  96. $json[] = $item["query"];
  97. }
  98. echo json_encode(
  99. [
  100. $_GET["s"],
  101. $json
  102. ],
  103. JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_IGNORE
  104. );
  105. break;
  106. case "marginalia":
  107. $json = $this->get($this->scrapers[$scraper], $_GET["s"]);
  108. $json = json_decode($json, true);
  109. if($json === null){
  110. $this->doempty();
  111. }
  112. echo json_encode(
  113. [
  114. $_GET["s"],
  115. $json
  116. ],
  117. JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_IGNORE
  118. );
  119. break;
  120. default:
  121. // if it respects the openSearch protocol
  122. $json = json_decode($this->get($this->scrapers[$scraper], $_GET["s"]), true);
  123. echo json_encode(
  124. [
  125. $_GET["s"],
  126. $json[1] // ensure it contains valid key 0
  127. ],
  128. JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_IGNORE
  129. );
  130. break;
  131. }
  132. }
  133. private function get($url, $query){
  134. try{
  135. $curlproc = curl_init();
  136. $url = str_replace("{searchTerms}", urlencode($query), $url);
  137. curl_setopt($curlproc, CURLOPT_URL, $url);
  138. curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding
  139. curl_setopt($curlproc, CURLOPT_HTTPHEADER,
  140. ["User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/116.0",
  141. "Accept: application/json, text/javascript, */*; q=0.01",
  142. "Accept-Language: en-US,en;q=0.5",
  143. "Accept-Encoding: gzip",
  144. "DNT: 1",
  145. "Connection: keep-alive",
  146. "Sec-Fetch-Dest: empty",
  147. "Sec-Fetch-Mode: cors",
  148. "Sec-Fetch-Site: same-site"]
  149. );
  150. curl_setopt($curlproc, CURLOPT_RETURNTRANSFER, true);
  151. curl_setopt($curlproc, CURLOPT_SSL_VERIFYHOST, 2);
  152. curl_setopt($curlproc, CURLOPT_SSL_VERIFYPEER, true);
  153. curl_setopt($curlproc, CURLOPT_CONNECTTIMEOUT, 30);
  154. curl_setopt($curlproc, CURLOPT_TIMEOUT, 30);
  155. $data = curl_exec($curlproc);
  156. if(curl_errno($curlproc)){
  157. throw new Exception(curl_error($curlproc));
  158. }
  159. curl_close($curlproc);
  160. return $data;
  161. }catch(Exception $error){
  162. do404("Curl error: " . $error->getMessage());
  163. }
  164. }
  165. private function do404($error){
  166. echo json_encode(
  167. ["error" => $error],
  168. JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_IGNORE
  169. );
  170. die();
  171. }
  172. private function doempty(){
  173. echo json_encode(
  174. [
  175. $_GET["s"],
  176. []
  177. ],
  178. JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_IGNORE
  179. );
  180. die();
  181. }
  182. }