ac.php 5.3 KB

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