fivehpx.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. <?php
  2. class fivehpx{
  3. public function __construct(){
  4. include "lib/backend.php";
  5. $this->backend = new backend("fivehpx");
  6. include "lib/fuckhtml.php";
  7. $this->fuckhtml = new fuckhtml();
  8. }
  9. public function getfilters($page){
  10. return [
  11. "sort" => [
  12. "display" => "Sort",
  13. "option" => [
  14. "relevance" => "Relevance",
  15. "pulse" => "Pulse",
  16. "newest" => "Newest"
  17. ]
  18. ]
  19. ];
  20. }
  21. private function get($proxy, $url, $get = [], $post_data = null){
  22. $curlproc = curl_init();
  23. if($get !== []){
  24. $get = http_build_query($get);
  25. $url .= "?" . $get;
  26. }
  27. curl_setopt($curlproc, CURLOPT_URL, $url);
  28. curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding
  29. if($post_data === null){
  30. curl_setopt($curlproc, CURLOPT_HTTPHEADER,
  31. ["User-Agent: " . config::USER_AGENT,
  32. "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
  33. "Accept-Language: en-US,en;q=0.5",
  34. "Accept-Encoding: gzip",
  35. "DNT: 1",
  36. "Sec-GPC: 1",
  37. "Connection: keep-alive",
  38. "Upgrade-Insecure-Requests: 1",
  39. "Sec-Fetch-Dest: document",
  40. "Sec-Fetch-Mode: navigate",
  41. "Sec-Fetch-Site: same-origin",
  42. "Sec-Fetch-User: ?1",
  43. "Priority: u=0, i",
  44. "TE: trailers"]
  45. );
  46. }else{
  47. curl_setopt($curlproc, CURLOPT_HTTPHEADER,
  48. ["User-Agent: " . config::USER_AGENT,
  49. "Accept: */*",
  50. "Accept-Language: en-US,en;q=0.5",
  51. "Accept-Encoding: gzip",
  52. "Referer: https://500px.com/",
  53. "content-type: application/json",
  54. //"x-csrf-token: undefined",
  55. "x-500px-source: Search",
  56. "Content-Length: " . strlen($post_data),
  57. "Origin: https://500px.com",
  58. "DNT: 1",
  59. "Sec-GPC: 1",
  60. "Connection: keep-alive",
  61. // "Cookie: _pin_unauth, _fbp, _sharedID, _sharedID_cst",
  62. "Sec-Fetch-Dest: empty",
  63. "Sec-Fetch-Mode: cors",
  64. "Sec-Fetch-Site: same-site",
  65. "Priority: u=4",
  66. "TE: trailers"]
  67. );
  68. // set post data
  69. curl_setopt($curlproc, CURLOPT_POST, true);
  70. curl_setopt($curlproc, CURLOPT_POSTFIELDS, $post_data);
  71. }
  72. curl_setopt($curlproc, CURLOPT_RETURNTRANSFER, true);
  73. curl_setopt($curlproc, CURLOPT_SSL_VERIFYHOST, 2);
  74. curl_setopt($curlproc, CURLOPT_SSL_VERIFYPEER, true);
  75. curl_setopt($curlproc, CURLOPT_CONNECTTIMEOUT, 30);
  76. curl_setopt($curlproc, CURLOPT_TIMEOUT, 30);
  77. // http2 bypass
  78. curl_setopt($curlproc, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
  79. $this->backend->assign_proxy($curlproc, $proxy);
  80. $data = curl_exec($curlproc);
  81. if(curl_errno($curlproc)){
  82. throw new Exception(curl_error($curlproc));
  83. }
  84. curl_close($curlproc);
  85. return $data;
  86. }
  87. public function image($get){
  88. if($get["npt"]){
  89. [$pagination, $proxy] =
  90. $this->backend->get(
  91. $get["npt"], "images"
  92. );
  93. $pagination = json_decode($pagination, true);
  94. $search = $pagination["search"];
  95. }else{
  96. $search = $get["s"];
  97. if(strlen($search) === 0){
  98. throw new Exception("Search term is empty!");
  99. }
  100. $proxy = $this->backend->get_ip();
  101. $pagination = [
  102. "sort" => strtoupper($get["sort"]),
  103. "search" => $search,
  104. "filters" => [],
  105. "nlp" => false,
  106. ];
  107. }
  108. try{
  109. $json =
  110. $this->get(
  111. $proxy,
  112. "https://api.500px.com/graphql",
  113. [],
  114. json_encode([
  115. "operationName" => "PhotoSearchPaginationContainerQuery",
  116. "variables" => $pagination,
  117. "query" =>
  118. 'query PhotoSearchPaginationContainerQuery(' .
  119. (isset($pagination["cursor"]) ? '$cursor: String, ' : "") .
  120. '$sort: PhotoSort, $search: String!, $filters: [PhotoSearchFilter!], $nlp: Boolean) { ...PhotoSearchPaginationContainer_query_1vzAZD} fragment PhotoSearchPaginationContainer_query_1vzAZD on Query { photoSearch(sort: $sort, first: 100, ' .
  121. (isset($pagination["cursor"]) ? 'after: $cursor, ' : "") .
  122. 'search: $search, filters: $filters, nlp: $nlp) { edges { node { id legacyId canonicalPath name description width height images(sizes: [33, 36]) { size url id } } } totalCount pageInfo { endCursor hasNextPage } }}'
  123. ])
  124. );
  125. }catch(Exception $error){
  126. throw new Exception("Failed to fetch graphQL object");
  127. }
  128. $json = json_decode($json, true);
  129. if($json === null){
  130. throw new Exception("Failed to decode graphQL object");
  131. }
  132. if(isset($json["errors"][0]["message"])){
  133. throw new Exception("500px returned an API error: " . $json["errors"][0]["message"]);
  134. }
  135. if(!isset($json["data"]["photoSearch"]["edges"])){
  136. throw new Exception("No edges returned by API");
  137. }
  138. $out = [
  139. "status" => "ok",
  140. "npt" => null,
  141. "image" => []
  142. ];
  143. foreach($json["data"]["photoSearch"]["edges"] as $image){
  144. $image = $image["node"];
  145. $title =
  146. trim(
  147. $this->fuckhtml
  148. ->getTextContent(
  149. $image["name"]
  150. ) . ": " .
  151. $this->fuckhtml
  152. ->getTextContent(
  153. $image["description"]
  154. )
  155. , " :"
  156. );
  157. $small = $this->image_ratio(600, $image["width"], $image["height"]);
  158. $large = $this->image_ratio(2048, $image["width"], $image["height"]);
  159. $out["image"][] = [
  160. "title" => $title,
  161. "source" => [
  162. [
  163. "url" => $image["images"][1]["url"],
  164. "width" => $large[0],
  165. "height" => $large[1]
  166. ],
  167. [
  168. "url" => $image["images"][0]["url"],
  169. "width" => $small[0],
  170. "height" => $small[1]
  171. ]
  172. ],
  173. "url" => "https://500px.com" . $image["canonicalPath"]
  174. ];
  175. }
  176. // get NPT token
  177. if($json["data"]["photoSearch"]["pageInfo"]["hasNextPage"] === true){
  178. $out["npt"] =
  179. $this->backend->store(
  180. json_encode([
  181. "cursor" => $json["data"]["photoSearch"]["pageInfo"]["endCursor"],
  182. "search" => $search,
  183. "sort" => $pagination["sort"],
  184. "filters" => [],
  185. "nlp" => false
  186. ]),
  187. "images",
  188. $proxy
  189. );
  190. }
  191. return $out;
  192. }
  193. private function image_ratio($longest_edge, $width, $height){
  194. $ratio = [
  195. $longest_edge / $width,
  196. $longest_edge / $height
  197. ];
  198. if($ratio[0] < $ratio[1]){
  199. $ratio = $ratio[0];
  200. }else{
  201. $ratio = $ratio[1];
  202. }
  203. return [
  204. floor($width * $ratio),
  205. floor($height * $ratio)
  206. ];
  207. }
  208. }