Вход Регистрация
Файл: you/_system/class/YoutubeDownloader.php
Строк: 276
<?
###################################################
#     BY MAKSAMKA (Mr.MAX) ICQ 154-26-36          #
#       Поиск видео > API v3 Youtube              #
#      Версия сборки V.2.0                        #
###################################################


class YoutubeDownloader
{
    protected 
$url;
    protected 
$fullInfo;

    public function 
__construct($url)
    {
        
$this->url = $url;
    }

    public function 
getFullInfo()
    {
        if (
is_null($this->fullInfo)) {
            
preg_match("/^.*((youtu.be/)|(v/)|(/u/w/)|(embed/)|(watch?))??v?=?([^#&?]*).*/i", $this->url, $matches);
            
$videoId = $matches[7];
            
$clearContent = file_get_contents("https://www.youtube.com/watch?v=$videoId");
            
preg_match('/ytplayer.config = ({.+});ytplayer/', $clearContent, $mathes);
            
$configData = json_decode($mathes[1], true);
            
$streamList = explode(',', $configData['args']['url_encoded_fmt_stream_map']);
            
$configData['args']['url_encoded_fmt_stream_map'] = array();
            foreach (
$streamList AS $stream) {
                
parse_str($stream, $res);
                
$configData['args']['url_encoded_fmt_stream_map'][] = $res;
            }
            
$streamList = explode(',', $configData['args']['adaptive_fmts']);
            
$configData['args']['adaptive_fmts'] = array();
            foreach (
$streamList AS $stream) {
                
parse_str($stream, $res);
                
$configData['args']['adaptive_fmts'][] = $res;
            }

            
$this->fullInfo = $configData['args'];
            
$this->fullInfo['html'] = $clearContent;
            
$this->fullInfo['video_id'] = $videoId;
            
$jsPath = $configData['assets']['js'];
            
$jsPlayerClear = file_get_contents('https://www.youtube.com' . $jsPath);
            
preg_match('/set("signature",s*(?:([^(]*).*))/', $jsPlayerClear, $mathes);
            
$signParserFnName = $mathes[1];
            
preg_match("/$signParserFnName=(function(.+;)/", $jsPlayerClear, $mathes);
            
$signFnBody = $mathes[1];
            
preg_match("/(w+).w+([wd,]+)/", $signFnBody, $mathes);
            
$helperObjName = $mathes[1];
            
preg_match_all("/$helperObjName.(w+)(w+,(d+));/", $signFnBody, $matches);
            
$startPos = strpos($jsPlayerClear, "$helperObjName={");
            
$calcRule = array();
            foreach (
$matches[1] AS $i => $fnName) {
                
$calcRule[] = array(
                    
'function' => $fnName,
                    
'param' => $matches[2][$i],
                );
            }
            
$endPos = $startPos + strlen($helperObjName) + 2;
            
$startPos += strlen($helperObjName) + 1;
            
$countOpenBraces = 1;
            while (
$countOpenBraces > 0) {
                
$char = substr($jsPlayerClear, $endPos, 1);
                
$endPos++;
                if (
$char == '{') {
                    
$countOpenBraces++;
                } elseif (
$char == '}') {
                    
$countOpenBraces--;
                }
            }
            
$helperObjBody = substr($jsPlayerClear, $startPos, $endPos - $startPos);
            
preg_match_all('/(w+):function([w,]+){([^}]+)}/', $helperObjBody, $matches);
            
$calcFunctions = array();
            foreach (
$matches[1] AS $i => $fnName) {
                
$fnBody = $matches[2][$i];
                if (
strpos($fnBody, 'reverse') !== false) {
                    
$calcFunctions[$fnName] = 'reverse';
                    continue;
                }
                if (
strpos($fnBody, 'splice') !== false) {
                    
$calcFunctions[$fnName] = 'splice';
                    continue;
                }
                
$calcFunctions[$fnName] = 'swap';
            }
            foreach (
$calcRule AS &$calcItem) {
                
$calcItem['function'] = $calcFunctions[$calcItem['function']];
            }
            
$this->fullInfo['calcSignatureSteps'] = $calcRule;
            
$calcSignExpression = <<<JS
    function calculateSignature(sign){
        var __HELPER_OBJ_NAME = __HELPER_OBJ_BODY__;
        var calcSign = __SIGN_FN_BODY__;
        return calcSign(sign);
    }
JS;
            
$calcSignExpression = str_replace('__HELPER_OBJ_NAME', $helperObjName, $calcSignExpression);
            
$calcSignExpression = str_replace('__HELPER_OBJ_BODY__', $helperObjBody, $calcSignExpression);
            
$calcSignExpression = str_replace('__SIGN_FN_BODY__', $signFnBody, $calcSignExpression);

            
$this->fullInfo['jsSignatureGen'] = $calcSignExpression;

        }
        return 
$this->fullInfo;
    }

    public function 
getBaseInfo()
    {
        
$fullInfo = $this->getFullInfo();
        
$baseInfo = array();
        
$baseInfo['name'] = $fullInfo['title'];
        
$videoId = $fullInfo['video_id'];
        
$baseInfo['previewUrl'] = "https://img.youtube.com/vi/$videoId/hqdefault.jpg";
        
$html = $fullInfo['html'];
        if (
preg_match('/<p id="eow-description"[^>]+>(.+)</p>/', $html, $matches)) {
            
$baseInfo['description'] = strip_tags(str_replace('<br />', "n", $matches[1]));
        }
        return 
$baseInfo;
    }

