yep.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. <?php
  2. class yep{
  3. public function __construct(){
  4. include "lib/backend.php";
  5. $this->backend = new backend("yep");
  6. include "lib/fuckhtml.php";
  7. $this->fuckhtml = new fuckhtml();
  8. }
  9. public function getfilters($page){
  10. return [
  11. "lang" => [
  12. "display" => "Language",
  13. "option" => [
  14. "any" => "Any language",
  15. "aa" => "Afar",
  16. "ab" => "Abkhazian",
  17. "ae" => "Avestan",
  18. "af" => "Afrikaans",
  19. "ak" => "Akan",
  20. "am" => "Amharic",
  21. "an" => "Aragonese",
  22. "ar" => "Arabic",
  23. "as" => "Assamese",
  24. "av" => "Avaric",
  25. "ay" => "Aymara",
  26. "az" => "Azerbaijani",
  27. "ba" => "Bashkir",
  28. "be" => "Belarusian",
  29. "bg" => "Bulgarian",
  30. "bh" => "Bihari",
  31. "bi" => "Bislama",
  32. "bm" => "Bambara",
  33. "bn" => "Bengali",
  34. "bo" => "Tibetan",
  35. "br" => "Breton",
  36. "bs" => "Bosnian",
  37. "ca" => "Catalan",
  38. "ce" => "Chechen",
  39. "ch" => "Chamorro",
  40. "co" => "Corsican",
  41. "cr" => "Cree",
  42. "cs" => "Czech",
  43. "cu" => "Church Slavic",
  44. "cv" => "Chuvash",
  45. "cy" => "Welsh",
  46. "da" => "Danish",
  47. "de" => "German",
  48. "dv" => "Divehi",
  49. "dz" => "Dzongkha",
  50. "ee" => "Ewe",
  51. "el" => "Greek",
  52. "en" => "English",
  53. "eo" => "Esperanto",
  54. "es" => "Spanish",
  55. "et" => "Estonian",
  56. "eu" => "Basque",
  57. "fa" => "Persian",
  58. "ff" => "Fulah",
  59. "fi" => "Finnish",
  60. "fj" => "Fijian",
  61. "fo" => "Faroese",
  62. "fr" => "French",
  63. "fy" => "Western Frisian",
  64. "ga" => "Irish",
  65. "gd" => "Scottish Gaelic",
  66. "gl" => "Galician",
  67. "gn" => "Guarani",
  68. "gu" => "Gujarati",
  69. "gv" => "Manx",
  70. "ha" => "Hausa",
  71. "he" => "Hebrew",
  72. "hi" => "Hindi",
  73. "ho" => "Hiri Motu",
  74. "hr" => "Croatian",
  75. "ht" => "Haitian",
  76. "hu" => "Hungarian",
  77. "hy" => "Armenian",
  78. "hz" => "Herero",
  79. "ia" => "Interlingua",
  80. "id" => "Indonesian",
  81. "ie" => "Interlingue",
  82. "ig" => "Igbo",
  83. "ii" => "Sichuan Yi",
  84. "ik" => "Inupiaq",
  85. "io" => "Ido",
  86. "is" => "Icelandic",
  87. "it" => "Italian",
  88. "iu" => "Inuktitut",
  89. "ja" => "Japanese",
  90. "jv" => "Javanese",
  91. "ka" => "Georgian",
  92. "kg" => "Kongo",
  93. "ki" => "Kikuyu",
  94. "kj" => "Kuanyama",
  95. "kk" => "Kazakh",
  96. "kl" => "Kalaallisut",
  97. "km" => "Central Khmer",
  98. "kn" => "Kannada",
  99. "ko" => "Korean",
  100. "kr" => "Kanuri",
  101. "ks" => "Kashmiri",
  102. "ku" => "Kurdish",
  103. "kv" => "Komi",
  104. "kw" => "Cornish",
  105. "ky" => "Kyrgyz",
  106. "la" => "Latin",
  107. "lb" => "Luxembourgish",
  108. "lg" => "Ganda",
  109. "li" => "Limburgish",
  110. "ln" => "Lingala",
  111. "lo" => "Lao",
  112. "lt" => "Lithuanian",
  113. "lu" => "Luba-Katanga",
  114. "lv" => "Latvian",
  115. "mg" => "Malagasy",
  116. "mh" => "Marshallese",
  117. "mi" => "Maori",
  118. "mk" => "Macedonian",
  119. "ml" => "Malayalam",
  120. "mn" => "Mongolian",
  121. "mr" => "Marathi",
  122. "ms" => "Malay",
  123. "mt" => "Maltese",
  124. "my" => "Burmese",
  125. "na" => "Nauru",
  126. "nb" => "Norwegian Bokmål",
  127. "nd" => "North Ndebele",
  128. "ne" => "Nepali",
  129. "ng" => "Ndonga",
  130. "nl" => "Dutch",
  131. "nn" => "Norwegian Nynorsk",
  132. "no" => "Norwegian",
  133. "nr" => "South Ndebele",
  134. "nv" => "Navajo",
  135. "ny" => "Chichewa",
  136. "oc" => "Occitan",
  137. "oj" => "Ojibwa",
  138. "om" => "Oromo",
  139. "or" => "Oriya",
  140. "os" => "Ossetian",
  141. "pa" => "Punjabi",
  142. "pi" => "Pali",
  143. "pl" => "Polish",
  144. "ps" => "Pashto",
  145. "pt" => "Portuguese",
  146. "qu" => "Quechua",
  147. "rm" => "Romansh",
  148. "rn" => "Rundi",
  149. "ro" => "Romanian",
  150. "ru" => "Russian",
  151. "rw" => "Kinyarwanda",
  152. "sa" => "Sanskrit",
  153. "sc" => "Sardinian",
  154. "sd" => "Sindhi",
  155. "se" => "Northern Sami",
  156. "sg" => "Sango",
  157. "si" => "Sinhala",
  158. "sk" => "Slovak",
  159. "sl" => "Slovenian",
  160. "sm" => "Samoan",
  161. "sn" => "Shona",
  162. "so" => "Somali",
  163. "sq" => "Albanian",
  164. "sr" => "Serbian",
  165. "ss" => "Swati",
  166. "st" => "Southern Sotho",
  167. "su" => "Sundanese",
  168. "sv" => "Swedish",
  169. "sw" => "Swahili",
  170. "ta" => "Tamil",
  171. "te" => "Telugu",
  172. "tg" => "Tajik",
  173. "th" => "Thai",
  174. "ti" => "Tigrinya",
  175. "tk" => "Turkmen",
  176. "tl" => "Tagalog",
  177. "tn" => "Tswana",
  178. "to" => "Tonga",
  179. "tr" => "Turkish",
  180. "ts" => "Tsonga",
  181. "tt" => "Tatar",
  182. "tw" => "Twi",
  183. "ty" => "Tahitian",
  184. "ug" => "Uyghur",
  185. "uk" => "Ukrainian",
  186. "ur" => "Urdu",
  187. "uz" => "Uzbek",
  188. "ve" => "Venda",
  189. "vi" => "Vietnamese",
  190. "vo" => "Volapük",
  191. "wa" => "Walloon",
  192. "wo" => "Wolof",
  193. "xh" => "Xhosa",
  194. "yi" => "Yiddish",
  195. "yo" => "Yoruba",
  196. "za" => "Zhuang",
  197. "zh" => "Chinese",
  198. "zh-cn" => "Chinese (Simplified)",
  199. "zh-tw" => "Chinese (Traditional)",
  200. "zu" => "Zulu"
  201. ]
  202. ],
  203. "nsfw" => [
  204. "display" => "NSFW",
  205. "option" => [
  206. "yes" => "Yes",
  207. "no" => "No"
  208. ]
  209. ]
  210. ];
  211. }
  212. private function get($proxy, $url, $get = [], $use_api = false, $post_data = null, $bearer = null){
  213. $curlproc = curl_init();
  214. if($get !== []){
  215. $get = http_build_query($get);
  216. $url .= "?" . $get;
  217. }
  218. curl_setopt($curlproc, CURLOPT_URL, $url);
  219. // use http1 lol
  220. curl_setopt($curlproc, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
  221. curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding
  222. if($use_api){
  223. $post_data = json_encode($post_data);
  224. curl_setopt($curlproc, CURLOPT_HTTPHEADER,
  225. ["Content-Type: application/json",
  226. "Authorization: Bearer $bearer",
  227. "Content-Length: " . strlen($post_data)]
  228. );
  229. curl_setopt($curlproc, CURLOPT_POST, true);
  230. curl_setopt($curlproc, CURLOPT_POSTFIELDS, $post_data);
  231. }else{
  232. curl_setopt($curlproc, CURLOPT_HTTPHEADER,
  233. ["User-Agent: " . config::USER_AGENT,
  234. "Accept: */*",
  235. "Accept-Language: en-US,en;q=0.9",
  236. "Accept-Encoding: gzip, deflate, br, zstd",
  237. "Referer: https://yep.com/",
  238. "Origin: https://yep.com",
  239. "DNT: 1",
  240. "Connection: keep-alive",
  241. "Sec-Fetch-Dest: empty",
  242. "Sec-Fetch-Mode: cors",
  243. "Sec-Fetch-Site: same-site",
  244. "Priority: u=4",
  245. "Pragma: no-cache",
  246. "Cache-Control: no-cache",
  247. "TE: trailers"]
  248. );
  249. }
  250. curl_setopt($curlproc, CURLOPT_RETURNTRANSFER, true);
  251. curl_setopt($curlproc, CURLOPT_SSL_VERIFYHOST, 2);
  252. curl_setopt($curlproc, CURLOPT_SSL_VERIFYPEER, true);
  253. curl_setopt($curlproc, CURLOPT_CONNECTTIMEOUT, 30);
  254. curl_setopt($curlproc, CURLOPT_TIMEOUT, 30);
  255. $this->backend->assign_proxy($curlproc, $proxy);
  256. $data = curl_exec($curlproc);
  257. if(curl_errno($curlproc)){
  258. throw new Exception(curl_error($curlproc));
  259. }
  260. curl_close($curlproc);
  261. return $data;
  262. }
  263. public function web($get){
  264. if(config::YEP_USE_API){
  265. return $this->web_api($get);
  266. }
  267. $search = $get["s"];
  268. if(strlen($search) === 0){
  269. throw new Exception("Search term is empty!");
  270. }
  271. $out = [
  272. "status" => "ok",
  273. "spelling" => [
  274. "type" => "no_correction",
  275. "using" => null,
  276. "correction" => null
  277. ],
  278. "npt" => null,
  279. "answer" => [],
  280. "web" => [],
  281. "image" => [],
  282. "video" => [],
  283. "news" => [],
  284. "related" => []
  285. ];
  286. // parse filters
  287. $filters = [
  288. "limit" => 100, // wwwwwwwwwwwwwww
  289. "query" => $search,
  290. ];
  291. if($get["nsfw"] == "no"){ $filters["safeSearch"] = "moderate"; }
  292. if($get["lang"] != "any"){ $filters["hl"] = $get["lang"]; }
  293. try{
  294. // https://api.yep.com/search?limit=20&query=asmr
  295. $json =
  296. $this->get(
  297. $this->backend->get_ip(),
  298. "https://api.yep.com/search",
  299. $filters
  300. );
  301. }catch(Exception $error){
  302. throw new Exception("Failed to fetch JSON");
  303. }
  304. $this->detect_cf($json);
  305. $json = json_decode($json, true);
  306. //$json = json_decode(file_get_contents("scraper/yep.json"), true);
  307. if($json === null){
  308. throw new Exception("Failed to decode JSON");
  309. }
  310. if(isset($json[1]["correction"])){
  311. $out["spelling"] = [
  312. "type" => "not_many",
  313. "using" => $search,
  314. "correction" => $json[1]["correction"][1]
  315. ];
  316. }
  317. if(isset($json[1]["results"])){
  318. foreach($json[1]["results"] as $item){
  319. switch(strtolower($item["type"])){
  320. case "organic":
  321. $sublinks = [];
  322. if(isset($item["sitelinks"]["full"])){
  323. foreach($item["sitelinks"]["full"] as $link){
  324. $sublinks[] = [
  325. "title" => $link["title"],
  326. "date" => null,
  327. "description" =>
  328. $this->titledots(
  329. strip_tags(
  330. html_entity_decode(
  331. $link["snippet"]
  332. )
  333. )
  334. ),
  335. "url" => $link["url"]
  336. ];
  337. }
  338. }
  339. $out["web"][] = [
  340. "title" => $item["title"],
  341. "description" =>
  342. $this->titledots(
  343. strip_tags(
  344. html_entity_decode(
  345. $item["snippet"]
  346. )
  347. )
  348. ),
  349. "url" => $item["url"],
  350. "date" => null,
  351. "type" => "web",
  352. "thumb" => [
  353. "url" => null,
  354. "ratio" => null
  355. ],
  356. "sublink" => $sublinks,
  357. "table" => []
  358. ];
  359. break;
  360. }
  361. }
  362. }
  363. return $out;
  364. }
  365. private function web_api($get){
  366. $search = $get["s"];
  367. if(strlen($search) === 0){
  368. throw new Exception("Search term is empty!");
  369. }
  370. $out = [
  371. "status" => "ok",
  372. "spelling" => [
  373. "type" => "no_correction",
  374. "using" => null,
  375. "correction" => null
  376. ],
  377. "npt" => null,
  378. "answer" => [],
  379. "web" => [],
  380. "image" => [],
  381. "video" => [],
  382. "news" => [],
  383. "related" => []
  384. ];
  385. // parse filters
  386. $filters = [
  387. "query" => $search,
  388. "limit" => 99 // for some reason they dont show anything sometimes at 100 results
  389. ];
  390. if($get["nsfw"] == "no"){ $filters["safe_search"] = true; }
  391. if($get["lang"] != "any"){ $filters["language"] = [ $get["lang"] ]; }
  392. // add api key
  393. $key_data = $this->backend->get_key();
  394. try{
  395. $json =
  396. $this->get(
  397. $this->backend->get_ip($key_data["increment"]),
  398. "https://platform.yep.com/api/search",
  399. [],
  400. true,
  401. $filters,
  402. $key_data["key"]
  403. );
  404. }catch(Exception $error){
  405. throw new Exception("Failed to fetch JSON");
  406. }
  407. // should never happen
  408. //$this->detect_cf($json);
  409. $json = json_decode($json, true);
  410. //$json = json_decode(file_get_contents("scraper/yep.json"), true);
  411. if($json === null){
  412. throw new Exception("Failed to decode JSON");
  413. }
  414. if(isset($json["error"])){
  415. throw new Exception("Yep API returned an error: " . $json["error"]);
  416. }
  417. if(isset($json["errors"])){
  418. throw new Exception("Yep API returned the following errors: {$json["message"]}");
  419. }
  420. if(
  421. isset($json["success"]) &&
  422. $json["success"] !== true
  423. ){
  424. throw new Exception("Yep API returned a false-y success value");
  425. }
  426. if(!isset($json["results"])){
  427. throw new Exception("Yep API did not return a results object");
  428. }
  429. foreach($json["results"] as $item){
  430. if(
  431. $item["url"] === null ||
  432. $item["url"] == ""
  433. ){
  434. // sometimes API fucks up
  435. continue;
  436. }
  437. $out["web"][] = [
  438. "title" => $item["title"],
  439. "description" => $item["description"],
  440. "url" => $item["url"],
  441. "date" => null,
  442. "type" => "web",
  443. "thumb" => [
  444. "url" => null,
  445. "ratio" => null
  446. ],
  447. "sublink" => [],
  448. "table" => []
  449. ];
  450. }
  451. return $out;
  452. }
  453. private function detect_cf($payload){
  454. // detect cloudflare page
  455. $this->fuckhtml->load($payload);
  456. if(
  457. count(
  458. $this->fuckhtml
  459. ->getElementsByClassName(
  460. "cf-wrapper",
  461. "div"
  462. )
  463. ) !== 0
  464. ){
  465. throw new Exception("Blocked by Cloudflare. Please follow curl-impersonate installation instructions");
  466. }
  467. }
  468. private function titledots($title){
  469. $substr = substr($title, -4);
  470. if(
  471. strpos($substr, "...") !== false ||
  472. strpos($substr, "…") !== false
  473. ){
  474. return trim(substr($title, 0, -4));
  475. }
  476. return trim($title);
  477. }
  478. private function unshiturl($url){
  479. $newurl = parse_url($url, PHP_URL_QUERY);
  480. parse_str($newurl, $newurl);
  481. if(isset($newurl["url"])){
  482. return $newurl["url"];
  483. }
  484. return $url;
  485. }
  486. }