purili.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. <?php
  2. class purili{
  3. public function __construct(){
  4. include "lib/backend.php";
  5. $this->backend = new backend("purili");
  6. }
  7. public function getfilters($page){
  8. switch($page){
  9. case "web":
  10. return [
  11. "nsfw" => [
  12. "display" => "NSFW",
  13. "option" => [
  14. "yes" => "Yes",
  15. "maybe" => "Maybe",
  16. "no" => "No"
  17. ]
  18. ],
  19. "language" => [
  20. "display" => "Language",
  21. "option" => [
  22. "any" => "Any language",
  23. "en" => "English only",
  24. "nl" => "Dutch preferred",
  25. "de" => "German preferred",
  26. "fr" => "French preferred",
  27. "es" => "Spanish preferred",
  28. "it" => "Italian preferred",
  29. "pt" => "Portuguese preferred"
  30. ]
  31. ]
  32. ];
  33. break;
  34. case "videos":
  35. return [];
  36. break;
  37. }
  38. }
  39. private function get($proxy, $url, $get = [], $nsfw = null, $language = null){
  40. $curlproc = curl_init();
  41. switch($nsfw){
  42. case "yes":
  43. case null:
  44. $get["fv"] = "0";
  45. $nsfw = "off";
  46. break;
  47. case "maybe":
  48. $get["fv"] = "1";
  49. $nsfw = "moderate";
  50. break;
  51. case "no":
  52. $get["fv"] = "2";
  53. $nsfw = "strict";
  54. break;
  55. }
  56. switch($language){
  57. case "any":
  58. case null:
  59. $language_cookie = "";
  60. break;
  61. default:
  62. $language_cookie = "; purili-language={$language}";
  63. break;
  64. }
  65. if($get !== []){
  66. $get = http_build_query($get);
  67. $url .= "?" . $get;
  68. }
  69. curl_setopt($curlproc, CURLOPT_URL, $url);
  70. curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding
  71. curl_setopt($curlproc, CURLOPT_HTTPHEADER,
  72. ["User-Agent: " . config::USER_AGENT,
  73. "Accept: */*",
  74. "Accept-Language: en-US,en;q=0.9",
  75. "Accept-Encoding: gzip, deflate, br, zstd",
  76. "DNT: 1",
  77. "Sec-GPC: 1",
  78. "Connection: keep-alive",
  79. "Cookie: purili-safesearch={$nsfw}{$language_cookie}",
  80. "Sec-Fetch-Dest: empty",
  81. "Sec-Fetch-Mode: cors",
  82. "Sec-Fetch-Site: same-origin",
  83. "Priority: u=4"]
  84. );
  85. curl_setopt($curlproc, CURLOPT_RETURNTRANSFER, true);
  86. curl_setopt($curlproc, CURLOPT_SSL_VERIFYHOST, 2);
  87. curl_setopt($curlproc, CURLOPT_SSL_VERIFYPEER, true);
  88. curl_setopt($curlproc, CURLOPT_CONNECTTIMEOUT, 30);
  89. curl_setopt($curlproc, CURLOPT_TIMEOUT, 30);
  90. $this->backend->assign_proxy($curlproc, $proxy);
  91. $data = curl_exec($curlproc);
  92. if(curl_errno($curlproc)){
  93. throw new Exception(curl_error($curlproc));
  94. }
  95. curl_close($curlproc);
  96. return $data;
  97. }
  98. public function web($get){
  99. if($get["npt"]){
  100. [$q, $proxy] = $this->backend->get($get["npt"], "web");
  101. $q = json_decode($q, true);
  102. $nsfw = $q["nsfw"];
  103. unset($q["nsfw"]);
  104. $language = $q["language"];
  105. unset($q["language"]);
  106. }else{
  107. $search = $get["s"];
  108. if(strlen($search) === 0){
  109. throw new Exception("Search term is empty!");
  110. }
  111. $proxy = $this->backend->get_ip();
  112. $q = [
  113. "q" => $search,
  114. "page" => 1,
  115. // added at $this->get()
  116. // "fv" => 0
  117. ];
  118. $nsfw = $get["nsfw"];
  119. $language = $get["language"];
  120. }
  121. // https://puri.li/api/search?q=4get&page=1&fv=0
  122. try{
  123. $json = $this->get(
  124. $proxy,
  125. "https://puri.li/api/search",
  126. $q,
  127. $nsfw,
  128. $language
  129. );
  130. }catch(Exception $error){
  131. throw new Exception("Failed to hit API");
  132. }
  133. $json = json_decode($json, true);
  134. if($json === null){
  135. throw new Exception("Failed to decode JSON");
  136. }
  137. if(!isset($json["results"])){
  138. throw new Exception("Failed to access results array");
  139. }
  140. $out = [
  141. "status" => "ok",
  142. "spelling" => [
  143. "type" => "no_correction",
  144. "using" => null,
  145. "correction" => null
  146. ],
  147. "npt" => null,
  148. "answer" => [],
  149. "web" => [],
  150. "image" => [],
  151. "video" => [],
  152. "news" => [],
  153. "related" => []
  154. ];
  155. foreach($json["results"] as $result){
  156. $out["web"][] = [
  157. "title" => $result["title"],
  158. "description" => $result["description"],
  159. "url" => $result["url"],
  160. "date" => null,
  161. "type" => "web",
  162. "thumb" => [
  163. "url" => null,
  164. "ratio" => null
  165. ],
  166. "sublink" => [],
  167. "table" => []
  168. ];
  169. }
  170. // get next page
  171. if($json["hasNext"]){
  172. $q["page"]++;
  173. $q["nsfw"] = $nsfw;
  174. $q["language"] = $language;
  175. $out["npt"] =
  176. $this->backend->store(
  177. json_encode($q),
  178. "web",
  179. $proxy
  180. );
  181. }
  182. return $out;
  183. }
  184. public function video($get){
  185. if($get["npt"]){
  186. [$q, $proxy] = $this->backend->get($get["npt"], "videos");
  187. $q = json_decode($q, true);
  188. }else{
  189. $search = $get["s"];
  190. if(strlen($search) === 0){
  191. throw new Exception("Search term is empty!");
  192. }
  193. $proxy = $this->backend->get_ip();
  194. $q = [
  195. "q" => $search,
  196. "offset" => 0,
  197. "limit" => 12
  198. // added at $this->get()
  199. // "fv" => 0
  200. ];
  201. }
  202. // https://puri.li/api/videos/search?q=higurashi&limit=12&fv=1
  203. // hidden &offset parameter only accessible through the API
  204. try{
  205. $json = $this->get(
  206. $proxy,
  207. "https://puri.li/api/videos/search",
  208. $q,
  209. null,
  210. null
  211. );
  212. }catch(Exception $error){
  213. throw new Exception("Failed to hit API");
  214. }
  215. $json = json_decode($json, true);
  216. if($json === null){
  217. throw new Exception("Failed to decode JSON");
  218. }
  219. if(!isset($json["results"])){
  220. throw new Exception("Failed to access results array");
  221. }
  222. $out = [
  223. "status" => "ok",
  224. "npt" => null,
  225. "video" => [],
  226. "author" => [],
  227. "livestream" => [],
  228. "playlist" => [],
  229. "reel" => []
  230. ];
  231. foreach($json["results"] as $result){
  232. if(isset($result["thumbnail"])){
  233. $thumb = [
  234. "ratio" => "16:9",
  235. "url" => $result["thumbnail"]
  236. ];
  237. }else{
  238. $thumb = [
  239. "ratio" => null,
  240. "url" => null
  241. ];
  242. }
  243. $out["video"][] = [
  244. "title" => $result["title"],
  245. "description" =>
  246. str_replace(
  247. "\n", " ",
  248. mb_substr(
  249. $result["description"], 0, 255, "utf-8"
  250. )
  251. ),
  252. "author" => [
  253. "name" => null,
  254. "url" => isset($result["channel_id"]) ? "https://www.youtube.com/channel/" . $result["channel_id"] : null,
  255. "avatar" => null
  256. ],
  257. "date" => strtotime($result["upload_date"]),
  258. "duration" => $result["duration"],
  259. "views" => $result["view_count"],
  260. "thumb" => $thumb,
  261. "url" => $result["url"]
  262. ];
  263. }
  264. // get next page
  265. if($json["limit"] + $json["offset"] < $json["total"]){
  266. $q["offset"] = $q["offset"] + $json["limit"];
  267. $out["npt"] =
  268. $this->backend->store(
  269. json_encode($q),
  270. "videos",
  271. $proxy
  272. );
  273. }
  274. return $out;
  275. }
  276. }