1735 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			1735 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
//$yt = new youtube();
 | 
						|
//header("Content-Type: application/json");
 | 
						|
//echo json_encode($yt->video("minecraft", null, "today", "any", "any", "live", "relevance"));
 | 
						|
 | 
						|
class youtube{
 | 
						|
	
 | 
						|
	public function __construct(){
 | 
						|
		
 | 
						|
		include "lib/backend.php";
 | 
						|
		$this->backend = new backend("yt");
 | 
						|
	}
 | 
						|
	
 | 
						|
	public function getfilters($page){
 | 
						|
		
 | 
						|
		if($page != "videos"){
 | 
						|
			
 | 
						|
			return [];
 | 
						|
		}
 | 
						|
		
 | 
						|
		return [
 | 
						|
			"date" => [
 | 
						|
				"display" => "Time posted",
 | 
						|
				"option" => [
 | 
						|
					"any" => "Any time",
 | 
						|
					"hour" => "Last hour",
 | 
						|
					"today" => "Today",
 | 
						|
					"week" => "This week",
 | 
						|
					"month" => "This month",
 | 
						|
					"year" => "This year"
 | 
						|
				]
 | 
						|
			],
 | 
						|
			"type" => [
 | 
						|
				"display" => "Type",
 | 
						|
				"option" => [
 | 
						|
					"video" => "Video",
 | 
						|
					"channel" => "Channel",
 | 
						|
					"playlist" => "Playlist",
 | 
						|
					"Movie" => "Movie"
 | 
						|
				]
 | 
						|
			],
 | 
						|
			"duration" => [
 | 
						|
				"display" => "Duration",
 | 
						|
				"option" => [
 | 
						|
					"any" => "Any duration",
 | 
						|
					"short" => "Short (>4min)",
 | 
						|
					"medium" => "Medium (4-20min)",
 | 
						|
					"long" => "Long (<20min)"
 | 
						|
				]
 | 
						|
			],
 | 
						|
			"feature" => [
 | 
						|
				"display" => "Feature",
 | 
						|
				"option" => [
 | 
						|
					"any" => "No features",
 | 
						|
					"live" => "Live",
 | 
						|
					"4k" => "4K",
 | 
						|
					"hd" => "HD",
 | 
						|
					"subtitles" => "Subtitles/CC",
 | 
						|
					"creativecommons" => "Creative Commons",
 | 
						|
					"360" => "VR 360°",
 | 
						|
					"vr180" => "VR 180°",
 | 
						|
					"3d" => "3D",
 | 
						|
					"hdr" => "HDR"
 | 
						|
				]
 | 
						|
			],
 | 
						|
			"sort" => [
 | 
						|
				"display" => "Sort by",
 | 
						|
				"option" => [
 | 
						|
					"relevance" => "Relevance",
 | 
						|
					"upload_date" => "Upload date",
 | 
						|
					"view_count" => "View count",
 | 
						|
					"rating" => "Rating"
 | 
						|
				]
 | 
						|
			]
 | 
						|
		];
 | 
						|
	}
 | 
						|
	
