video("minecraft", null, "today", "any", "any", "live", "relevance")); class yt{ 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