<?php

$id = $video_id;

// Delete sig file if is old 60 sec
if (is_file(TOOLS_PATH.'sig.php')) {
    $filelastmodified = filemtime(TOOLS_PATH.'sig.php');
    if((time() - $filelastmodified) > 60) {
        unlink(TOOLS_PATH.'sig.php');
    }
}

function getc($url) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    $data = curl_exec($ch);
    curl_close($ch);

    return $data;
}

function cut_yt($ganti) {
    $arayganti = array('Youtube','youtube','YouTube');
    $ganti = str_replace($arayganti,'',$ganti);
    return $ganti;
}

function exformat($itag) {
    switch ($itag) {
        case "5":
            return "flv, video, 240p, audio";
            break;
        case "6":
            return "flv, video, 270p, audio";
            break;
        case "13":
            return "3gp, video, audio";
            break;
        case "17":
            return "3gp, video, 144p, audio";
            break;
        case "18":
            return "mp4, video, 360p, audio";
            break;
        case "22":
            return "mp4, video, 720p, audio";
            break;
        case "34":
            return "flv, video, 360p, audio";
            break;
        case "35":
            return "flv, video, 480p, audio";
            break;
        case "36":
            return "3gp, video, audio";
            break;
        case "37":
            return "mp4, video, 1080p, audio";
            break;
        case "38":
            return "mp4, video, 3072p, audio";
            break;
        case "43":
            return "webm, video, 360p, audio";
            break;
        case "44":
            return "webm, video, 480p, audio";
            break;
        case "45":
            return "webm, video, 720p, audio";
            break;
        case "46":
            return "webm, video, 1080p, audio";
            break;
        case "59":
            return "mp4, video, 480p, audio";
            break;
        case "78":
            return "mp4, video, 480p, audio";
            break;
        case "82":
            return "mp4, video, 360p, audio";
            break;
        case "83":
            return "mp4, video, 480p, audio";
            break;
        case "84":
            return "mp4, video, 720p, audio";
            break;
        case "85":
            return "mp4, video, 1080p, audio";
            break;
        case "100":
            return "webm, video, 360p, audio";
            break;
        case "101":
            return "webm, video, 480p, audio";
            break;
        case "102":
            return "webm, video, 720p, audio";
            break;
        case "91":
            return "mp4, video, 144p, audio";
            break;
        case "92":
            return "mp4, video, 240p, audio";
            break;
        case "93":
            return "mp4, video, 360p, audio";
            break;
        case "94":
            return "mp4, video, 480p, audio";
            break;
        case "95":
            return "mp4, video, 720p, audio";
            break;
        case "96":
            return "mp4, video, 1080p, audio";
            break;
        case "132":
            return "mp4, video, 240p, audio";
            break;
        case "151":
            return "mp4, video, 72p, audio";
            break;
        case "133":
            return "mp4, video, 240p";
            break;
        case "134":
            return "mp4, video, 360p";
            break;
        case "135":
            return "mp4, video, 480p";
            break;
        case "136":
            return "mp4, video, 720p";
            break;
        case "137":
            return "mp4, video, 1080p";
            break;
        case "138":
            return "mp4, video";
            break;
        case "160":
            return "mp4, video, 144p";
            break;
        case "212":
            return "mp4, video, 480p";
            break;
        case "264":
            return "mp4, video, 1440p";
            break;
        case "298":
            return "mp4, video, 720p";
            break;
        case "299":
            return "mp4, video, 1080p";
            break;
        case "266":
            return "mp4, video, 2160p";
            break;
        case "139":
            return "m4a, audio";
            break;
        case "140":
            return "m4a, audio";
            break;
        case "141":
            return "m4a, audio";
            break;
        case "256":
            return "m4a, audio";
            break;
        case "258":
            return "m4a, audio";
            break;
        case "325":
            return "m4a, audio";
            break;
        case "328":
            return "m4a, audio";
            break;
        case "167":
            return "webm, video, 360p";
            break;
        case "168":
            return "webm, video, 480p";
            break;
        case "169":
            return "webm, video, 720p";
            break;
        case "170":
            return "webm, video, 1080p";
            break;
        case "218":
            return "webm, video, 480p";
            break;
        case "219":
            return "webm, video, 480p";
            break;
        case "278":
            return "webm, video, 144p";
            break;
        case "242":
            return "webm, video, 240p";
            break;
        case "243":
            return "webm, video, 360p";
            break;
        case "244":
            return "webm, video, 480p";
            break;
        case "245":
            return "webm, video, 480p";
            break;
        case "246":
            return "webm, video, 480p";
            break;
        case "247":
            return "webm, video, 720p";
            break;
        case "248":
            return "webm, video, 1080p";
            break;
        case "271":
            return "webm, video, 1440p";
            break;
        case "272":
            return "webm, video, 2160p";
            break;
        case "302":
            return "webm, video, 720p";
            break;
        case "303":
            return "webm, video, 1080p";
            break;
        case "308":
            return "webm, video, 1440p";
            break;
        case "313":
            return "webm, video, 2160p";
            break;
        case "315":
            return "webm, video, 2160p";
            break;
        case "171":
            return "webm, audio";
            break;
        case "249":
            return "webm, audio";
            break;
        case "250":
            return "webm, audio";
            break;
        case "251":
            return "webm, audio";
            break;
        case "394":
            return "video";
            break;
        case "395":
            return "video";
            break;
        case "396":
            return "video";
            break;
        case "397":
            return "video";
            break;
        case "398":
            return "av01, video, 720p";
            break;
        case "399":
            return "av01, video, 1080p";
            break;
        default:
            return $itag;
            break;
    }
}