 | 
						|
	private function ytfilter($date, $type, $duration, $feature, $sort){
 | 
						|
		
 | 
						|
		// ------------
 | 
						|
		// INCOMPATIBLE FILTERS
 | 
						|
		// channel,playlist		DURATION, FEATURES, SORT BY
 | 
						|
		// Movie				Features=[live, subtitles, creative commons, 3d]
 | 
						|
		
 | 
						|
		// live, 3D
 | 
						|
		// Type[channel, playlist, movie]
 | 
						|
		
 | 
						|
		// UPLOAD DATE, DURATION, 4k, 360, VR180, HDR
 | 
						|
		// Type[channel, playlist]
 | 
						|
		
 | 
						|
		// -----------
 | 
						|
		
 | 
						|
		// MUST BE TOGETHER
 | 
						|
		// Relevance,upload date		Type=Video
 | 
						|
		
 | 
						|
		switch($type){
 | 
						|
			
 | 
						|
			case "channel":
 | 
						|
			case "playlist":
 | 
						|
				if($duration != "any"){ $duration = "any"; }
 | 
						|
				if($feature != "any"){ $feature = "any"; }
 | 
						|
				if($sort != "any"){ $sort = "any"; }
 | 
						|
				break;
 | 
						|
			
 | 
						|
			case "movie":
 | 
						|
				if(
 | 
						|
					in_array(
 | 
						|
						$feature,
 | 
						|
						[
 | 
						|
							"live",
 | 
						|
							"subtitles",
 | 
						|
							"creative_commons",
 | 
						|
							"3d"
 | 
						|
						],
 | 
						|
					)
 | 
						|
				){
 | 
						|
					
 | 
						|
					$feature = "any";
 | 
						|
				}
 | 
						|
				break;
 | 
						|
		}
 | 
						|
		
 | 
						|
		switch($feature){
 | 
						|
			
 | 
						|
			case "live":
 | 
						|
			case "3d":
 | 
						|
				if(
 | 
						|
					in_array(
 | 
						|
						$type,
 | 
						|
						[
 | 
						|
							"channel",
 | 
						|
							"playlist",
 | 
						|
							"movie"
 | 
						|
						],
 | 
						|
					)
 | 
						|
				){
 | 
						|
					
 | 
						|
					$type = "video";
 | 
						|
				}
 | 
						|
				break;
 | 
						|
		}
 | 
						|
		
 | 
						|
		if(
 | 
						|
			(
 | 
						|
				$date != "any" ||
 | 
						|
				$duration != "any" ||
 | 
						|
				$feature == "4k" ||
 | 
						|
				$feature == "360" ||
 | 
						|
				$feature == "vr180" ||
 | 
						|
				$feature == "hdr"
 | 
						|
			) &&
 | 
						|
			(
 | 
						|
				$type == "channel" ||
 | 
						|
				$type == "playlist"
 | 
						|
			)
 | 
						|
		){
 | 
						|
			
 | 
						|
			$type = "video";
 | 
						|
		}
 | 
						|
		
 | 
						|
		if(
 | 
						|
			$date == "any" &&
 | 
						|
			$type == "video" &&
 | 
						|
			$duration == "any" &&
 | 
						|
			$feature == "any" &&
 | 
						|
			$sort == "relevance"
 | 
						|
		){
 | 
						|
			
 | 
						|
			return null;
 | 
						|
		}
 | 
						|
		
 | 
						|
		//print_r([$date, $type, $duration, $feature, $sort]);
 | 
						|
		
 | 
						|
		/*
 | 
						|
			Encode hex data
 | 
						|
		*/
 | 
						|
		
 | 
						|
		// UPLOAD DATE
 | 
						|
		// hour				EgQIARAB			12 04 08 01 10 01
 | 
						|
		// today			EgQIAhAB			12 04 08 02 10 01
 | 
						|
		// week				EgQIAxAB			12 04 08 03 10 01
 | 
						|
		// month			EgQIBBAB			12 04 08 04 10 01
 | 
						|
		// year				EgQIBRAB			12 04 08 05 10 01
 | 
						|
		
 | 
						|
		// TYPE
 | 
						|
		// video			EgIQAQ%253D%253D	12 02 10 01
 | 
						|
		// channel			EgIQAg%253D%253D	12 02 10 02
 | 
						|
		// playlist			EgIQAw%253D%253D	12 02 10 03
 | 
						|
		// movie			EgIQBA%253D%253D	12 02 10 04
 | 
						|
		
 | 
						|
		// DURATION
 | 
						|
		// -4min			EgIYAQ%253D%253D	12 02 18 01
 | 
						|
		// 4-20min			EgIYAw%253D%253D	12 02 18 03
 | 
						|
		// 20+min			EgIYAg%253D%253D	12 02 18 02
 | 
						|
		
 | 
						|
		// FEATURE
 | 
						|
		// live				EgJAAQ%253D%253D	12 02 40 01
 | 
						|
		// 4K				EgJwAQ%253D%253D	12 02 70 01
 | 
						|
		// HD				EgIgAQ%253D%253D	12 02 20 01
 | 
						|
		// Subtitles/CC		EgIoAQ%253D%253D	12 02 28 01
 | 
						|
		// Creative Commons	EgIwAQ%253D%253D	12 02 30 01
 | 
						|
		// 360				EgJ4AQ%253D%253D	12 02 78 01
 | 
						|
		// VR180			EgPQAQE%253D		12 03 d0 01 01
 | 
						|
		// 3D				EgI4AQ%253D%253D	12 02 38 01
 | 
						|
		// HDR				EgPIAQE%253D		12 03 c8 01 01
 | 
						|
		// (location & purchased unused)
 | 
						|
		
 | 
						|
		// SORT BY
 | 
						|
		// Relevance		CAASAhAB			08 00 12 02 10 01 (is nothing by default)
 | 
						|
		// Upload date		CAI%253D			08 02
 | 
						|
		// View count		CAM%253D			08 03
 | 
						|
		// Rating			CAE%253D			08 01
 | 
						|
		
 | 
						|
		// video
 | 
						|
		// 12 02 10 01
 | 
						|
		
 | 
						|
		// under 4 minutes
 | 
						|
		// 12 02 18 01
 | 
						|
		
 | 
						|
		// video + under 4 minutes
 | 
						|
		// 12 04 10 01 18 01
 | 
						|
		
 | 
						|
		// video + under 4 minutes + HD
 | 
						|
		// 08 00 12 06 10 01 18 01 20 01
 | 
						|
		
 | 
						|
		// video + under 4 minutes + upload date
 | 
						|
		// 08 02 12 04 10 01 18 01
 | 
						|
		
 | 
						|
		// video + under 4 minutes + HD + upload date
 | 
						|
		// 08 02 12 06 10 01 18 01 20 01
 | 
						|
		
 | 
						|
		// this year + video + under 4 minutes + HD + upload date
 | 
						|
		// 08 02 12 08 08 05 10 01 18 01 20 01
 | 
						|
		
 | 
						|
		// this week + video + over 20 minutes + HD + view count
 | 
						|
		// 08 03 12 08 08 03 10 01 18 02 20 01
 | 
						|
		
 | 
						|
		//echo urlencode(urlencode(base64_encode(hex2bin($str))));
 | 
						|
		//echo bin2hex(base64_decode(urldecode(urldecode("CAI%253D"))));
 | 
						|
		
 | 
						|
		// week + video + 20min + rating
 | 
						|
		// 08 01 12 06 08 03 10 01 18 02
 | 
						|
		
 | 
						|
		// week + video + 20min + live + rating
 | 
						|
		// 08 01 12 08 08 03 10 01 18 02 40 01
 | 
						|
		
 | 
						|
		// live 12 02 40 01
 | 
						|
		
 | 
						|
		$hex = null;
 | 
						|
		if(
 | 
						|
			$date == "any" &&
 | 
						|
			$type == "video" &&
 | 
						|
			$duration == "any" &&
 | 
						|
			$feature == "any" &&
 | 
						|
			$sort == "relevance"
 | 
						|
		){
 | 
						|
			
 | 
						|
			return $hex;
 | 
						|
		}
 | 
						|
		
 | 
						|
		$opcode = 0;
 | 
						|
		
 | 
						|
		if($date != "any"){ $opcode += 2; }
 | 
						|
		if($type != "any"){ $opcode += 2; }
 | 
						|
		if($duration != "any"){ $opcode += 2; }
 | 
						|
		
 | 
						|
		switch($feature){
 | 
						|
			
 | 
						|
			case "live":
 | 
						|
			case "4k":
 | 
						|
			case "hd":
 | 
						|
			case "subtitles":
 | 
						|
			case "creativecommons":
 | 
						|
			case "360":
 | 
						|
			case "3d":
 | 
						|
				$opcode += 2;
 | 
						|
				break;
 | 
						|
			
 | 
						|
			case "hdr":
 | 
						|
			case "vr180":
 | 
						|
				$opcode += 3;
 | 
						|
				break;
 | 
						|
		}
 | 
						|
		
 | 
						|
		switch($sort){
 | 
						|
			
 | 
						|
			case "relevance": $hex .= "0800"; break;
 | 
						|
			case "upload_date": $hex .= "0802"; break;
 | 
						|
			case "view_count": $hex .= "0803"; break;
 | 
						|
			case "rating": $hex .= "0801"; break;
 | 
						|
		}
 | 
						|
		
 | 
						|
		$hex .= "12" . "0".$opcode;
 | 
						|
		
 | 
						|
		switch($date){
 | 
						|
			
 | 
						|
			case "hour": $hex .= "0801"; break;
 | 
						|
			case "today": $hex .= "0802"; break;
 | 
						|
			case "week": $hex .= "0803"; break;
 | 
						|
			case "month": $hex .= "0804"; break;
 | 
						|
			case "year": $hex .= "0805"; break;
 | 
						|
		}
 | 
						|
		
 | 
						|
		switch($type){
 | 
						|
			
 | 
						|
			case "video": $hex .= "1001"; break;
 | 
						|
			case "channel": $hex .= "1002"; break;
 | 
						|
			case "playlist": $hex .= "1003"; break;
 | 
						|
			case "movie": $hex .= "1004"; break;
 | 
						|
		}
 | 
						|
		
 | 
						|
		switch($duration){
 | 
						|
			
 | 
						|
			case "short": $hex .= "1801"; break;
 | 
						|
			case "medium": $hex .= "1803"; break;
 | 
						|
			case "long": $hex .= "1802"; break;
 | 
						|
		}
 | 
						|
		
 | 
						|
		switch($feature){
 | 
						|
			
 | 
						|
			case "live": $hex .= "4001"; break;
 | 
						|
			case "4k": $hex .= "7001"; break;
 | 
						|
			case "hd": $hex .= "2001"; break;
 | 
						|
			case "subtitles": $hex .= "2801"; break;
 | 
						|
			case "creativecommons": $hex .= "3001"; break;
 | 
						|
			case "360": $hex .= "7801"; break;
 | 
						|
			case "vr180": $hex .= "d00101"; break;
 | 
						|
			case "3d": $hex .= "3801"; break;
 | 
						|
			case "hdr": $hex .= "c80101"; break;
 | 
						|
		}
 | 
						|
		
 | 
						|
		//echo $hex . "\n\n";
 | 
						|
		return urlencode(base64_encode(hex2bin($hex)));
 | 
						|
	}
 | 
						|
	
 | 
						|
	// me reading youtube's json
 | 
						|
	// https://imgur.com/X9hVlFX
 | 
						|
	
 | 
						|
	const req_web = 0;
 | 
						|
	const req_xhr = 1;
 | 
						|
	