    public static function 
getItagInfo()
    {
        return array(
            
5 => array('format' => 'flv', 'withVideo' => true, 'withAudio' => true),
            
6 => array('format' => 'flv', 'withVideo' => true, 'withAudio' => true),
            
13 => array('format' => '3gp', 'withVideo' => true, 'withAudio' => true),
            
17 => array('format' => '3gp', 'withVideo' => true, 'withAudio' => true),
            
18 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => true),
            
22 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => true),
            
34 => array('format' => 'flv', 'withVideo' => true, 'withAudio' => true),
            
35 => array('format' => 'flv', 'withVideo' => true, 'withAudio' => true),
            
36 => array('format' => '3gp', 'withVideo' => true, 'withAudio' => true),
            
37 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => true),
            
38 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => true),
            
43 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => true),
            
44 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => true),
            
45 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => true),
            
46 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => true),
            
82 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => true),
            
83 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => true),
            
84 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => true),
            
85 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => true),
            
100 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => true),
            
101 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => true),
            
102 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => true),
            
92 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => true),
            
93 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => true),
            
94 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => true),
            
95 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => true),
            
96 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => true),
            
132 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => true),
            
151 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => true),
            
133 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => false),
            
134 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => false),
            
135 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => false),
            
136 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => false),
            
137 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => false),
            
138 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => false),
            
160 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => false),
            
264 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => false),
            
298 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => false),
            
299 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => false),
            
266 => array('format' => 'mp4', 'withVideo' => true, 'withAudio' => false),
            
139 => array('format' => 'm4a', 'withVideo' => false, 'withAudio' => true),
            
140 => array('format' => 'm4a', 'withVideo' => false, 'withAudio' => true),
            
141 => array('format' => 'm4a', 'withVideo' => false, 'withAudio' => true),
            
167 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
168 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
169 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
170 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
218 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
219 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
242 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
243 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
244 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
245 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
246 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
247 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
248 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
271 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
272 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
302 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
303 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
308 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
313 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
315 => array('format' => 'webm', 'withVideo' => true, 'withAudio' => false),
            
171 => array('format' => 'webm', 'withVideo' => false, 'withAudio' => true),
            
172 => array('format' => 'webm', 'withVideo' => false, 'withAudio' => true),
        );
    }

    static protected function 
calcSignature($signatureEncoded, $steps)
    {
        
$sign = str_split($signatureEncoded);
        foreach (
$steps AS $step) {
            
$fn = $step['function'];
            
$param = (int)$step['param'];

            switch (
$fn) {
                case 
'reverse':
                    
$sign = array_reverse($sign);
                    break;
                case 
'splice':
                    
$sign = array_slice($sign, $param);
                    break;
                case 
'swap':
                    
$c = $sign[0];
                    
$sign[0] = $sign[$param % count($sign)];
                    
$sign[$param] = $c;
                    break;
            }
        }
        return 
implode('', $sign);
    }

    public static function 
getResponseHeaders($url)
    {
        
$clearHeaders = get_headers($url);
        
$headers = array();
        foreach (
$clearHeaders AS $header) {
            
$header = explode(':', $header);
            if (
count($header) === 2) {
                
$headers[$header[0]] = trim($header[1]);
            }
        }
        return 
$headers;
    }


    public function 
getDownloadInfoOne($fmtsItem)
    {
        
$fullInfo = $this->getFullInfo();
        
$title = $fullInfo['title'];
        
$url = $fmtsItem['url'] . '&title=' . $_SERVER['HTTP_HOST'] .'_' . urlencode($title);
        
$signature = false;
        if (isset(
$fmtsItem['signature'])) {
            
$signature = $fmtsItem['signature'];
        }

        if (isset(
$fmtsItem['sig'])) {
            
$signature = self::calcSignature($fmtsItem['sig'], $fullInfo['calcSignatureSteps']);
        }

        if (isset(
$fmtsItem['s'])) {
            
$signature = self::calcSignature($fmtsItem['s'], $fullInfo['calcSignatureSteps']);
        }

        if (
$signature) {
            
$url .= '&signature=' . $signature;
        }

        
$headers = self::getResponseHeaders($url);
        
$downloadInfo = array();
          
$downloadInfo['url'] = $url;
        
$downloadInfo['youtubeItag'] = $fmtsItem['itag'];
        
$downloadInfo['fileType'] = explode(';', $fmtsItem['type']);
        
$downloadInfo['fileType'] = $downloadInfo['fileType'][0];
        
$ext = explode('/', $downloadInfo['fileType']);
        
$ext = $ext[1];
        
$downloadInfo['name'] = $title . '.' . $ext;
        
$downloadInfo['itagInfo'] = self::getItagInfo();
        if (isset(
$downloadInfo['itagInfo'][$fmtsItem['itag']])) {
            
$downloadInfo['itagInfo'] = $downloadInfo['itagInfo'][$fmtsItem['itag']];
        } else {
            
$downloadInfo['itagInfo'] = null;
        }
        
$downloadInfo[] = $downloadInfo;
        return 
$downloadInfo;
    }

    
/**
     * Return array of download information for video
     *
     * @return VideoDownloadInfo[]
     * @throws VideoDownloaderDownloadException
     */
    
public function getDownloadsInfo()
    {
        
$fullInfo = $this->getFullInfo();
        
$fmts = $fullInfo['url_encoded_fmt_stream_map'];
        
$fmts = array_merge($fmts, $fullInfo['adaptive_fmts']);
        
$downloadsInfo = array();
        foreach (
$fmts AS $item) {
            
$downloadsInfo[] = $this->getDownloadInfoOne($item);
        }
        return 
$downloadsInfo;
    }

}
Онлайн: 2
Реклама