$a = getc("https://www.youtube.com/embed/".$id);

$ccc=explode('s/player/', $a);
$ddd=explode('/www-player.css', $ccc[1]);

$gsts = file_get_contents('https://www.youtube.com/s/player/'.$ddd[0].'/player_ias.vflset/en_US/base.js');

function getchiper($decipherScript) {
    $decipherPatterns = explode('.split("")', $decipherScript);
    unset($decipherPatterns[0]);
    foreach ($decipherPatterns as $value) {
        $value = explode('.join("")', explode('}', $value)[0]);
        if (count($value) === 2) {
            $value = explode(';', $value[0]);
            array_pop($value);
            unset($value[0]);
            $decipherPatterns = implode(';', $value);
            break;
        }
    }
    preg_match_all('/(?<=;).*?(?=\[|\.)/', $decipherPatterns, $deciphers);
    if ($deciphers && count($deciphers[0]) >= 2) {
        $deciphers = $deciphers[0][0];
        $deciphersObjectVar = $decipherPatterns ;
        $decipher = explode($deciphers . '={', $decipherScript)[1];
        $decipher = str_replace(["\n", "\r"], '', $decipher);
        $decipher = explode('}};', $decipher)[0];
        $decipher = explode('},', $decipher);
        // Convert deciphers to object
        $deciphers = [];

        foreach ($decipher as &$function) {
            $deciphers[explode(':function', $function)[0]] = explode('){', $function)[1];
        }
        // Convert pattern to array
        $decipherPatterns = str_replace($deciphersObjectVar . '.', '', $decipherPatterns);
        $decipherPatterns = str_replace($deciphersObjectVar . '[', '', $decipherPatterns);
        $decipherPatterns = str_replace(['](a,', '(a,'], '->(', $decipherPatterns);
        $decipherPatterns = explode(';', $decipherPatterns);
        $patterns =$decipherPatterns;
        $deciphers =$deciphers;

        if (!file_exists(TOOLS_PATH.'sig.php')) {

            for ($i=0; $i < count($patterns); $i++) {
                $executes = explode('->', $patterns[$i]);
                $execute=explode('.', $executes[0]);
                $number = intval(str_replace(['(', ')'], '', $executes[1]));
                $execute = $deciphers[$execute[1]];
                switch ($execute) {
                    case 'a.reverse()':
                        $processSignature = '$reverse';
                        break;
                    case 'var c=a[0];a[0]=a[b%a.length];a[b]=c':
                        $processSignature= '$length';
                        break;
                    case 'var c=a[0];a[0]=a[b%a.length];a[b%a.length]=c':
                        $processSignature= '$lengtha';
                        break;
                    case 'a.splice(0,b)':
                        $processSignature= '$splice';
                        break;
                    default:
                        die("\n==== Decipher dictionary was not found ====");
                        break;
                }
                $myfile = fopen(TOOLS_PATH.'sig.php', "a+") or die("Unable to open file!");
                if ($i==0) {
                    fwrite($myfile, '<?php $a = str_split($s);');
                }
                fwrite($myfile, $processSignature.'($a,'.$number.');');
                fclose($myfile);
            }

        }
    }
}

function sig($s){
    $reverse=function(&$a){
        $a = array_reverse($a);
    };
    $splice=function(&$a, $b){
        $a = array_slice($a, $b);
    };
    $length = function(&$a, $b){
        $c = $a[0];
        $a[0] = $a[$b % count($a)];
        $a[$b] = $c;
    };
    $lengtha = function(&$a, $b){
        $c = $a[0];
        $a[0] = $a[$b%count($a)];
        $a[$b%count($a)] = $c;
    };

    include(TOOLS_PATH.'sig.php');
    return join('', $a);
}


getchiper($gsts);
$data = getc("https://www.youtube.com/get_video_info?video_id=".$id."&asv=3&el=detailpage&hl=en_US");
parse_str($data,$info);
$streams = $info['player_response'];
$jsn_str = str_replace("\u0026","&", $streams);
$streamin_data_json = json_decode($jsn_str, true);

// Microdata
$vidtitle = $streamin_data_json["videoDetails"]["title"];
$vidId  = $streamin_data_json["videoDetails"]["videoId"];

if (isset( $streamin_data_json["videoDetails"]["shortDescription"] )) {
    $viddes = $streamin_data_json["videoDetails"]["shortDescription"];
} else {
    $viddes = null;
}

