2024-04-21 23:31:56 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
class qwant{
|
|
|
|
|
|
|
|
public function __construct(){
|
|
|
|
|
|
|
|
include "lib/backend.php";
|
|
|
|
$this->backend = new backend("qwant");
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getfilters($page){
|
|
|
|
|
|
|
|
$base = [
|
|
|
|
"nsfw" => [
|
|
|
|
"display" => "NSFW",
|
|
|
|
"option" => [
|
|
|
|
"yes" => "Yes",
|
|
|
|
"maybe" => "Maybe",
|
|
|
|
"no" => "No"
|
|
|
|
]
|
|
|
|
],
|
|
|
|
"country" => [
|
|
|
|
"display" => "Country",
|
|
|
|
"option" => [
|
|
|
|
"en_US" => "United States",
|
|
|
|
"fr_FR" => "France",
|
|
|
|
"en_GB" => "Great Britain",
|
|
|
|
"de_DE" => "Germany",
|
|
|
|
"it_IT" => "Italy",
|
|
|
|
"es_AR" => "Argentina",
|
|
|
|
"en_AU" => "Australia",
|
|
|
|
"es_ES" => "Spain (es)",
|
|
|
|
"ca_ES" => "Spain (ca)",
|
|
|
|
"cs_CZ" => "Czech Republic",
|
|
|
|
"ro_RO" => "Romania",
|
|
|
|
"el_GR" => "Greece",
|
|
|
|
"zh_CN" => "China",
|
|
|
|
"zh_HK" => "Hong Kong",
|
|
|
|
"en_NZ" => "New Zealand",
|
|
|
|
"fr_FR" => "France",
|
|
|
|
"th_TH" => "Thailand",
|
|
|
|
"ko_KR" => "South Korea",
|
|
|
|
"sv_SE" => "Sweden",
|
|
|
|
"nb_NO" => "Norway",
|
|
|
|
"da_DK" => "Denmark",
|
|
|
|
"hu_HU" => "Hungary",
|
|
|
|
"et_EE" => "Estonia",
|
|
|
|
"es_MX" => "Mexico",
|
|
|
|
"es_CL" => "Chile",
|
|
|
|
"en_CA" => "Canada (en)",
|
|
|
|
"fr_CA" => "Canada (fr)",
|
|
|
|
"en_MY" => "Malaysia",
|
|
|
|
"bg_BG" => "Bulgaria",
|
|
|
|
"fi_FI" => "Finland",
|
|
|
|
"pl_PL" => "Poland",
|
|
|
|
"nl_NL" => "Netherlands",
|
|
|
|
"pt_PT" => "Portugal",
|
|
|
|
"de_CH" => "Switzerland (de)",
|
|
|
|
"fr_CH" => "Switzerland (fr)",
|
|
|
|
"it_CH" => "Switzerland (it)",
|
|
|
|
"de_AT" => "Austria",
|
|
|
|
"fr_BE" => "Belgium (fr)",
|
|
|
|
"nl_BE" => "Belgium (nl)",
|
|
|
|
"en_IE" => "Ireland",
|
|
|
|
"he_IL" => "Israel"
|
|
|
|
]
|
|
|
|
]
|
|
|
|
];
|
|
|
|
|
|
|
|
switch($page){
|
|
|
|
|
|
|
|
case "web":
|
|
|
|
$base = array_merge(
|
|
|
|
$base,
|
|
|
|
[
|
|
|
|
"time" => [
|
|
|
|
"display" => "Time posted",
|
|
|
|
"option" => [
|
|
|
|
"any" => "Any time",
|
|
|
|
"day" => "Past 24 hours",
|
|
|
|
"week" => "Past week",
|
|
|
|
"month" => "Past month"
|
|
|
|
]
|
|
|
|
],
|
|
|
|
"extendedsearch" => [
|
|
|
|
// no display, wont show in interface
|
|
|
|
"option" => [
|
|
|
|
"yes" => "Yes",
|
|
|
|
"no" => "No"
|
|
|
|
]
|
|
|
|
]
|
|
|
|
]
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "images":
|
|
|
|
$base = array_merge(
|
|
|
|
$base,
|
|
|
|
[
|
|
|
|
"time" => [
|
|
|
|
"display" => "Time posted",
|
|
|
|
"option" => [
|
|
|
|
"any" => "Any time",
|
|
|
|
"day" => "Past 24 hours",
|
|
|
|
"week" => "Past week",
|
|
|
|
"month" => "Past month"
|
|
|
|
]
|
|
|
|
],
|
|
|
|
"size" => [
|
|
|
|
"display" => "Size",
|
|
|
|
"option" => [
|
|
|
|
"any" => "Any size",
|
|
|
|
"large" => "Large",
|
|
|
|
"medium" => "Medium",
|
|
|
|
"small" => "Small"
|
|
|
|
]
|
|
|
|
],
|
|
|
|
"color" => [
|
|
|
|
"display" => "Color",
|
|
|
|
"option" => [
|
|
|
|
"any" => "Any color",
|
|
|
|
"coloronly" => "Color only",
|
|
|
|
"monochrome" => "Monochrome",
|
|
|
|
"black" => "Black",
|
|
|
|
"brown" => "Brown",
|
|
|
|
"gray" => "Gray",
|
|
|
|
"white" => "White",
|
|
|
|
"yellow" => "Yellow",
|
|
|
|
"orange" => "Orange",
|
|
|
|
"red" => "Red",
|
|
|
|
"pink" => "Pink",
|
|
|
|
"purple" => "Purple",
|
|
|
|
"blue" => "Blue",
|
|
|
|
"teal" => "Teal",
|
|
|
|
"green" => "Green"
|
|
|
|
]
|
|
|
|
],
|
|
|
|
"imagetype" => [
|
|
|
|
"display" => "Type",
|
|
|
|
"option" => [
|
|
|
|
"any" => "Any type",
|
|
|
|
"animatedgif" => "Animated GIF",
|
|
|
|
"photo" => "Photograph",
|
|
|
|
"transparent" => "Transparent"
|
|
|
|
]
|
|
|
|
],
|
|
|
|
"license" => [
|
|
|
|
"display" => "License",
|
|
|
|
"option" => [
|
|
|
|
"any" => "Any license",
|
|
|
|
"share" => "Non-commercial reproduction and sharing",
|
|
|
|
"sharecommercially" => "Reproduction and sharing",
|
|
|
|
"modify" => "Non-commercial reproduction, sharing and modification",
|
|
|
|
"modifycommercially" => "Reproduction, sharing and modification",
|
|
|
|
"public" => "Public domain"
|
|
|
|
]
|
|
|
|
]
|
|
|
|
]
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "videos":
|
|
|
|
$base = array_merge(
|
|
|
|
$base,
|
|
|
|
[
|
|
|
|
"order" => [
|
|
|
|
"display" => "Order by",
|
|
|
|
"option" => [
|
|
|
|
"relevance" => "Relevance",
|
|
|
|
"views" => "Views",
|
|
|
|
"date" => "Most recent",
|
|
|
|
]
|
|
|
|
],
|
|
|
|
"source" => [
|
|
|
|
"display" => "Source",
|
|
|
|
"option" => [
|
|
|
|
"any" => "Any source",
|
|
|
|
"youtube" => "YouTube",
|
|
|
|
"dailymotion" => "Dailymotion",
|
|
|
|
]
|
|
|
|
]
|
|
|
|
]
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "news":
|
|
|
|
$base = array_merge(
|
|
|
|
$base,
|
|
|
|
[
|
|
|
|
"time" => [
|
|
|
|
"display" => "Time posted",
|
|
|
|
"option" => [
|
|
|
|
"any" => "Any time",
|
|
|
|
"hour" => "Less than 1 hour ago",
|
|
|
|
"day" => "Past 24 hours",
|
|
|
|
"week" => "Past week",
|
|
|
|
"month" => "Past month"
|
|
|
|
]
|
|
|
|
],
|
|
|
|
"order" => [
|
|
|
|
"display" => "Order by",
|
|
|
|
"option" => [
|
|
|
|
"relevance" => "Relevance",
|
|
|
|
"date" => "Most recent"
|
|
|
|
]
|
|
|
|
]
|
|
|
|
]
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $base;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function get($proxy, $url, $get = []){
|
|
|
|
|
|
|
|
$headers = [
|
|
|
|
"User-Agent: " . config::USER_AGENT,
|
|
|
|
"Accept: application/json, text/plain, */*",
|
|
|
|
"Accept-Language: en-US,en;q=0.5",
|
|
|
|
"Accept-Encoding: gzip",
|
|
|
|
"DNT: 1",
|
|
|
|
"Connection: keep-alive",
|
|
|
|
"Origin: https://www.qwant.com",
|
|
|
|
"Referer: https://www.qwant.com/",
|
|
|
|
"Sec-Fetch-Dest: empty",
|
|
|
|
"Sec-Fetch-Mode: cors",
|
|
|
|
"Sec-Fetch-Site: same-site",
|
|
|
|
"TE: trailers"
|
|
|
|
];
|
|
|
|
|
|
|
|
$curlproc = curl_init();
|
|
|
|
|
|
|
|
if($get !== []){
|
|
|
|
$get = http_build_query($get);
|
|
|
|
$url .= "?" . $get;
|
|
|
|
}
|
|
|
|
|
|
|
|
curl_setopt($curlproc, CURLOPT_URL, $url);
|
|
|
|
|
|
|
|
curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding
|
|
|
|
curl_setopt($curlproc, CURLOPT_HTTPHEADER, $headers);
|
|
|
|
|
|
|
|
// Bypass HTTP/2 check
|
|
|
|
curl_setopt($curlproc, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
|
|
|
|
|
|
|
|
curl_setopt($curlproc, CURLOPT_RETURNTRANSFER, true);
|
|
|
|
curl_setopt($curlproc, CURLOPT_SSL_VERIFYHOST, 2);
|
|
|
|
curl_setopt($curlproc, CURLOPT_SSL_VERIFYPEER, true);
|
|
|
|
curl_setopt($curlproc, CURLOPT_CONNECTTIMEOUT, 30);
|
|
|
|
curl_setopt($curlproc, CURLOPT_TIMEOUT, 30);
|
|
|
|
|
|
|
|
$this->backend->assign_proxy($curlproc, $proxy);
|
|
|
|
|
|
|
|
$data = curl_exec($curlproc);
|
|
|
|
|
|
|
|
if(curl_errno($curlproc)){
|
|
|
|
throw new Exception(curl_error($curlproc));
|
|
|
|
}
|
|
|
|
|
|
|
|
curl_close($curlproc);
|
2024-04-22 15:12:46 +00:00
|
|
|
|
2024-04-21 23:31:56 +00:00
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function web($get){
|
|
|
|
|
|
|
|
if($get["npt"]){
|
|
|
|
|
|
|
|
// get next page data
|
|
|
|
[$params, $proxy] = $this->backend->get($get["npt"], "web");
|
|
|
|
|
|
|
|
$params = json_decode($params, true);
|
|
|
|
|
|
|
|
}else{
|
|
|
|
|
|
|
|
// get _GET data instead
|
|
|
|
$search = $get["s"];
|
|
|
|
if(strlen($search) === 0){
|
|
|
|
|
|
|
|
throw new Exception("Search term is empty!");
|
|
|
|
}
|
|
|
|
|
|
|
|
if(strlen($search) > 2048){
|
|
|
|
|
|
|
|
throw new Exception("Search term is too long!");
|
|
|
|
}
|
|
|
|
|
|
|
|
$proxy = $this->backend->get_ip();
|
|
|
|
|
|
|
|
$params = [
|
|
|
|
"q" => $search,
|
|
|
|
"freshness" => $get["time"],
|
|
|
|
"count" => 10,
|
|
|
|
"locale" => $get["country"],
|
|
|
|
"offset" => 0,
|
|
|
|
"device" => "desktop",
|
|
|
|
"tgp" => 3,
|
|
|
|
"safesearch" => 0,
|
|
|
|
"displayed" => "true"
|
|
|
|
];
|
|
|
|
|
|
|
|
switch($get["nsfw"]){
|
|
|
|
|
|
|
|
case "yes": $params["safesearch"] = 0; break;
|
|
|
|
case "maybe": $params["safesearch"] = 1; break;
|
|
|
|
case "no": $params["safesearch"] = 2; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
$handle = fopen("scraper/qwant_web.json", "r");
|
|
|
|
$json = fread($handle, filesize("scraper/qwant_web.json"));
|
|
|
|
fclose($handle);*/
|
|
|
|
|
|
|
|
try{
|
|
|
|
$json =
|
|
|
|
$this->get(
|
|
|
|
$proxy,
|
|
|
|
"https://fdn.qwant.com/v3/search/web",
|
|
|
|
$params
|
|
|
|
);
|
|
|
|
|
|
|
|
}catch(Exception $error){
|
|
|
|
|
|
|
|
throw new Exception("Could not fetch JSON");
|
|
|
|
}
|
|
|
|
|
|
|
|
$json = json_decode($json, true);
|
|
|
|
|
|
|
|
if($json === NULL){
|
|
|
|
|
|
|
|
throw new Exception("Failed to decode JSON");
|
|
|
|
}
|
|
|
|
|
|
|
|
if(isset($json["data"]["message"][0])){
|
|
|
|
|
|
|
|
throw new Exception("Server returned an error:\n" . $json["data"]["message"][0]);
|
|
|
|
}
|
|
|
|
|
2024-04-22 00:26:10 +00:00
|
|
|
$out = [
|
|
|
|
"status" => "ok",
|
|
|
|
"spelling" => [
|
|
|
|
"type" => "no_correction",
|
|
|
|
"using" => null,
|
|
|
|
"correction" => null
|
|
|
|
],
|
|
|
|
"npt" => null,
|
|
|
|
"answer" => [],
|
|
|
|
"web" => [],
|
|
|
|
"image" => [],
|
|
|
|
"video" => [],
|
|
|
|
"news" => [],
|
|
|
|
"related" => []
|
|
|
|
];
|
|
|
|
|
2024-10-09 22:34:36 +00:00
|
|
|
if(
|
|
|
|
$json["status"] != "success" &&
|
|
|
|
$json["data"]["error_code"] === 5
|
|
|
|
){
|
2024-05-30 23:13:47 +00:00
|
|
|
|
2024-10-09 22:34:36 +00:00
|
|
|
// no results
|
|
|
|
return $out;
|
2024-04-21 23:31:56 +00:00
|
|
|
}
|
|
|
|
|
2024-10-09 22:34:36 +00:00
|
|
|
$this->detect_errors($json);
|
|
|
|
|
2024-04-21 23:31:56 +00:00
|
|
|
if(!isset($json["data"]["result"]["items"]["mainline"])){
|
|
|
|
|
|
|
|
throw new Exception("Server did not return a result object");
|
|
|
|
}
|
|
|
|
|
|
|
|
// data is OK, parse
|
|
|
|
|
|
|
|
// get instant answer
|
|
|
|
if(
|
|
|
|
$get["extendedsearch"] == "yes" &&
|
|
|
|
isset($json["data"]["result"]["items"]["sidebar"][0]["endpoint"])
|
|
|
|
){
|
|
|
|
|
|
|
|
try{
|
|
|
|
$answer =
|
|
|
|
$this->get(
|
|
|
|
$proxy,
|
|
|
|
"https://api.qwant.com/v3" .
|
|
|
|
$json["data"]["result"]["items"]["sidebar"][0]["endpoint"],
|
|
|
|
[]
|
|
|
|
);
|
|
|
|
|
|
|
|
$answer = json_decode($answer, true);
|
|
|
|
|
|
|
|
if(
|
|
|
|
$answer === null ||
|
|
|
|
$answer["status"] != "success" ||
|
|
|
|
$answer["data"]["result"] === null
|
|
|
|
){
|
|
|
|
|
|
|
|
throw new Exception();
|
|
|
|
}
|
|
|
|
|
|
|
|
// parse answer
|
|
|
|
$out["answer"][] = [
|
|
|
|
"title" => $answer["data"]["result"]["title"],
|
|
|
|
"description" => [
|
|
|
|
[
|
|
|
|
"type" => "text",
|
|
|
|
"value" => $this->trimdots($answer["data"]["result"]["description"])
|
|
|
|
]
|
|
|
|
],
|
|
|
|
"url" => $answer["data"]["result"]["url"],
|
|
|
|
"thumb" =>
|
|
|
|
$answer["data"]["result"]["thumbnail"]["landscape"] == null ?
|
|
|
|
null :
|
|
|
|
$this->unshitimage(
|
|
|
|
$answer["data"]["result"]["thumbnail"]["landscape"],
|
|
|
|
false
|
|
|
|
),
|
|
|
|
"table" => [],
|
|
|
|
"sublink" => []
|
|
|
|
];
|
|
|
|
|
|
|
|
}catch(Exception $error){
|
|
|
|
|
|
|
|
// do nothing in case of failure
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// get word correction
|
|
|
|
if(isset($json["data"]["query"]["queryContext"]["alteredQuery"])){
|
|
|
|
|
|
|
|
$out["spelling"] = [
|
|
|
|
"type" => "including",
|
|
|
|
"using" => $json["data"]["query"]["queryContext"]["alteredQuery"],
|
|
|
|
"correction" => $json["data"]["query"]["queryContext"]["alterationOverrideQuery"]
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
// check for next page
|
|
|
|
if($json["data"]["result"]["lastPage"] === false){
|
|
|
|
|
|
|
|
$params["offset"] = $params["offset"] + 10;
|
|
|
|
|
|
|
|
$out["npt"] =
|
|
|
|
$this->backend->store(
|
|
|
|
json_encode($params),
|
|
|
|
"web",
|
|
|
|
$proxy
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// parse results
|
|
|
|
foreach($json["data"]["result"]["items"]["mainline"] as $item){
|
|
|
|
|
|
|
|
switch($item["type"]){ // ignores ads
|
|
|
|
|
|
|
|
case "web":
|
2024-04-27 18:25:39 +00:00
|
|
|
|
|
|
|
$first_iteration = true;
|
2024-04-21 23:31:56 +00:00
|
|
|
foreach($item["items"] as $result){
|
|
|
|
|
|
|
|
if(isset($result["thumbnailUrl"])){
|
|
|
|
|
|
|
|
$thumb = [
|
|
|
|
"url" => $this->unshitimage($result["thumbnailUrl"]),
|
|
|
|
"ratio" => "16:9"
|
|
|
|
];
|
|
|
|
}else{
|
|
|
|
|
|
|
|
$thumb = [
|
|
|
|
"url" => null,
|
|
|
|
"ratio" => null
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
$sublinks = [];
|
|
|
|
if(isset($result["links"])){
|
|
|
|
|
|
|
|
foreach($result["links"] as $link){
|
|
|
|
|
|
|
|
$sublinks[] = [
|
|
|
|
"title" => $this->trimdots($link["title"]),
|
|
|
|
"date" => null,
|
|
|
|
"description" => isset($link["desc"]) ? $this->trimdots($link["desc"]) : null,
|
|
|
|
"url" => $link["url"]
|
|
|
|
];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-27 18:25:39 +00:00
|
|
|
// detect gibberish results
|
|
|
|
if(
|
|
|
|
$first_iteration &&
|
2024-05-30 23:13:47 +00:00
|
|
|
!isset($result["urlPingSuffix"])
|
2024-04-27 18:25:39 +00:00
|
|
|
){
|
|
|
|
|
|
|
|
throw new Exception("Qwant returned gibberish results");
|
|
|
|
}
|
|
|
|
|
2024-04-21 23:31:56 +00:00
|
|
|
$out["web"][] = [
|
|
|
|
"title" => $this->trimdots($result["title"]),
|
|
|
|
"description" => $this->trimdots($result["desc"]),
|
|
|
|
"url" => $result["url"],
|
|
|
|
"date" => null,
|
|
|
|
"type" => "web",
|
|
|
|
"thumb" => $thumb,
|
|
|
|
"sublink" => $sublinks,
|
|
|
|
"table" => []
|
|
|
|
];
|
2024-04-27 18:25:39 +00:00
|
|
|
|
|
|
|
$first_iteration = false;
|
2024-04-21 23:31:56 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "images":
|
|
|
|
foreach($item["items"] as $image){
|
|
|
|
|
|
|
|
$out["image"][] = [
|
|
|
|
"title" => $image["title"],
|
|
|
|
"source" => [
|
|
|
|
[
|
|
|
|
"url" => $image["media"],
|
|
|
|
"width" => (int)$image["width"],
|
|
|
|
"height" => (int)$image["height"]
|
|
|
|
],
|
|
|
|
[
|
|
|
|
"url" => $this->unshitimage($image["thumbnail"]),
|
|
|
|
"width" => $image["thumb_width"],
|
|
|
|
"height" => $image["thumb_height"]
|
|
|
|
]
|
|
|
|
],
|
|
|
|
"url" => $image["url"]
|
|
|
|
];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "videos":
|
|
|
|
foreach($item["items"] as $video){
|
|
|
|
|
|
|
|
$out["video"][] = [
|
|
|
|
"title" => $video["title"],
|
|
|
|
"description" => null,
|
|
|
|
"date" => (int)$video["date"],
|
|
|
|
"duration" => $video["duration"] === null ? null : $video["duration"] / 1000,
|
|
|
|
"views" => null,
|
|
|
|
"thumb" =>
|
|
|
|
$video["thumbnail"] === null ?
|
|
|
|
[
|
|
|
|
"url" => null,
|
|
|
|
"ratio" => null,
|
|
|
|
] :
|
|
|
|
[
|
|
|
|
"url" => $this->unshitimage($video["thumbnail"]),
|
|
|
|
"ratio" => "16:9",
|
|
|
|
],
|
|
|
|
"url" => $video["url"]
|
|
|
|
];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "related_searches":
|
|
|
|
foreach($item["items"] as $related){
|
|
|
|
|
|
|
|
$out["related"][] = $related["text"];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $out;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function image($get){
|
|
|
|
|
|
|
|
if($get["npt"]){
|
|
|
|
|
|
|
|
[$params, $proxy] =
|
|
|
|
$this->backend->get(
|
|
|
|
$get["npt"],
|
|
|
|
"images"
|
|
|
|
);
|
|
|
|
|
|
|
|
$params = json_decode($params, true);
|
|
|
|
}else{
|
|
|
|
|
|
|
|
$search = $get["s"];
|
|
|
|
|
|
|
|
if(strlen($search) === 0){
|
|
|
|
|
|
|
|
throw new Exception("Search term is empty!");
|
|
|
|
}
|
|
|
|
|
|
|
|
$proxy = $this->backend->get_ip();
|
|
|
|
|
|
|
|
$params = [
|
|
|
|
"t" => "images",
|
|
|
|
"q" => $search,
|
|
|
|
"count" => 125,
|
|
|
|
"locale" => $get["country"],
|
|
|
|
"offset" => 0, // increment by 125
|
|
|
|
"device" => "desktop",
|
|
|
|
"tgp" => 3
|
|
|
|
];
|
|
|
|
|
|
|
|
if($get["time"] != "any"){
|
|
|
|
|
|
|
|
$params["freshness"] = $get["time"];
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach(["size", "color", "imagetype", "license"] as $p){
|
|
|
|
|
|
|
|
if($get[$p] != "any"){
|
|
|
|
|
|
|
|
$params[$p] = $get[$p];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch($get["nsfw"]){
|
|
|
|
|
|
|
|
case "yes": $params["safesearch"] = 0; break;
|
|
|
|
case "maybe": $params["safesearch"] = 1; break;
|
|
|
|
case "no": $params["safesearch"] = 2; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
try{
|
|
|
|
$json = $this->get(
|
|
|
|
$proxy,
|
|
|
|
"https://api.qwant.com/v3/search/images",
|
|
|
|
$params,
|
|
|
|
);
|
|
|
|
}catch(Exception $err){
|
|
|
|
|
|
|
|
throw new Exception("Failed to get JSON");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
$handle = fopen("scraper/yandex.json", "r");
|
|
|
|
$json = fread($handle, filesize("scraper/yandex.json"));
|
|
|
|
fclose($handle);*/
|
|
|
|
|
|
|
|
$json = json_decode($json, true);
|
|
|
|
|
|
|
|
if($json === null){
|
|
|
|
|
|
|
|
throw new Exception("Failed to decode JSON");
|
|
|
|
}
|
|
|
|
|
2024-10-09 22:34:36 +00:00
|
|
|
$this->detect_errors($json);
|
2024-04-21 23:31:56 +00:00
|
|
|
|
2024-04-27 19:03:56 +00:00
|
|
|
if(isset($json["data"]["result"]["items"]["mainline"])){
|
|
|
|
|
|
|
|
throw new Exception("Qwant returned gibberish results");
|
|
|
|
}
|
|
|
|
|
2024-04-21 23:31:56 +00:00
|
|
|
$out = [
|
|
|
|
"status" => "ok",
|
|
|
|
"npt" => null,
|
|
|
|
"image" => []
|
|
|
|
];
|
|
|
|
|
|
|
|
if($json["data"]["result"]["lastPage"] === false){
|
|
|
|
|
|
|
|
$params["offset"] = $params["offset"] + 125;
|
|
|
|
|
|
|
|
$out["npt"] = $this->backend->store(
|
|
|
|
json_encode($params),
|
|
|
|
"images",
|
|
|
|
$proxy
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach($json["data"]["result"]["items"] as $image){
|
|
|
|
|
|
|
|
$out["image"][] = [
|
|
|
|
"title" => $this->trimdots($image["title"]),
|
|
|
|
"source" => [
|
|
|
|
[
|
|
|
|
"url" => $image["media"],
|
|
|
|
"width" => $image["width"],
|
|
|
|
"height" => $image["height"]
|
|
|
|
],
|
|
|
|
[
|
|
|
|
"url" => $this->unshitimage($image["thumbnail"]),
|
|
|
|
"width" => $image["thumb_width"],
|
|
|
|
"height" => $image["thumb_height"]
|
|
|
|
]
|
|
|
|
],
|
|
|
|
"url" => $image["url"]
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
return $out;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function video($get){
|
|
|
|
|
|
|
|
$search = $get["s"];
|
|
|
|
if(strlen($search) === 0){
|
|
|
|
|
|
|
|
throw new Exception("Search term is empty!");
|
|
|
|
}
|
|
|
|
|
|
|
|
$params = [
|
|
|
|
"t" => "videos",
|
|
|
|
"q" => $search,
|
|
|
|
"count" => 50,
|
|
|
|
"locale" => $get["country"],
|
|
|
|
"offset" => 0, // dont implement pagination
|
|
|
|
"device" => "desktop",
|
|
|
|
"tgp" => 3
|
|
|
|
];
|
|
|
|
|
|
|
|
switch($get["nsfw"]){
|
|
|
|
|
|
|
|
case "yes": $params["safesearch"] = 0; break;
|
|
|
|
case "maybe": $params["safesearch"] = 1; break;
|
|
|
|
case "no": $params["safesearch"] = 2; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
try{
|
|
|
|
$json =
|
|
|
|
$this->get(
|
|
|
|
$this->backend->get_ip(),
|
|
|
|
"https://api.qwant.com/v3/search/videos",
|
|
|
|
$params
|
|
|
|
);
|
|
|
|
}catch(Exception $error){
|
|
|
|
|
|
|
|
throw new Exception("Could not fetch JSON");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
$handle = fopen("scraper/yandex-video.json", "r");
|
|
|
|
$json = fread($handle, filesize("scraper/yandex-video.json"));
|
|
|
|
fclose($handle);
|
|
|
|
*/
|
|
|
|
|
|
|
|
$json = json_decode($json, true);
|
|
|
|
|
|
|
|
if($json === null){
|
|
|
|
|
|
|
|
throw new Exception("Could not parse JSON");
|
|
|
|
}
|
|
|
|
|
2024-10-09 22:34:36 +00:00
|
|
|
$this->detect_errors($json);
|
2024-04-21 23:31:56 +00:00
|
|
|
|
2024-04-27 19:03:56 +00:00
|
|
|
if(isset($json["data"]["result"]["items"]["mainline"])){
|
|
|
|
|
|
|
|
throw new Exception("Qwant returned gibberish results");
|
|
|
|
}
|
|
|
|
|
2024-04-21 23:31:56 +00:00
|
|
|
$out = [
|
|
|
|
"status" => "ok",
|
|
|
|
"npt" => null,
|
|
|
|
"video" => [],
|
|
|
|
"author" => [],
|
|
|
|
"livestream" => [],
|
|
|
|
"playlist" => [],
|
|
|
|
"reel" => []
|
|
|
|
];
|
|
|
|
|
|
|
|
foreach($json["data"]["result"]["items"] as $video){
|
|
|
|
|
|
|
|
if(empty($video["thumbnail"])){
|
|
|
|
|
|
|
|
$thumb = [
|
|
|
|
"url" => null,
|
|
|
|
"ratio" => null
|
|
|
|
];
|
|
|
|
}else{
|
|
|
|
|
|
|
|
$thumb = [
|
|
|
|
"url" => $this->unshitimage($video["thumbnail"], false),
|
|
|
|
"ratio" => "16:9"
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
$duration = (int)$video["duration"];
|
|
|
|
|
|
|
|
$out["video"][] = [
|
|
|
|
"title" => $video["title"],
|
|
|
|
"description" => $this->limitstrlen($video["desc"]),
|
|
|
|
"author" => [
|
|
|
|
"name" => $video["channel"],
|
|
|
|
"url" => null,
|
|
|
|
"avatar" => null
|
|
|
|
],
|
|
|
|
"date" => (int)$video["date"],
|
|
|
|
"duration" => $duration === 0 ? null : $duration,
|
|
|
|
"views" => null,
|
|
|
|
"thumb" => $thumb,
|
|
|
|
"url" => preg_replace("/\?syndication=.+/", "", $video["url"])
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
return $out;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function news($get){
|
|
|
|
|
|
|
|
$search = $get["s"];
|
|
|
|
if(strlen($search) === 0){
|
|
|
|
|
|
|
|
throw new Exception("Search term is empty!");
|
|
|
|
}
|
|
|
|
|
|
|
|
$params = [
|
|
|
|
"t" => "news",
|
|
|
|
"q" => $search,
|
|
|
|
"count" => 50,
|
|
|
|
"locale" => $get["country"],
|
|
|
|
"offset" => 0, // dont implement pagination
|
|
|
|
"device" => "desktop",
|
|
|
|
"tgp" => 3
|
|
|
|
];
|
|
|
|
|
|
|
|
switch($get["nsfw"]){
|
|
|
|
|
|
|
|
case "yes": $params["safesearch"] = 0; break;
|
|
|
|
case "maybe": $params["safesearch"] = 1; break;
|
|
|
|
case "no": $params["safesearch"] = 2; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
try{
|
|
|
|
$json =
|
|
|
|
$this->get(
|
|
|
|
$this->backend->get_ip(),
|
|
|
|
"https://api.qwant.com/v3/search/news",
|
|
|
|
$params
|
|
|
|
);
|
|
|
|
}catch(Exception $error){
|
|
|
|
|
|
|
|
throw new Exception("Could not fetch JSON");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
$handle = fopen("scraper/yandex-video.json", "r");
|
|
|
|
$json = fread($handle, filesize("scraper/yandex-video.json"));
|
|
|
|
fclose($handle);
|
|
|
|
*/
|
|
|
|
|
|
|
|
$json = json_decode($json, true);
|
|
|
|
|
|
|
|
if($json === null){
|
|
|
|
|
|
|
|
throw new Exception("Could not parse JSON");
|
|
|
|
}
|
|
|
|
|
2024-10-09 22:34:36 +00:00
|
|
|
$this->detect_errors($json);
|
2024-04-21 23:31:56 +00:00
|
|
|
|
2024-04-27 19:03:56 +00:00
|
|
|
if(isset($json["data"]["result"]["items"]["mainline"])){
|
|
|
|
|
|
|
|
throw new Exception("Qwant returned gibberish results");
|
|
|
|
}
|
|
|
|
|
2024-04-21 23:31:56 +00:00
|
|
|
$out = [
|
|
|
|
"status" => "ok",
|
|
|
|
"npt" => null,
|
|
|
|
"news" => []
|
|
|
|
];
|
|
|
|
|
|
|
|
foreach($json["data"]["result"]["items"] as $news){
|
|
|
|
|
|
|
|
if(empty($news["media"][0]["pict_big"]["url"])){
|
|
|
|
|
|
|
|
$thumb = [
|
|
|
|
"url" => null,
|
|
|
|
"ratio" => null
|
|
|
|
];
|
|
|
|
}else{
|
|
|
|
|
|
|
|
$thumb = [
|
|
|
|
"url" => $this->unshitimage($news["media"][0]["pict_big"]["url"], false),
|
|
|
|
"ratio" => "16:9"
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
$out["news"][] = [
|
|
|
|
"title" => $news["title"],
|
|
|
|
"author" => $news["press_name"],
|
|
|
|
"description" => $this->trimdots($news["desc"]),
|
|
|
|
"date" => (int)$news["date"],
|
|
|
|
"thumb" => $thumb,
|
|
|
|
"url" => $news["url"]
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
return $out;
|
|
|
|
}
|
|
|
|
|
2024-10-09 22:34:36 +00:00
|
|
|
private function detect_errors($json){
|
|
|
|
|
|
|
|
if(
|
|
|
|
isset($json["status"]) &&
|
|
|
|
$json["status"] == "error"
|
|
|
|
){
|
|
|
|
|
|
|
|
if(isset($json["data"]["error_data"]["captchaUrl"])){
|
|
|
|
|
|
|
|
throw new Exception("Qwant returned a captcha");
|
|
|
|
}elseif(isset($json["data"]["error_data"]["error_code"])){
|
|
|
|
|
|
|
|
throw new Exception(
|
|
|
|
"Qwant returned an API error: " .
|
|
|
|
$json["data"]["error_data"]["error_code"]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new Exception("Qwant returned an API error");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-21 23:31:56 +00:00
|
|
|
private function limitstrlen($text){
|
|
|
|
|
|
|
|
return explode("\n", wordwrap($text, 300, "\n"))[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
private function trimdots($text){
|
|
|
|
|
|
|
|
return trim($text, ". ");
|
|
|
|
}
|
|
|
|
|
|
|
|
private function unshitimage($url, $is_bing = true){
|
|
|
|
|
|
|
|
// https://s1.qwant.com/thumbr/0x0/8/d/f6de4deb2c2b12f55d8bdcaae576f9f62fd58a05ec0feeac117b354d1bf5c2/th.jpg?u=https%3A%2F%2Fwww.bing.com%2Fth%3Fid%3DOIP.vvDWsagzxjoKKP_rOqhwrQAAAA%26w%3D160%26h%3D160%26c%3D7%26pid%3D5.1&q=0&b=1&p=0&a=0
|
|
|
|
parse_str(parse_url($url)["query"], $parts);
|
|
|
|
|
|
|
|
if($is_bing){
|
|
|
|
$parse = parse_url($parts["u"]);
|
|
|
|
parse_str($parse["query"], $parts);
|
|
|
|
|
|
|
|
return "https://" . $parse["host"] . "/th?id=" . urlencode($parts["id"]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $parts["u"];
|
|
|
|
}
|
|
|
|
}
|