123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734 |
- <?php
- //$yt = new youtube();
- //header("Content-Type: application/json");
- //echo json_encode($yt->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<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");
- }
- }
|