$vidpub = $streamin_data_json["microformat"]["playerMicroformatRenderer"]["publishDate"];
$vidviewCount = $streamin_data_json["videoDetails"]["viewCount"];
$vidauthor = $streamin_data_json["videoDetails"]["author"];
$vidauthorid = $streamin_data_json["videoDetails"]["channelId"];
$vidauthourl = "channel/{$vidauthorid}";
$vidtime = $streamin_data_json["videoDetails"]["lengthSeconds"];
$vidisLiveContent = $streamin_data_json["videoDetails"]["isLiveContent"];

// thumbs
$vidthumb = array();
foreach ($streamin_data_json["videoDetails"]["thumbnail"]["thumbnails"] as $data) {
    $url = $data['url'];
    $values = array(
        'url' => $url,
        'width' => $data['width'],
        'height' => $data['height']
    );
    array_push($vidthumb, $values);
}

// keywords
$vidkeywords = array();
if ( isset($streamin_data_json["videoDetails"]["keywords"]) ) {
    foreach ($streamin_data_json["videoDetails"]["keywords"] as $data) {
        array_push($vidkeywords, $data);
    }
}

// streams
if (isset($streamin_data_json["streamingData"])) {

    if (isset($streamin_data_json["streamingData"]["formats"])) {
        $strF=$streamin_data_json["streamingData"]["formats"];
    }

    if (isset($streamin_data_json["streamingData"]["adaptiveFormats"])) {
        $strA=$streamin_data_json["streamingData"]["adaptiveFormats"];
    }

    $vdef = array();
    if (isset($strF)) {
        foreach ($strF as $stream) {
            if (isset($stream["signatureCipher"])) {
                parse_str($stream["signatureCipher"],$dturl);
                $values = array(
                    'url' => $dturl['url'].'&sig='.sig($dturl['s']),
                    'itag' => $stream['itag'],
                    'type' => $stream['mimeType'],
                    'quality' => $stream['quality'],
                    'fps' => $stream['fps'],
                    'resolution' => $stream['qualityLabel'],
                    'qualityLabel' => $stream['qualityLabel'],
                    'format' => exformat($stream['itag'])
                );
                array_push($vdef, $values);
            } else {
                if (!empty($strF['url'])) {
                    $values = array(
                        'url' => $strF['url'],
                    );
                    array_push($vdef, $values);
                }
            }
        }
    }


    $aud = array();
    $vid = array();
    if (isset($strF)) {
        foreach ($strF as $stream) {
            if (isset( $stream['url'] )) {
                if (preg_match('/video/', $stream['mimeType'])) {
                    $url = $stream['url'];
                    $values = array(
                        'url' => $url,
                        'itag' => $stream['itag'],
                        'type' => $stream['mimeType'],
                        'quality' => $stream['quality'],
                        'fps' => $stream['fps'],
                        'resolution' => $stream['qualityLabel'],
                        'qualityLabel' => $stream['qualityLabel'],
                        'format' => exformat($stream['itag']),
                    );
                    array_push($vid, $values);
                }
            }
        }
    }

    if (isset($strA)) {
        foreach ($strA as $stream) {
            if (isset($stream["signatureCipher"])) {
                parse_str($stream["signatureCipher"],$dturl);
                $stream['url']=$dturl['url'].'&sig='.sig($dturl['s']);
            }

            if (preg_match('/audio/', $stream['mimeType'])) {
                $url = $stream['url'];
                $values = array(
                    'url' => $url,
                    'itag' => $stream['itag'],
                    'type' => $stream['mimeType'],
                    'quality' => $stream['quality'],
                    'format' => exformat($stream['itag']),
                );
                array_push($aud, $values);
            }

            if (preg_match('/video/', $stream['mimeType'])) {
                $url = $stream['url'];
                $values = array(
                    'url' => $url,
                    'itag' => $stream['itag'],
                    'type' => $stream['mimeType'],
                    'quality' => $stream['quality'],
                    'fps' => $stream['fps'],
                    'resolution' => $stream['qualityLabel'],
                    'qualityLabel' => $stream['qualityLabel'],
                    'format' => exformat($stream['itag']),
                );
                array_push($vid, $values);
            }
        }
    }

} else {
    $vdef = array();
    $aud = array();
    $vid = array();
}

// $json['title']=$vidtitle;
// $json['videoId']=$vidId;
// $json['videoThumbnails']=$vidthumb;
// $json['description']=$viddes;
// $json['publishedText']=$vidpub;
// $json['viewCount']=$vidviewCount;
// $json['keywords']=$vidkeywords;
// $json['author']=$vidauthor;
// $json['authorId']=$vidauthorid;
// $json['authorUrl']=$vidauthourl;
// $json['lengthSeconds']=$vidtime;
// $json['liveNow']=$vidisLiveContent;
// $json['default']=$vdef;
// $json['audio']=$aud;
// $json['video']=$vid;