 | 
						|
	private function get($proxy, $url, $get = [], $reqtype = self::req_web, $continuation = null){
 | 
						|
		
 | 
						|
		$curlproc = curl_init();
 | 
						|
		
 | 
						|
		if($get !== []){
 | 
						|
			$get = http_build_query($get);
 | 
						|
			$url .= "?" . $get;
 | 
						|
		}
 | 
						|
		
 | 
						|
		curl_setopt($curlproc, CURLOPT_URL, $url);
 | 
						|
		
 | 
						|
		switch($reqtype){
 | 
						|
			case self::req_web:
 | 
						|
				$headers =
 | 
						|
					["User-Agent: " . config::USER_AGENT,
 | 
						|
					"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
 | 
						|
					"Accept-Language: en-US,en;q=0.5",
 | 
						|
					"Accept-Encoding: gzip",
 | 
						|
					"Cookie: PREF=tz=America.New_York",
 | 
						|
					"DNT: 1",
 | 
						|
					"Connection: keep-alive",
 | 
						|
					"Upgrade-Insecure-Requests: 1",
 | 
						|
					"Sec-Fetch-Dest: document",
 | 
						|
					"Sec-Fetch-Mode: navigate",
 | 
						|
					"Sec-Fetch-Site: none",
 | 
						|
					"Sec-Fetch-User: ?1"];
 | 
						|
				break;
 | 
						|
			
 | 
						|
			case self::req_xhr:
 | 
						|
				$headers =
 | 
						|
					["User-Agent: " . config::USER_AGENT,
 | 
						|
					"Accept: */*",
 | 
						|
					"Accept-Language: en-US,en;q=0.5",
 | 
						|
					"Accept-Encoding: gzip",
 | 
						|
					"Cookie: PREF=tz=America.New_York",
 | 
						|
					"Referer: https://youtube.com.com/",
 | 
						|
					"Content-Type: application/json",
 | 
						|
					"Content-Length: " . strlen($continuation),
 | 
						|
					"DNT: 1",
 | 
						|
					"Connection: keep-alive",
 | 
						|
					"Sec-Fetch-Dest: empty",
 | 
						|
					"Sec-Fetch-Mode: same-origin",
 | 
						|
					"Sec-Fetch-Site: same-origin"];
 | 
						|
				
 | 
						|
				curl_setopt($curlproc, CURLOPT_POST, true);
 | 
						|
				curl_setopt($curlproc, CURLOPT_POSTFIELDS, $continuation);
 | 
						|
				break;
 | 
						|
		}
 | 
						|
		
 | 
						|
		curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding
 | 
						|
		curl_setopt($curlproc, CURLOPT_HTTPHEADER, $headers);
 | 
						|
		
 | 
						|
		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);
 | 
						|
		return $data;
 | 
						|
	}
 | 
						|
	
 | 
						|
	public function video($get){
 | 
						|
		
 | 
						|
		$this->out = [
 | 
						|
			"status" => "ok",
 | 
						|
			"npt" => null,
 | 
						|
			"video" => [],
 | 
						|
			"author" => [],
 | 
						|
			"livestream" => [],
 | 
						|
			"playlist" => [],
 | 
						|
			"reel" => []
 | 
						|
		];
 | 
						|
		
 | 
						|
		if($get["npt"]){
 | 
						|
			
 | 
						|
			// parse nextPage
 | 
						|
			// https://www.youtube.com/youtubei/v1/search?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8&prettyPrint=false
 | 
						|
			/*
 | 
						|
			$handle = fopen("nextpage.json", "r");
 | 
						|
			$json = fread($handle, filesize("nextpage.json"));
 | 
						|
			fclose($handle);*/
 | 
						|
			
 | 
						|
			[$npt, $proxy] =
 | 
						|
				$this->backend->get(
 | 
						|
					$get["npt"],
 | 
						|
					"videos"
 | 
						|
				);
 | 
						|
			
 | 
						|
			$npt = json_decode($npt, true);
 | 
						|
			
 | 
						|
			try{
 | 
						|
				$json = $this->get(
 | 
						|
					$proxy,
 | 
						|
					"https://www.youtube.com/youtubei/v1/search",
 | 
						|
					[
 | 
						|
						"key" => $npt["key"],
 | 
						|
						"prettyPrint" => "false"
 | 
						|
					],
 | 
						|
					self::req_xhr,
 | 
						|
					json_encode($npt["post"])
 | 
						|
				);
 | 
						|
			}catch(Exception $error){
 | 
						|
				
 | 
						|
				throw new Exception("Could not fetch results page");
 | 
						|
			}
 | 
						|
			
 | 
						|
			$json = json_decode($json);
 | 
						|
			
 | 
						|
			foreach(
 | 
						|
				$json
 | 
						|
				->onResponseReceivedCommands[0]
 | 
						|
				->appendContinuationItemsAction
 | 
						|
				->continuationItems[0]
 | 
						|
				->itemSectionRenderer
 | 
						|
				->contents
 | 
						|
				as $video
 | 
						|
			){
 | 
						|
				
 | 
						|
				$this->parsevideoobject($video);
 | 
						|
			}
 | 
						|
			
 | 
						|
			if(
 | 
						|
				!isset(
 | 
						|
					$json
 | 
						|
					->onResponseReceivedCommands[0]
 | 
						|
					->appendContinuationItemsAction
 | 
						|
					->continuationItems[1]
 | 
						|
					->continuationItemRenderer
 | 
						|
					->continuationEndpoint
 | 
						|
					->continuationCommand
 | 
						|
					->token
 | 
						|
				)
 | 
						|
			){
 | 
						|
				
 | 
						|
				$npt = null;
 | 
						|
				
 | 
						|
			}else{
 | 
						|
				// prepare nextpage for later..
 | 
						|
				$npt["post"]["continuation"] =
 | 
						|
					$json
 | 
						|
					->onResponseReceivedCommands[0]
 | 
						|
					->appendContinuationItemsAction
 | 
						|
					->continuationItems[1]
 | 
						|
					->continuationItemRenderer
 | 
						|
					->continuationEndpoint
 | 
						|
					->continuationCommand
 | 
						|
					->token;
 | 
						|
			}
 | 
						|
			
 | 
						|
			$this->out["npt"] = $npt;
 | 
						|
			
 | 
						|
		}else{
 | 
						|
			
 | 
						|
			$search = $get["s"];
 | 
						|
			if(strlen($search) === 0){
 | 
						|
				
 | 
						|
				throw new Exception("Search term is empty!");
 | 
						|
			}
 | 
						|
			
 | 
						|
			$proxy = $this->backend->get_ip();
 | 
						|
			$date = $get["date"];
 | 
						|
			$type = $get["type"];
 | 
						|
			$duration = $get["duration"];
 | 
						|
			$feature = $get["feature"];
 | 
						|
			$sort = $get["sort"];
 | 
						|
			
 | 
						|
			// parse ytInitialData
 | 
						|
			
 | 
						|
			$get = [
 | 
						|
				"search_query" => $search
 | 
						|
			];
 | 
						|
			
 | 
						|
			if(
 | 
						|
				(
 | 
						|
					$filter =
 | 
						|
					$this->ytfilter(
 | 
						|
						$date,
 | 
						|
						$type,
 | 
						|
						$duration,
 | 
						|
						$feature,
 | 
						|
						$sort
 | 
						|
					)
 | 
						|
				) !== null
 | 
						|
			){
 | 
						|
				
 | 
						|
				$get["sp"] = $filter;
 | 
						|
			}
 | 
						|
			
 | 
						|
			try{
 | 
						|
				$json = $this->get(
 | 
						|
					$proxy,
 | 
						|
					"https://www.youtube.com/results",
 | 
						|
					$get
 | 
						|
				);
 | 
						|
			}catch(Exception $error){
 | 
						|
				
 | 
						|
				throw new Exception("Could not fetch results page");
 | 
						|
			}
 | 
						|
			/*
 | 
						|
			$handle = fopen("test.html", "r");
 | 
						|
			$json = fread($handle, filesize("test.html"));
 | 
						|
			fclose($handle);
 | 
						|
			*/
 | 
						|
			if(
 | 
						|
				!preg_match(
 | 
						|
					'/ytcfg\.set\(({".*})\); *window\.ytcfg/',
 | 
						|
					$json,
 | 
						|
					$ytconfig
 | 
						|
				)
 | 
						|
			){
 | 
						|
				
 | 
						|
				throw new Exception("Could not get ytcfg");
 | 
						|
			}
 | 
						|
			
 | 
						|
			$ytconfig = json_decode($ytconfig[1]);
 | 
						|
			
 | 
						|
			if(
 | 
						|
				!preg_match(
 | 
						|
					'/ytInitialData *= *({.*});<\/script>/',
 | 
						|
					$json,
 | 
						|
					$json
 | 
						|
				)
 | 
						|
			){
 | 
						|
				
 | 
						|
				throw new Exception("Could not get ytInitialData");
 | 
						|
			}
 | 
						|
			
 | 
						|
			$json = json_decode($json[1]);
 | 
						|
			
 | 
						|
			// generate POST data for nextpage
 | 
						|
			
 | 
						|
			$ytconfig->INNERTUBE_CONTEXT->client->screenWidthPoints = 1239;
 | 
						|
			$ytconfig->INNERTUBE_CONTEXT->client->screenHeightPoints = 999;
 | 
						|
			$ytconfig->INNERTUBE_CONTEXT->client->screenPixelDensity = 1;
 | 
						|
			$ytconfig->INNERTUBE_CONTEXT->client->screenDensityFloat = 1;
 | 
						|
			$ytconfig->INNERTUBE_CONTEXT->client->utcOffsetMinutes = -240;
 | 
						|
			$ytconfig->INNERTUBE_CONTEXT->request->internalExperimentFlags = [];
 | 
						|
			$ytconfig->INNERTUBE_CONTEXT->request->consistencyTokenJars = [];
 | 
						|
			
 | 
						|
			$ytconfig->INNERTUBE_CONTEXT->client->mainAppWebInfo = [
 | 
						|
				"graftUrl" => $ytconfig->INNERTUBE_CONTEXT->client->originalUrl,
 | 
						|
				"webDisplayMode" => "WEB_DISPLAY_MODE_BROWSER",
 | 
						|
				"isWebNativeShareAvailable" => false
 | 
						|
			];
 | 
						|
			
 | 
						|
			$ytconfig->INNERTUBE_CONTEXT->adSignalsInfo = [
 | 
						|
				"params" => [
 | 
						|
					[
 | 
						|
						"key" => "dt",
 | 
						|
						"value" => (string)$ytconfig->TIME_CREATED_MS
 | 
						|
					],
 | 
						|
					[
 | 
						|
						"key" => "flash",
 | 
						|
						"value" => "0"
 | 
						|
					],
 | 
						|
					[
 | 
						|
						"key" => "frm",
 | 
						|
						"value" => "0"
 | 
						|
					],
 | 
						|
					[
 | 
						|
						"key" => "u_tz",
 | 
						|
						"value" => "-240"
 | 
						|
					],
 | 
						|
					[
 | 
						|
						"key" => "u_his",
 | 
						|
						"value" => "3"
 | 
						|
					],
 | 
						|
					[
 | 
						|
						"key" => "u_h",
 | 
						|
						"value" => "1080"
 | 
						|
					],
 | 
						|
					[
 | 
						|
						"key" => "u_w",
 | 
						|
						"value" => "1920"
 | 
						|
					],
 | 
						|
					[
 | 
						|
						"key" => "u_ah",
 | 
						|
						"value" => "1080"
 | 
						|
					],
 | 
						|
					[
 | 
						|
						"key" => "u_cd",
 | 
						|
						"value" => "24"
 | 
						|
					],
 | 
						|
					[
 | 
						|
						"key" => "bc",
 | 
						|
						"value" => "31"
 | 
						|
					],
 | 
						|
					[
 | 
						|
						"key" => "bih",
 | 
						|
						"value" => "999"
 | 
						|
					],
 | 
						|
					[
 | 
						|
						"key" => "biw",
 | 
						|
						"value" => "1239"
 | 
						|
					],
 | 
						|
					[
 | 
						|
						"key" => "brdim",
 | 
						|
						"value" => "0,0,0,0,1920,0,1920,1061,1239,999"
 | 
						|
					],
 | 
						|
					[
 | 
						|
						"key" => "vis",
 | 
						|
						"value" => "1"
 | 
						|
					],
 | 
						|
					[
 | 
						|
						"key" => "wgl",
 | 
						|
						"value" => "true"
 | 
						|
					],
 | 
						|
					[
 | 
						|
						"key" => "ca_type",
 | 
						|
						"value" => "image"
 | 
						|
					]
 | 
						|
				]
 | 
						|
			];
 | 
						|
			
 | 
						|
			/*
 | 
						|
			echo json_encode($json);
 | 
						|
			die();*/
 | 
						|
			
 | 
						|
			// *inhales*
 | 
						|
			foreach(
 | 
						|
				$json
 | 
						|
				->contents
 | 
						|
				->twoColumnSearchResultsRenderer
 | 
						|
				->primaryContents
 | 
						|
				->sectionListRenderer
 | 
						|
				->contents[0]
 | 
						|
				->itemSectionRenderer
 | 
						|
				->contents
 | 
						|
				as $video
 | 
						|
			){
 | 
						|
				
 | 
						|
				$this->parsevideoobject($video);
 | 
						|
			}
 | 
						|
			
 | 
						|
			// get additional data from secondaryContents
 | 
						|
			if(
 | 
						|
				isset(
 | 
						|
					$json
 | 
						|
					->contents
 | 
						|
					->twoColumnSearchResultsRenderer
 | 
						|
					->secondaryContents
 | 
						|
					->secondarySearchContainerRenderer
 | 
						|
					->contents[0]
 | 
						|
					->universalWatchCardRenderer
 | 
						|
				)
 | 
						|
			){
 | 
						|
				
 | 
						|
				$video =
 | 
						|
					$json
 | 
						|
					->contents
 | 
						|
					->twoColumnSearchResultsRenderer
 | 
						|
					->secondaryContents
 | 
						|
					->secondarySearchContainerRenderer
 | 
						|
					->contents[0]
 | 
						|
					->universalWatchCardRenderer;
 | 
						|
				/*
 | 
						|
				echo json_encode($video);
 | 
						|
				die();*/
 | 
						|
				
 | 
						|
				$author =
 | 
						|
					[
 | 
						|
						"name" =>
 | 
						|
							$video
 | 
						|
							->header
 | 
						|
							->watchCardRichHeaderRenderer
 | 
						|
							->title
 | 
						|
							->simpleText,
 | 
						|
						"url" =>
 | 
						|
							"https://www.youtube.com/channel/" .
 | 
						|
							$video
 | 
						|
							->header
 | 
						|
							->watchCardRichHeaderRenderer
 | 
						|
							->titleNavigationEndpoint
 | 
						|
							->browseEndpoint
 | 
						|
							->browseId,
 | 
						|
						"avatar" => null
 | 
						|
					];
 | 
						|
				
 | 
						|
				if(
 | 
						|
					isset(
 | 
						|
						$video
 | 
						|
						->header
 | 
						|
						->watchCardRichHeaderRenderer
 | 
						|
						->avatar
 | 
						|
						->thumbnails[0]
 | 
						|
						->url
 | 
						|
					)
 | 
						|
				){
 | 
						|
					
 | 
						|
					$author["avatar"] =
 | 
						|
						$video
 | 
						|
						->header
 | 
						|
						->watchCardRichHeaderRenderer
 | 
						|
						->avatar
 | 
						|
						->thumbnails[0]
 | 
						|
						->url;
 | 
						|
				}
 | 
						|
				
 | 
						|
				// add video in callToAction if present
 | 
						|
				if(
 | 
						|
					isset(
 | 
						|
						$video
 | 
						|
						->callToAction
 | 
						|
						->watchCardHeroVideoRenderer
 | 
						|
						->lengthText
 | 
						|
					)
 | 
						|
				){
 | 
						|
					
 | 
						|
					array_push(
 | 
						|
						$this->out["video"],
 | 
						|
						[
 | 
						|
							"title" =>
 | 
						|
								$video
 | 
						|
								->callToAction
 | 
						|
								->watchCardHeroVideoRenderer
 | 
						|
								->title
 | 
						|
								->simpleText,
 | 
						|
							"description" => null,
 | 
						|
							"author" => $author,
 | 
						|
							"date" =>
 | 
						|
								$this->textualdate2unix(
 | 
						|
									trim(
 | 
						|
										explode(
 | 
						|
											"•",
 | 
						|
											$video
 | 
						|
											->callToAction
 | 
						|
											->watchCardHeroVideoRenderer
 | 
						|
											->subtitle
 | 
						|
											->simpleText
 | 
						|
										)[2]
 | 
						|
									)
 | 
						|
								),
 | 
						|
							"duration" =>
 | 
						|
								$this->hms2int(
 | 
						|
									$video
 | 
						|
									->callToAction
 | 
						|
									->watchCardHeroVideoRenderer
 | 
						|
									->lengthText
 | 
						|
									->simpleText
 | 
						|
								),
 | 
						|
							"views" =>
 | 
						|
								$this->truncatedcount2int(
 | 
						|
									trim(
 | 
						|
										explode(
 | 
						|
											"•",
 | 
						|
											$video
 | 
						|
											->callToAction
 | 
						|
											->watchCardHeroVideoRenderer
 | 
						|
											->subtitle
 | 
						|
											->simpleText,
 | 
						|
											2
 | 
						|
										)[1]
 | 
						|
									)
 | 
						|
								),
 | 
						|
							"thumb" => [
 | 
						|
								"url" =>
 | 
						|
									$video
 | 
						|
									->callToAction
 | 
						|
									->watchCardHeroVideoRenderer
 | 
						|
									->heroImage
 | 
						|
									->singleHeroImageRenderer
 | 
						|
									->thumbnail
 | 
						|
									->thumbnails[0]
 | 
						|
									->url,
 | 
						|
								"ratio" => "16:9"
 | 
						|
							],
 | 
						|
							"url" =>
 | 
						|
								"https://www.youtube.com/watch?v=" .
 | 
						|
								$video
 | 
						|
								->callToAction
 | 
						|
								->watchCardHeroVideoRenderer
 | 
						|
								->navigationEndpoint
 | 
						|
								->watchEndpoint
 | 
						|
								->videoId
 | 
						|
						]
 | 
						|
					);
 | 
						|
				}
 | 
						|
				
 | 
						|
				// get all playlists, ignore videos
 | 
						|
				$out = null;
 | 
						|
				
 | 
						|
				foreach(
 | 
						|
					$video
 | 
						|
					->sections
 | 
						|
					as $section
 | 
						|
				){
 | 
						|
					
 | 
						|
					if(
 | 
						|
						isset(
 | 
						|
							$section
 | 
						|
							->watchCardSectionSequenceRenderer
 | 
						|
							->lists[0]
 | 
						|
							->horizontalCardListRenderer
 | 
						|
							->cards
 | 
						|
						)
 | 
						|
					){
 | 
						|
						
 | 
						|
						$out =
 | 
						|
							$section
 | 
						|
							->watchCardSectionSequenceRenderer
 | 
						|
							->lists[0]
 | 
						|
							->horizontalCardListRenderer
 | 
						|
							->cards;
 | 
						|
						break;
 | 
						|
					}
 | 
						|
				}
 | 
						|
				
 | 
						|
				if($out !== null){
 | 
						|
					
 | 
						|
					foreach(
 | 
						|
						$out as $video
 | 
						|
					){
 | 
						|
						
 | 
						|
						if(
 | 
						|
							!isset(
 | 
						|
								$video
 | 
						|
								->searchRefinementCardRenderer
 | 
						|
							)
 | 
						|
						){
 | 
						|
							
 | 
						|
							continue;
 | 
						|
						}
 | 
						|
						
 | 
						|
						$video =
 | 
						|
							$video
 | 
						|
							->searchRefinementCardRenderer;
 | 
						|
						
 | 
						|
						array_push(
 | 
						|
							$this->out["playlist"],
 | 
						|
							[
 | 
						|
								"title" =>
 | 
						|
									$video
 | 
						|
									->query
 | 
						|
									->runs[0]
 | 
						|
									->text,
 | 
						|
								"description" => null,
 | 
						|
								"author" => $author,
 | 
						|
								"date" => null,
 | 
						|
								"duration" => null,
 | 
						|
								"views" => null,
 | 
						|
								"thumb" => [
 | 
						|
									"url" =>
 | 
						|
										$video
 | 
						|
										->thumbnail
 | 
						|
										->thumbnails[0]
 | 
						|
										->url,
 | 
						|
									"ratio" => "1:1"
 | 
						|
								],
 | 
						|
								"url" =>
 | 
						|
									"https://www.youtube.com" .
 | 
						|
									$video
 | 
						|
									->searchEndpoint
 | 
						|
									->commandMetadata
 | 
						|
									->webCommandMetadata
 | 
						|
									->url
 | 
						|
							]
 | 
						|
						);
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
			
 | 
						|
			foreach(
 | 
						|
				$json
 | 
						|
				->contents
 | 
						|
				->twoColumnSearchResultsRenderer
 | 
						|
				->primaryContents
 | 
						|
				->sectionListRenderer
 | 
						|
				->contents
 | 
						|
				as $cont
 | 
						|
			){
 | 
						|
				
 | 
						|
				if(isset($cont->continuationItemRenderer)){
 | 
						|
					
 | 
						|
					$this->out["npt"] = [
 | 
						|
						"key" =>
 | 
						|
							$ytconfig
 | 
						|
							->INNERTUBE_API_KEY,
 | 
						|
						"post" => [
 | 
						|
							"context" =>
 | 
						|
								$ytconfig
 | 
						|
								->INNERTUBE_CONTEXT,
 | 
						|
							"continuation" =>
 | 
						|
								$cont
 | 
						|
								->continuationItemRenderer
 | 
						|
								->continuationEndpoint
 | 
						|
								->continuationCommand
 | 
						|
								->token
 | 
						|
						]
 | 
						|
					];
 | 
						|
					break;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		
 | 
						|
		if($this->out["npt"] !== null){
 | 
						|
			
 | 
						|
			$this->out["npt"] =
 | 
						|
				$this->backend->store(
 | 
						|
					json_encode(
 | 
						|
						$this->out["npt"]
 | 
						|
					),
 | 
						|
					"videos",
 | 
						|
					$proxy
 | 
						|
				);
 | 
						|
		}
 | 
						|
		
 | 
						|
		return $this->out;
 | 
						|
	}
 | 
						|
	
 | 
						|
	private function parsevideoobject($video){
 | 
						|
		
 | 
						|
		if(isset($video->videoRenderer)){
 | 
						|
			
 | 
						|
			$video = $video->videoRenderer;
 | 
						|
			
 | 
						|
			$description = null;
 | 
						|
			
 | 
						|
			if(isset($video->detailedMetadataSnippets)){
 | 
						|
				foreach(
 | 
						|
					$video
 | 
						|
					->detailedMetadataSnippets[0]
 | 
						|
					->snippetText
 | 
						|
					->runs
 | 
						|
					as $description_part
 | 
						|
				){
 | 
						|
					
 | 
						|
					$description .= $description_part->text;
 | 
						|
				}
 | 
						|
			}
 | 
						|
			
 | 
						|
			if(
 | 
						|
				isset(
 | 
						|
					$video
 | 
						|
					->badges[0]
 | 
						|
					->metadataBadgeRenderer
 | 
						|
					->icon
 | 
						|
					->iconType
 | 
						|
				) &&
 | 
						|
				$video
 | 
						|
				->badges[0]
 | 
						|
				->metadataBadgeRenderer
 | 
						|
				->icon
 | 
						|
				->iconType
 | 
						|
				== "LIVE"
 | 
						|
			){
 | 
						|
				
 | 
						|
				$type = "livestream";
 | 
						|
				$date = null;
 | 
						|
				$duration = "_LIVE";
 | 
						|
				
 | 
						|
				if(isset($video->viewCountText->runs[0]->text)){
 | 
						|
					
 | 
						|
					$views =
 | 
						|
						$this->views2int(
 | 
						|
							$video
 | 
						|
							->viewCountText
 | 
						|
							->runs[0]
 | 
						|
							->text
 | 
						|
						);
 | 
						|
				}else{
 | 
						|
					
 | 
						|
					$views = null;
 | 
						|
				}
 | 
						|
			}else{
 | 
						|
				
 | 
						|
				$type = "video";
 | 
						|
				
 | 
						|
				if(isset($video->publishedTimeText->simpleText)){
 | 
						|
					
 | 
						|
					$date = $this->textualdate2unix(
 | 
						|
						$video
 | 
						|
						->publishedTimeText
 | 
						|
						->simpleText
 | 
						|
					);
 | 
						|
				}else{
 | 
						|
					
 | 
						|
					$date = null;
 | 
						|
				}
 | 
						|
				
 | 
						|
				if(isset($video->lengthText->simpleText)){
 | 
						|
					
 | 
						|
					$duration =
 | 
						|
						$this->hms2int(
 | 
						|
							$video
 | 
						|
							->lengthText
 | 
						|
							->simpleText
 | 
						|
						);
 | 
						|
				}else{
 | 
						|
					
 | 
						|
					$duration = null;
 | 
						|
				}
 | 
						|
				
 | 
						|
				if(isset($video->viewCountText->simpleText)){
 | 
						|
					
 | 
						|
					$views =
 | 
						|
						$this->views2int(
 | 
						|
							$video
 | 
						|
							->viewCountText
 | 
						|
							->simpleText
 | 
						|
						);
 | 
						|
				}else{
 | 
						|
					
 | 
						|
					$views = null;
 | 
						|
				}
 | 
						|
			}
 | 
						|
			
 | 
						|
			if(
 | 
						|
				$video
 | 
						|
				->navigationEndpoint
 | 
						|
				->commandMetadata
 | 
						|
				->webCommandMetadata
 | 
						|
				->webPageType
 | 
						|
				== "WEB_PAGE_TYPE_SHORTS"
 | 
						|
			){
 | 
						|
				
 | 
						|
				// haha you thought you could get me, youtube
 | 
						|
				// jokes on you i dont go outside
 | 
						|
				$type = "reel";
 | 
						|
			}
 | 
						|
			
 | 
						|
			array_push(
 | 
						|
				$this->out[$type],
 | 
						|
				[
 | 
						|
					"title" =>
 | 
						|
						$video
 | 
						|
						->title
 | 
						|
						->runs[0]
 | 
						|
						->text,
 | 
						|
					"description" =>
 | 
						|
						$this->titledots($description),
 | 
						|
					"author" => [
 | 
						|
							"name" =>
 | 
						|
								$video
 | 
						|
								->longBylineText
 | 
						|
								->runs[0]
 | 
						|
								->text,
 | 
						|
							"url" =>
 | 
						|
								"https://www.youtube.com/channel/" .
 | 
						|
								$video
 | 
						|
								->longBylineText
 | 
						|
								->runs[0]
 | 
						|
								->navigationEndpoint
 | 
						|
								->browseEndpoint
 | 
						|
								->browseId,
 | 
						|
							"avatar" =>
 | 
						|
								$this->checkhttpspresence(
 | 
						|
									$video
 | 
						|
									->channelThumbnailSupportedRenderers
 | 
						|
									->channelThumbnailWithLinkRenderer
 | 
						|
									->thumbnail
 | 
						|
									->thumbnails[0]
 | 
						|
									->url
 | 
						|
								)
 | 
						|
						],
 | 
						|
					"date" => $date,
 | 
						|
					"duration" => $duration,
 | 
						|
					"views" => $views,
 | 
						|
					"thumb" => [
 | 
						|
						"url" =>
 | 
						|
							$video
 | 
						|
							->thumbnail
 | 
						|
							->thumbnails[0]
 | 
						|
							->url,
 | 
						|
						"ratio" => "16:9"
 | 
						|
					],
 | 
						|
					"url" =>
 | 
						|
						"https://www.youtube.com/watch?v=" .
 | 
						|
						$video
 | 
						|
						->videoId
 | 
						|
				]
 | 
						|
			);
 | 
						|
		}elseif(isset($video->watchCardCompactVideoRenderer)){
 | 
						|
			
 | 
						|
			$video =
 | 
						|
				$video
 | 
						|
				->watchCardCompactVideoRenderer;
 | 
						|
			
 | 
						|
			array_push(
 | 
						|
				$this->out["video"],
 | 
						|
				[
 | 
						|
					"title" =>
 | 
						|
						$video
 | 
						|
						->title
 | 
						|
						->simpleText,
 | 
						|
					"description" => null,
 | 
						|
					"author" => [
 | 
						|
							"name" =>
 | 
						|
								$video
 | 
						|
								->byline
 | 
						|
								->runs[0]
 | 
						|
								->text,
 | 
						|
							"url" =>
 | 
						|
								"https://www.youtube.com/channel/" .
 | 
						|
								$video
 | 
						|
								->byline
 | 
						|
								->runs[0]
 | 
						|
								->navigationEndpoint
 | 
						|
								->browseEndpoint
 | 
						|
								->browseId,
 | 
						|
							"avatar" => null
 | 
						|
						],
 | 
						|
					"date" =>
 | 
						|
						$this->textualdate2unix(
 | 
						|
							trim(
 | 
						|
								explode(
 | 
						|
									"•",
 | 
						|
									$video
 | 
						|
									->subtitle
 | 
						|
									->simpleText,
 | 
						|
									2
 | 
						|
								)[1]
 | 
						|
							)
 | 
						|
						),
 | 
						|
					"duration" =>
 | 
						|
						$this->hms2int(
 | 
						|
							$video
 | 
						|
							->lengthText
 | 
						|
							->simpleText
 | 
						|
						),
 | 
						|
					"views" =>
 | 
						|
						$this->truncatedcount2int(
 | 
						|
							trim(
 | 
						|
								explode(
 | 
						|
									"•",
 | 
						|
									$video
 | 
						|
									->subtitle
 | 
						|
									->simpleText,
 | 
						|
									2
 | 
						|
								)[0]
 | 
						|
							)
 | 
						|
						),
 | 
						|
					"thumb" => [
 | 
						|
						"url" =>
 | 
						|
							$video
 | 
						|
							->thumbnail
 | 
						|
							->thumbnails[0]
 | 
						|
							->url,
 | 
						|
						"ratio" => "16:9"
 | 
						|
					],
 | 
						|
					"url" =>
 | 
						|
						"https://www.youtube.com/watch?v=" .
 | 
						|
						$video
 | 
						|
						->navigationEndpoint
 | 
						|
						->watchEndpoint
 | 
						|
						->videoId
 | 
						|
				]
 | 
						|
			);
 | 
						|
			
 | 
						|
		}elseif(isset($video->reelShelfRenderer)){
 | 
						|
			
 | 
						|
			foreach(
 | 
						|
				$video
 | 
						|
				->reelShelfRenderer
 | 
						|
				->items
 | 
						|
				as $reel
 | 
						|
			){
 | 
						|
				
 | 
						|
				$reel =
 | 
						|
					$reel
 | 
						|
					->reelItemRenderer;
 | 
						|
				
 | 
						|
				array_push(
 | 
						|
					$this->out["reel"],
 | 
						|
					[
 | 
						|
						"title" =>
 | 
						|
							$reel
 | 
						|
							->headline
 | 
						|
							->simpleText,
 | 
						|
						"description" => null,
 | 
						|
						"author" => [
 | 
						|
							"name" => null,
 | 
						|
							"url" => null,
 | 
						|
							"avatar" => null
 | 
						|
						],
 | 
						|
						"date" => null,
 | 
						|
						"duration" =>
 | 
						|
							$this->textualtime2int(
 | 
						|
								$reel
 | 
						|
								->accessibility
 | 
						|
								->accessibilityData
 | 
						|
								->label
 | 
						|
							),
 | 
						|
						"views" =>
 | 
						|
							$this->truncatedcount2int(
 | 
						|
								$reel
 | 
						|
								->viewCountText
 | 
						|
								->simpleText
 | 
						|
							),
 | 
						|
						"thumb" => [
 | 
						|
							"url" =>
 | 
						|
								$reel
 | 
						|
								->thumbnail
 | 
						|
								->thumbnails[0]
 | 
						|
								->url,
 | 
						|
							"ratio" => "9:16"
 | 
						|
						],
 | 
						|
						"url" =>
 | 
						|
							"https://www.youtube.com/watch?v=" .
 | 
						|
							$reel
 | 
						|
							->videoId
 | 
						|
					]
 | 
						|
				);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		
 | 
						|
		elseif(isset($video->channelRenderer)){
 | 
						|
			
 | 
						|
			$video = $video->channelRenderer;
 | 
						|
			
 | 
						|
			$description = null;
 | 
						|
			
 | 
						|
			if(isset($video->descriptionSnippet)){
 | 
						|
				
 | 
						|
				foreach(
 | 
						|
					$video
 | 
						|
					->descriptionSnippet
 | 
						|
					->runs
 | 
						|
					as $description_part
 | 
						|
				){
 | 
						|
					
 | 
						|
					$description .= $description_part->text;
 | 
						|
				}
 | 
						|
			}
 | 
						|
			
 | 
						|
			array_push(
 | 
						|
				$this->out["author"],
 | 
						|
				[
 | 
						|
					"title" =>
 | 
						|
						$video
 | 
						|
						->title
 | 
						|
						->simpleText,
 | 
						|
					"followers" =>
 | 
						|
						isset(
 | 
						|
							$video
 | 
						|
							->videoCountText
 | 
						|
							->simpleText
 | 
						|
						) ?
 | 
						|
						$this->truncatedcount2int(
 | 
						|
							$video
 | 
						|
							->videoCountText
 | 
						|
							->simpleText
 | 
						|
						) :
 | 
						|
						0,
 | 
						|
					"description" => $this->titledots($description),
 | 
						|
					"thumb" =>
 | 
						|
						[
 | 
						|
							"url" =>
 | 
						|
								$this->checkhttpspresence(
 | 
						|
									$video
 | 
						|
									->thumbnail
 | 
						|
									->thumbnails[
 | 
						|
										count(
 | 
						|
											$video
 | 
						|
											->thumbnail
 | 
						|
											->thumbnails
 | 
						|
										) - 1
 | 
						|
									]
 | 
						|
									->url
 | 
						|
								),
 | 
						|
							"ratio" => "1:1"
 | 
						|
						],
 | 
						|
					"url" =>
 | 
						|
						"https://www.youtube.com/channel/" .
 | 
						|
						$video
 | 
						|
						->channelId
 | 
						|
				]
 | 
						|
			);
 | 
						|
		}
 | 
						|
		
 | 
						|
		elseif(isset($video->shelfRenderer)){
 | 
						|
			
 | 
						|
			if(
 | 
						|
				!is_object(
 | 
						|
					$video
 | 
						|
					->shelfRenderer
 | 
						|
					->content
 | 
						|
					->verticalListRenderer
 | 
						|
				)
 | 
						|
			){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
			
 | 
						|
			foreach(
 | 
						|
				$video
 | 
						|
				->shelfRenderer
 | 
						|
				->content
 | 
						|
				->verticalListRenderer
 | 
						|
				->items
 | 
						|
				as $shelfvideo
 | 
						|
			){
 | 
						|
				
 | 
						|
				$this->parsevideoobject($shelfvideo);
 | 
						|
			}
 | 
						|
			
 | 
						|
		}elseif(isset($video->radioRenderer)){
 | 
						|
			
 | 
						|
			$video = $video->radioRenderer;
 | 
						|
			
 | 
						|
			$description =
 | 
						|
				$video
 | 
						|
				->videoCountText
 | 
						|
				->runs[0]
 | 
						|
				->text
 | 
						|
				. ".";
 | 
						|
			
 | 
						|
			$tmp = [];
 | 
						|
			foreach(
 | 
						|
				$video->videos
 | 
						|
				as $childvideo
 | 
						|
			){
 | 
						|
				
 | 
						|
				$tmp[] =
 | 
						|
					$childvideo
 | 
						|
					->childVideoRenderer
 | 
						|
					->title
 | 
						|
					->simpleText;
 | 
						|
			}
 | 
						|
			
 | 
						|
			if(count($tmp) !== 0){
 | 
						|
				
 | 
						|
				$description .=
 | 
						|
					" " . implode(", ", $tmp);
 | 
						|
			}
 | 
						|
			
 | 
						|
			array_push(
 | 
						|
				$this->out["playlist"],
 | 
						|
				[
 | 
						|
					"title" =>
 | 
						|
						$video
 | 
						|
						->title
 | 
						|
						->simpleText,
 | 
						|
					"description" => $description,
 | 
						|
					"author" => [
 | 
						|
						"name" =>
 | 
						|
							$video
 | 
						|
							->longBylineText
 | 
						|
							->simpleText,
 | 
						|
						"url" => null,
 | 
						|
						"avatar" => null
 | 
						|
					],
 | 
						|
					"date" => null,
 | 
						|
					"duration" => null,
 | 
						|
					"views" => null,
 | 
						|
					"thumb" => [
 | 
						|
						"url" =>
 | 
						|
							$video
 | 
						|
							->thumbnail
 | 
						|
							->thumbnails[
 | 
						|
								count(
 | 
						|
									$video
 | 
						|
									->thumbnail
 | 
						|
									->thumbnails
 | 
						|
								) - 1
 | 
						|
							]
 | 
						|
							->url,
 | 
						|
						"ratio" => "16:9"
 | 
						|
					],
 | 
						|
					"url" =>
 | 
						|
						"https://www.youtube.com/watch?v=" .
 | 
						|
						$video
 | 
						|
						->videos[0]
 | 
						|
						->childVideoRenderer
 | 
						|
						->videoId .
 | 
						|
						"&list=" .
 | 
						|
						$video
 | 
						|
						->playlistId .
 | 
						|
						"&start_radio=1"
 | 
						|
				]
 | 
						|
			);
 | 
						|
			
 | 
						|
		}elseif(isset($video->playlistRenderer)){
 | 
						|
			
 | 
						|
			$video = $video->playlistRenderer;
 | 
						|
			
 | 
						|
			$description = $video->videoCount . " videos.";
 | 
						|
			
 | 
						|
			$tmp = [];
 | 
						|
			foreach(
 | 
						|
				$video
 | 
						|
				->videos
 | 
						|
				as $childvideo
 | 
						|
			){
 | 
						|
				
 | 
						|
				$tmp[] =
 | 
						|
					$childvideo
 | 
						|
					->childVideoRenderer
 | 
						|
					->title
 | 
						|
					->simpleText;
 | 
						|
			}
 | 
						|
			
 | 
						|
			if(count($tmp) !== 0){
 | 
						|
				
 | 
						|
				$description .=
 | 
						|
					" " . implode(", ", $tmp);
 | 
						|
			}
 | 
						|
			
 | 
						|
			array_push(
 | 
						|
				$this->out["playlist"],
 | 
						|
				[
 | 
						|
					"title" =>
 | 
						|
						$video
 | 
						|
						->title
 | 
						|
						->simpleText,
 | 
						|
					"description" => $description,
 | 
						|
					"author" => [
 | 
						|
						"name" =>
 | 
						|
							$video
 | 
						|
							->longBylineText
 | 
						|
							->runs[0]
 | 
						|
							->text,
 | 
						|
						"url" =>
 | 
						|
							"https://www.youtube.com/channel/" .
 | 
						|
							$video
 | 
						|
							->longBylineText
 | 
						|
							->runs[0]
 | 
						|
							->navigationEndpoint
 | 
						|
							->browseEndpoint
 | 
						|
							->browseId,
 | 
						|
						"picture" => null
 | 
						|
					],
 | 
						|
					"date" => null,
 | 
						|
					"duration" => null,
 | 
						|
					"views" => null,
 | 
						|
					"thumb" =>
 | 
						|
						[
 | 
						|
							"url" =>
 | 
						|
								$video
 | 
						|
								->thumbnails[0]
 | 
						|
								->thumbnails[
 | 
						|
									count(
 | 
						|
										$video
 | 
						|
										->thumbnails[0]
 | 
						|
										->thumbnails
 | 
						|
									) - 1
 | 
						|
								]
 | 
						|
								->url,
 | 
						|
							"ratio" => "16:9"
 | 
						|
						],
 | 
						|
					"url" =>
 | 
						|
						"https://www.youtube.com/watch?v=" .
 | 
						|
						$video
 | 
						|
						->videos[0]
 | 
						|
						->childVideoRenderer
 | 
						|
						->videoId .
 | 
						|
						"&list=" .
 | 
						|
						$video
 | 
						|
						->playlistId .
 | 
						|
						"&start_radio=1"
 | 
						|
				]
 | 
						|
			);
 | 
						|
			
 | 
						|
		}/*else{
 | 
						|
			if(!isset($video->searchPyvRenderer)){
 | 
						|
			echo json_encode($video);
 | 
						|
			die();}
 | 
						|
		}*/
 | 
						|
	}
 | 
						|
	
 | 
						|
	private function textualdate2unix($number){
 | 
						|
		
 | 
						|
		$number =
 | 
						|
			explode(
 | 
						|
				" ",
 | 
						|
				str_replace(
 | 
						|
						[
 | 
						|
							" ago",
 | 
						|
							"seconds",
 | 
						|
							"minutes",
 | 
						|
							"hours",
 | 
						|
							"days",
 | 
						|
							"weeks",
 | 
						|
							"months",
 | 
						|
							"years"
 | 
						|
						],
 | 
						|
						[
 | 
						|
							"",
 | 
						|
							"second",
 | 
						|
							"minute",
 | 
						|
							"hour",
 | 
						|
							"day",
 | 
						|
							"week",
 | 
						|
							"month",
 | 
						|
							"year"
 | 
						|
						],
 | 
						|
						$number
 | 
						|
					),
 | 
						|
				2
 | 
						|
			);
 | 
						|
		
 | 
						|
		$time = 0;
 | 
						|
		switch($number[1]){
 | 
						|
			
 | 
						|
			case "second":
 | 
						|
				$time = (int)$number[0];
 | 
						|
				break;
 | 
						|
			
 | 
						|
			case "minute":
 | 
						|
				$time = (int)$number[0] * 60;
 | 
						|
				break;
 | 
						|
			
 | 
						|
			case "hour":
 | 
						|
				$time = (int)$number[0] * 3600;
 | 
						|
				break;
 | 
						|
				
 | 
						|
			case "day":
 | 
						|
				$time = (int)$number[0] * 86400;
 | 
						|
				break;
 | 
						|
				
 | 
						|
			case "week":
 | 
						|
				$time = (int)$number[0] * 604800;
 | 
						|
				break;
 | 
						|
				
 | 
						|
			case "month":
 | 
						|
				$time = (int)$number[0] * 2629746;
 | 
						|
				break;
 | 
						|
				
 | 
						|
			case "year":
 | 
						|
				$time = (int)$number[0] * 31556952;
 | 
						|
				break;
 | 
						|
		}
 | 
						|
		
 | 
						|
		return time() - $time;
 | 
						|
	}
 | 
						|
	
 | 
						|
	private function checkhttpspresence($link){
 | 
						|
		
 | 
						|
		if(substr($link, 0, 2) == "//"){
 | 
						|
			
 | 
						|
			return "https:" . $link;
 | 
						|
		}
 | 
						|
		
 | 
						|
		return $link;
 | 
						|
	}
 | 
						|
	
 | 
						|
	private function textualtime2int($number){
 | 
						|
		
 | 
						|
		$number = explode(" - ", $number);
 | 
						|
		
 | 
						|
		if(count($number) >= 2){
 | 
						|
			
 | 
						|
			$number = $number[count($number) - 2];
 | 
						|
		}else{
 | 
						|
			
 | 
						|
			$number = $number[0];
 | 
						|
		}
 | 
						|
		
 | 
						|
		$number =
 | 
						|
			str_replace(
 | 
						|
				[
 | 
						|
					" ",
 | 
						|
					"seconds",
 | 
						|
					"minutes",
 | 
						|
					"hours",
 | 
						|
				],
 | 
						|
				[
 | 
						|
					"",
 | 
						|
					"second",
 | 
						|
					"minute",
 | 
						|
					"hour"
 | 
						|
				],
 | 
						|
				$number
 | 
						|
			);
 | 
						|
		
 | 
						|
		preg_match_all(
 | 
						|
			'/([0-9]+)(second|minute|hour)/',
 | 
						|
			$number,
 | 
						|
			$number
 | 
						|
		);
 | 
						|
		
 | 
						|
		$time = 0;
 | 
						|
		
 | 
						|
		for($i=0; $i<count($number[0]); $i++){
 | 
						|
			
 | 
						|
			switch($number[2][$i]){
 | 
						|
				
 | 
						|
				case "second":
 | 
						|
					$time = $time + (int)$number[1][$i];
 | 
						|
					break;
 | 
						|
					
 | 
						|
				case "minute":
 | 
						|
					$time = $time + ((int)$number[1][$i] * 60);
 | 
						|
					break;
 | 
						|
					
 | 
						|
				case "hour":
 | 
						|
					$time = $time + ((int)$number[1][$i] * 3600);
 | 
						|
					break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		
 | 
						|
		return $time;
 | 
						|
	}
 | 
						|
	
 | 
						|
	private function views2int($views){
 | 
						|
		
 | 
						|
		return
 | 
						|
			(int)str_replace(
 | 
						|
				",", "",
 | 
						|
				explode(" ", $views, 2)[0]
 | 
						|
			);
 | 
						|
	}
 | 
						|
	
 | 
						|
	private function hms2int($time){
 | 
						|
		
 | 
						|
		$parts = explode(":", $time, 3);
 | 
						|
		$time = 0;
 | 
						|
		
 | 
						|
		if(count($parts) === 3){
 | 
						|
			
 | 
						|
			// hours
 | 
						|
			$time = $time + ((int)$parts[0] * 3600);
 | 
						|
			array_shift($parts);
 | 
						|
		}
 | 
						|
		
 | 
						|
		if(count($parts) === 2){
 | 
						|
			
 | 
						|
			// minutes
 | 
						|
			$time = $time + ((int)$parts[0] * 60);
 | 
						|
			array_shift($parts);
 | 
						|
		}
 | 
						|
		
 | 
						|
		// seconds
 | 
						|
		$time = $time + (int)$parts[0];
 | 
						|
		
 | 
						|
		return $time;
 | 
						|
	}
 | 
						|
	
 | 
						|
	private function truncatedcount2int($number){
 | 
						|
		
 | 
						|
		// decimal should always be 1 number long
 | 
						|
		$number = explode(" ", $number, 2);
 | 
						|
		$number = $number[0];
 | 
						|
		
 | 
						|
		$unit = strtolower($number[strlen($number) - 1]);
 | 
						|
		
 | 
						|
		$tmp = explode(".", $number, 2);
 | 
						|
		$number = (int)$number;
 | 
						|
		
 | 
						|
		if(count($tmp) === 2){
 | 
						|
			
 | 
						|
			$decimal = (int)$tmp[1];
 | 
						|
		}else{
 | 
						|
			
 | 
						|
			$decimal = 0;
 | 
						|
		}
 | 
						|
		
 | 
						|
		switch($unit){
 | 
						|
			
 | 
						|
			case "k":
 | 
						|
				$exponant = 1000;
 | 
						|
				break;
 | 
						|
			
 | 
						|
			case "m":
 | 
						|
				$exponant = 1000000;
 | 
						|
				break;
 | 
						|
			
 | 
						|
			case "b";
 | 
						|
				$exponant = 1000000000;
 | 
						|
				break;
 | 
						|
			
 | 
						|
			default:
 | 
						|
				$exponant = 1;
 | 
						|
				break;
 | 
						|
		}
 | 
						|
		
 | 
						|
		return ($number * $exponant) + ($decimal * ($exponant / 10));
 | 
						|
	}
 | 
						|
	
 | 
						|
	private function titledots($title){
 | 
						|
		
 | 
						|
		$substr = substr($title, -3);
 | 
						|
		
 | 
						|
		if(
 | 
						|
			$substr == "..." ||
 | 
						|
			$substr == "…"
 | 
						|
		){
 | 
						|
			
 | 
						|
			return trim(substr($title, 0, -3), " \n\r\t\v\x00\0\x0B\xc2\xa0");
 | 
						|
		}
 | 
						|
		
 | 
						|
		return trim($title, " \n\r\t\v\x00\0\x0B\xc2\xa0");
 | 
						|
	}
 | 
						|
}
 |