greppr.php 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. <?php
  2. // greppr dev probably monitors 4get code, lol
  3. // hello greppr dude, add an API you moron
  4. class greppr{
  5. public function __construct(){
  6. include "lib/backend.php";
  7. $this->backend = new backend("greppr");
  8. include "lib/fuckhtml.php";
  9. $this->fuckhtml = new fuckhtml();
  10. }
  11. public function getfilters($page){
  12. return [];
  13. }
  14. private function get($proxy, $url, $get = [], $cookies = [], $post = false){
  15. $curlproc = curl_init();
  16. curl_setopt($curlproc, CURLOPT_URL, $url);
  17. curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding
  18. $cookie = [];
  19. foreach($cookies as $k => $v){
  20. $cookie[] = "{$k}={$v}";
  21. }
  22. $cookie = implode("; ", $cookie);
  23. if($post === false){
  24. if($get !== []){
  25. $get = http_build_query($get);
  26. $url .= "?" . $get;
  27. }
  28. if($cookie == ""){
  29. curl_setopt($curlproc, CURLOPT_HTTPHEADER,
  30. ["User-Agent: " . config::USER_AGENT,
  31. "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
  32. "Accept-Language: en-US,en;q=0.5",
  33. "Accept-Encoding: gzip",
  34. "DNT: 1",
  35. "Connection: keep-alive",
  36. "Upgrade-Insecure-Requests: 1",
  37. "Sec-Fetch-Dest: document",
  38. "Sec-Fetch-Mode: navigate",
  39. "Sec-Fetch-Site: none",
  40. "Sec-Fetch-User: ?1"]
  41. );
  42. }else{
  43. curl_setopt($curlproc, CURLOPT_HTTPHEADER,
  44. ["User-Agent: " . config::USER_AGENT,
  45. "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
  46. "Accept-Language: en-US,en;q=0.5",
  47. "Accept-Encoding: gzip, deflate, br, zstd",
  48. "DNT: 1",
  49. "Sec-GPC: 1",
  50. "Connection: keep-alive",
  51. "Referer: https://greppr.org/search",
  52. "Cookie: {$cookie}",
  53. "Upgrade-Insecure-Requests: 1",
  54. "Sec-Fetch-Dest: document",
  55. "Sec-Fetch-Mode: navigate",
  56. "Sec-Fetch-Site: same-origin",
  57. "Sec-Fetch-User: ?1",
  58. "Priority: u=0, i"]
  59. );
  60. }
  61. }else{
  62. $get = http_build_query($get);
  63. curl_setopt($curlproc, CURLOPT_POST, true);
  64. curl_setopt($curlproc, CURLOPT_POSTFIELDS, $get);
  65. curl_setopt($curlproc, CURLOPT_HTTPHEADER,
  66. ["User-Agent: " . config::USER_AGENT,
  67. "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
  68. "Accept-Language: en-US,en;q=0.5",
  69. "Accept-Encoding: gzip, deflate, br, zstd",
  70. "Content-Type: application/x-www-form-urlencoded",
  71. "Content-Length: " . strlen($get),
  72. "Origin: https://greppr.org",
  73. "DNT: 1",
  74. "Sec-GPC: 1",
  75. "Connection: keep-alive",
  76. "Referer: https://greppr.org/",
  77. "Cookie: {$cookie}",
  78. "Upgrade-Insecure-Requests: 1",
  79. "Sec-Fetch-Dest: document",
  80. "Sec-Fetch-Mode: navigate",
  81. "Sec-Fetch-Site: same-origin",
  82. "Sec-Fetch-User: ?1",
  83. "Priority: u=0, i"]
  84. );
  85. }
  86. curl_setopt($curlproc, CURLOPT_RETURNTRANSFER, true);
  87. curl_setopt($curlproc, CURLOPT_SSL_VERIFYHOST, 2);
  88. curl_setopt($curlproc, CURLOPT_SSL_VERIFYPEER, true);
  89. curl_setopt($curlproc, CURLOPT_CONNECTTIMEOUT, 30);
  90. curl_setopt($curlproc, CURLOPT_TIMEOUT, 30);
  91. $this->backend->assign_proxy($curlproc, $proxy);
  92. $headers = [];
  93. curl_setopt(
  94. $curlproc,
  95. CURLOPT_HEADERFUNCTION,
  96. function($curlproc, $header) use (&$headers){
  97. $len = strlen($header);
  98. $header = explode(':', $header, 2);
  99. if(count($header) < 2){
  100. // ignore invalid headers
  101. return $len;
  102. }
  103. $headers[strtolower(trim($header[0]))][] = trim($header[1]);
  104. return $len;
  105. }
  106. );
  107. $data = curl_exec($curlproc);
  108. if(curl_errno($curlproc)){
  109. throw new Exception(curl_error($curlproc));
  110. }
  111. curl_close($curlproc);
  112. return [
  113. "headers" => $headers,
  114. "data" => $data
  115. ];
  116. }
  117. public function web($get, $first_attempt = true){
  118. if($get["npt"]){
  119. [$q, $proxy] = $this->backend->get($get["npt"], "web");
  120. $tokens = json_decode($q, true);
  121. //
  122. // Get paginated page
  123. //
  124. try{
  125. $html = $this->get(
  126. $proxy,
  127. "https://greppr.org" . $tokens["get"],
  128. [],
  129. $tokens["cookies"],
  130. false
  131. );
  132. }catch(Exception $error){
  133. throw new Exception("Failed to fetch search page");
  134. }
  135. }else{
  136. $search = $get["s"];
  137. if(strlen($search) === 0){
  138. throw new Exception("Search term is empty!");
  139. }
  140. $proxy = $this->backend->get_ip();
  141. //
  142. // get token
  143. //
  144. try{
  145. $html =
  146. $this->get(
  147. $proxy,
  148. "https://greppr.org",
  149. [],
  150. [],
  151. false
  152. );
  153. }catch(Exception $error){
  154. throw new Exception("Failed to fetch homepage");
  155. }
  156. //
  157. // Parse token
  158. //
  159. $this->fuckhtml->load($html["data"]);
  160. $tokens = [
  161. "req" => null,
  162. "data" => null,
  163. "cookies" => null
  164. ];
  165. $inputs =
  166. $this->fuckhtml
  167. ->getElementsByTagName(
  168. "input"
  169. );
  170. foreach($inputs as $input){
  171. if(!isset($input["attributes"]["name"])){
  172. continue;
  173. }
  174. if(
  175. isset($input["attributes"]["value"]) &&
  176. !empty($input["attributes"]["value"])
  177. ){
  178. $tokens
  179. ["data"]
  180. [$this->fuckhtml
  181. ->getTextContent(
  182. $input["attributes"]["name"]
  183. )] =
  184. $this->fuckhtml
  185. ->getTextContent(
  186. $input["attributes"]["value"]
  187. );
  188. }else{
  189. $tokens["req"] =
  190. $this->fuckhtml
  191. ->getTextContent(
  192. $input["attributes"]["name"]
  193. );
  194. }
  195. }
  196. if($tokens["req"] === null){
  197. throw new Exception("Failed to get request ID");
  198. }
  199. if(isset($html["headers"]["set-cookie"])){
  200. foreach($html["headers"]["set-cookie"] as $cookie){
  201. if(
  202. preg_match(
  203. '/([^=]+)=([^;]+)/',
  204. $cookie,
  205. $matches
  206. )
  207. ){
  208. $tokens["cookies"][$matches[1]] = $matches[2];
  209. }
  210. }
  211. }
  212. //
  213. // Get initial search page
  214. //
  215. $tokens_req = $tokens["data"];
  216. $tokens_req[$tokens["req"]] = $search;
  217. try{
  218. $html = $this->get(
  219. $proxy,
  220. "https://greppr.org/search",
  221. $tokens_req,
  222. $tokens["cookies"],
  223. true
  224. );
  225. }catch(Exception $error){
  226. throw new Exception("Failed to fetch search page");
  227. }
  228. }
  229. //$html = file_get_contents("scraper/greppr.html");
  230. //$this->fuckhtml->load($html);
  231. $this->fuckhtml->load($html["data"]);
  232. $out = [
  233. "status" => "ok",
  234. "spelling" => [
  235. "type" => "no_correction",
  236. "using" => null,
  237. "correction" => null
  238. ],
  239. "npt" => null,
  240. "answer" => [],
  241. "web" => [],
  242. "image" => [],
  243. "video" => [],
  244. "news" => [],
  245. "related" => []
  246. ];
  247. // get results for later
  248. $results =
  249. $this->fuckhtml
  250. ->getElementsByClassName(
  251. "result",
  252. "div"
  253. );
  254. // check for next page
  255. $next_elem =
  256. $this->fuckhtml
  257. ->getElementsByClassName(
  258. "pagination",
  259. "ul"
  260. );
  261. if(count($next_elem) !== 0){
  262. $this->fuckhtml->load($next_elem[0]);
  263. $as =
  264. $this->fuckhtml
  265. ->getElementsByClassName(
  266. "page-link",
  267. "a"
  268. );
  269. $break = false;
  270. foreach($as as $a){
  271. if($break === true){
  272. $out["npt"] =
  273. $this->backend->store(
  274. json_encode([
  275. "get" =>
  276. $this->fuckhtml
  277. ->getTextContent(
  278. $a["attributes"]["href"]
  279. ),
  280. "cookies" => $tokens["cookies"]
  281. ]),
  282. "web",
  283. $proxy
  284. );
  285. break;
  286. }
  287. if($a["attributes"]["href"] == "#"){
  288. $break = true;
  289. }
  290. }
  291. }
  292. // scrape results
  293. foreach($results as $result){
  294. $this->fuckhtml->load($result);
  295. $a =
  296. $this->fuckhtml
  297. ->getElementsByTagName(
  298. "a"
  299. )[0];
  300. $description =
  301. $this->fuckhtml
  302. ->getElementsByClassName(
  303. "highlightedDesc",
  304. "p"
  305. );
  306. if(count($description) === 0){
  307. $description = null;
  308. }else{
  309. $description =
  310. $this->limitstrlen(
  311. $this->fuckhtml
  312. ->getTextContent(
  313. $description[0]
  314. )
  315. );
  316. }
  317. $date =
  318. $this->fuckhtml
  319. ->getElementsByTagName(
  320. "p"
  321. );
  322. $date =
  323. strtotime(
  324. explode(
  325. ":",
  326. $this->fuckhtml
  327. ->getTextContent(
  328. $date[count($date) - 1]["innerHTML"]
  329. )
  330. )[1]
  331. );
  332. $out["web"][] = [
  333. "title" =>
  334. $this->fuckhtml
  335. ->getTextContent(
  336. $a["innerHTML"]
  337. ),
  338. "description" => $description,
  339. "url" =>
  340. $this->fuckhtml
  341. ->getTextContent(
  342. $a["attributes"]["href"]
  343. ),
  344. "date" => $date,
  345. "type" => "web",
  346. "thumb" => [
  347. "url" => null,
  348. "ratio" => null
  349. ],
  350. "sublink" => [],
  351. "table" => []
  352. ];
  353. }
  354. return $out;
  355. }
  356. private function limitstrlen($text){
  357. return explode("\n", wordwrap($text, 300, "\n"))[0];
  358. }
  359. }