示例#1
0
        private static IEnumerable <VideoInfo> GetVideoInfos(IEnumerable <ExtractionInfo> extractionInfos, string videoTitle)
        {
            var downLoadInfos = new List <VideoInfo>();

            foreach (ExtractionInfo extractionInfo in extractionInfos)
            {
                string itag = HTTPHelperYoutube.ParseQueryString(extractionInfo.Uri.Query)["itag"];

                int formatCode = int.Parse(itag);

                VideoInfo info = VideoInfo.Defaults.SingleOrDefault(videoInfo => videoInfo.FormatCode == formatCode);

                if (info != null)
                {
                    info = new VideoInfo(info)
                    {
                        DownloadUrl        = extractionInfo.Uri.ToString(),
                        Title              = videoTitle,
                        RequiresDecryption = extractionInfo.RequiresDecryption
                    };
                }

                else
                {
                    info = new VideoInfo(formatCode)
                    {
                        DownloadUrl = extractionInfo.Uri.ToString()
                    };
                }

                downLoadInfos.Add(info);
            }

            return(downLoadInfos);
        }
示例#2
0
        public static bool TryNormalizeYoutubeUrl(string url, out string normalizedUrl)
        {
            url = url.Trim();

            url = url.Replace("youtu.be/", "youtube.com/watch?v=");
            url = url.Replace("www.youtube", "youtube");
            url = url.Replace("youtube.com/embed/", "youtube.com/watch?v=");

            if (url.Contains("/v/"))
            {
                url = "https://youtube.com" + new Uri(url).AbsolutePath.Replace("/v/", "/watch?v=");
            }

            url = url.Replace("/watch#", "/watch?");

            IDictionary <string, string> query = HTTPHelperYoutube.ParseQueryString(url);

            string v;

            if (!query.TryGetValue("v", out v))
            {
                normalizedUrl = null;
                return(false);
            }

            normalizedUrl = "https://youtube.com/watch?v=" + v;

            return(true);
        }
示例#3
0
        } //END TryNormalizeYoutubeUrl

        //--------------------------------------------------------------------------------//
        private static IEnumerable <ExtractionInfo> ExtractDownloadUrls(JObject json)
        //--------------------------------------------------------------------------------//
        {
            string[] splitByUrls            = GetStreamMap(json).Split(',');
            string[] adaptiveFmtSplitByUrls = GetAdaptiveStreamMap(json).Split(',');
            splitByUrls = splitByUrls.Concat(adaptiveFmtSplitByUrls).ToArray();

            foreach (string s in splitByUrls)
            {
                IDictionary <string, string> queries = HTTPHelperYoutube.ParseQueryString(s);
                string url;

                bool requiresDecryption = false;

                if (queries.ContainsKey("s") || queries.ContainsKey("sig"))
                {
                    requiresDecryption = queries.ContainsKey("s");
                    string signature = queries.ContainsKey("s") ? queries["s"] : queries["sig"];

                    url = string.Format("{0}&{1}={2}", queries["url"], SignatureQuery, signature);

                    string fallbackHost = queries.ContainsKey("fallback_host") ? "&fallback_host=" + queries["fallback_host"] : String.Empty;

                    url += fallbackHost;
                }

                else
                {
                    url = queries["url"];
                }

                url = HTTPHelperYoutube.UrlDecode(url);
                url = HTTPHelperYoutube.UrlDecode(url);

                IDictionary <string, string> parameters = HTTPHelperYoutube.ParseQueryString(url);
                if (!parameters.ContainsKey(RateBypassFlag))
                {
                    url += string.Format("&{0}={1}", RateBypassFlag, "yes");
                }

                yield return(new ExtractionInfo {
                    RequiresDecryption = requiresDecryption, Uri = new Uri(url)
                });
            }
        } //END ExtractDownloadUrls
示例#4
0
        public IEnumerator DecryptDownloadUrl(Action <string> callback, VideoInfo videoInfo)
        {
            IDictionary <string, string> queries = HTTPHelperYoutube.ParseQueryString(videoInfo.DownloadUrl);

            if (queries.ContainsKey(SignatureQuery))
            {
                string encryptedSignature = queries[SignatureQuery];

                //decrypted = GetDecipheredSignature( encryptedSignature);
                //MagicHands.DecipherWithVersion(encryptedSignature, videoInfo.HtmlPlayerVersion);
                //string jsUrl = string.Format("http://s.ytimg.com/yts/jsbin/{0}-{1}.js", videoInfo.HtmlscriptName, videoInfo.HtmlPlayerVersion);
                string jsUrl = string.Format("http://s.ytimg.com/yts/jsbin/player{0}.js", videoInfo.HtmlPlayerVersion);
                yield return(StartCoroutine(DownloadUrl(jsUrl)));

                string js = downloadUrlResponse.data;
                //Find "C" in this: var A = B.sig||C (B.s)
                string functNamePattern = @"(\w+)=function\((\w+)\){\2=\2\.split\(\""\""\);"; //Regex Formed To Find Word or DollarSign

                var funcName = Regex.Match(js, functNamePattern).Groups[1].Value;

                if (funcName.Contains("$"))
                {
                    funcName = "\\" + funcName; //Due To Dollar Sign Introduction, Need To Escape
                }

                string funcPattern = @"(?!h\.)" + @funcName + @"=function\(\w+\)\{.*?\}";         //Escape funcName string
                var    funcBody    = Regex.Match(js, funcPattern, RegexOptions.Singleline).Value; //Entire sig function
                var    lines       = funcBody.Split(';');                                         //Each line in sig function

                string idReverse = "", idSlice = "", idCharSwap = "";                             //Hold name for each cipher method
                string functionIdentifier = "";
                string operations         = "";

                foreach (var line in lines.Skip(1).Take(lines.Length - 2)) //Matches the funcBody with each cipher method. Only runs till all three are defined.
                {
                    if (!string.IsNullOrEmpty(idReverse) && !string.IsNullOrEmpty(idSlice) &&
                        !string.IsNullOrEmpty(idCharSwap))
                    {
                        break; //Break loop if all three cipher methods are defined
                    }

                    functionIdentifier = GetFunctionFromLine(line);
                    string reReverse = string.Format(@"{0}:\bfunction\b\(\w+\)", functionIdentifier);                        //Regex for reverse (one parameter)
                    string reSlice   = string.Format(@"{0}:\bfunction\b\([a],b\).(\breturn\b)?.?\w+\.", functionIdentifier); //Regex for slice (return or not)
                    string reSwap    = string.Format(@"{0}:\bfunction\b\(\w+\,\w\).\bvar\b.\bc=a\b", functionIdentifier);    //Regex for the char swap.

                    if (Regex.Match(js, reReverse).Success)
                    {
                        idReverse = functionIdentifier; //If def matched the regex for reverse then the current function is a defined as the reverse
                    }

                    if (Regex.Match(js, reSlice).Success)
                    {
                        idSlice = functionIdentifier; //If def matched the regex for slice then the current function is defined as the slice.
                    }

                    if (Regex.Match(js, reSwap).Success)
                    {
                        idCharSwap = functionIdentifier; //If def matched the regex for charSwap then the current function is defined as swap.
                    }
                }

                foreach (var line in lines.Skip(1).Take(lines.Length - 2))
                {
                    Match m;
                    functionIdentifier = GetFunctionFromLine(line);

                    if ((m = Regex.Match(line, @"\(\w+,(?<index>\d+)\)")).Success && functionIdentifier == idCharSwap)
                    {
                        operations += "w" + m.Groups["index"].Value + " "; //operation is a swap (w)
                    }

                    if ((m = Regex.Match(line, @"\(\w+,(?<index>\d+)\)")).Success && functionIdentifier == idSlice)
                    {
                        operations += "s" + m.Groups["index"].Value + " "; //operation is a slice
                    }

                    if (functionIdentifier == idReverse) //No regex required for reverse (reverse method has no parameters)
                    {
                        operations += "r ";              //operation is a reverse
                    }
                }

                operations = operations.Trim();

                string magicResult = MagicHands.DecipherWithOperations(encryptedSignature, operations);

                videoInfo.DownloadUrl        = HTTPHelperYoutube.ReplaceQueryStringParameter(videoInfo.DownloadUrl, SignatureQuery, magicResult);
                videoInfo.RequiresDecryption = false;
                callback.Invoke(videoInfo.DownloadUrl);
            }
            else
            {
                yield return(null);
            }
        }
示例#5
0
        public void DoRegexFunctionsForVideo()
        {
            string js = masterURLForVideo;
            //Find "C" in this: var A = B.sig||C (B.s)
            string functNamePattern = @"(\w+)\s*=\s*function\(\s*(\w+)\s*\)\s*{\s*\2\s*=\s*\2\.split\(\""\""\)\s*;(.+)return\s*\2\.join\(\""\""\)\s*}\s*;";

            var funcName = Regex.Match(js, functNamePattern).Groups[1].Value;

            if (funcName.Contains("$"))
            {
                funcName = "\\" + funcName; //Due To Dollar Sign Introduction, Need To Escape
            }

            string funcPattern = @"(?!h\.)" + @funcName + @"=function\(\w+\)\{.*?\}";         //Escape funcName string
            var    funcBody    = Regex.Match(js, funcPattern, RegexOptions.Singleline).Value; //Entire sig function
            var    lines       = funcBody.Split(';');                                         //Each line in sig function

            string idReverse = "", idSlice = "", idCharSwap = "";                             //Hold name for each cipher method
            string functionIdentifier = "";
            string operations         = "";

            foreach (var line in lines.Skip(1).Take(lines.Length - 2)) //Matches the funcBody with each cipher method. Only runs till all three are defined.
            {
                if (!string.IsNullOrEmpty(idReverse) && !string.IsNullOrEmpty(idSlice) &&
                    !string.IsNullOrEmpty(idCharSwap))
                {
                    break; //Break loop if all three cipher methods are defined
                }

                functionIdentifier = GetFunctionFromLine(line);
                string reReverse = string.Format(@"{0}:\bfunction\b\(\w+\)", functionIdentifier);                        //Regex for reverse (one parameter)
                string reSlice   = string.Format(@"{0}:\bfunction\b\([a],b\).(\breturn\b)?.?\w+\.", functionIdentifier); //Regex for slice (return or not)
                string reSwap    = string.Format(@"{0}:\bfunction\b\(\w+\,\w\).\bvar\b.\bc=a\b", functionIdentifier);    //Regex for the char swap.

                if (Regex.Match(js, reReverse).Success)
                {
                    idReverse = functionIdentifier; //If def matched the regex for reverse then the current function is a defined as the reverse
                }

                if (Regex.Match(js, reSlice).Success)
                {
                    idSlice = functionIdentifier; //If def matched the regex for slice then the current function is defined as the slice.
                }

                if (Regex.Match(js, reSwap).Success)
                {
                    idCharSwap = functionIdentifier; //If def matched the regex for charSwap then the current function is defined as swap.
                }
            }

            foreach (var line in lines.Skip(1).Take(lines.Length - 2))
            {
                Match m;
                functionIdentifier = GetFunctionFromLine(line);

                if ((m = Regex.Match(line, @"\(\w+,(?<index>\d+)\)")).Success && functionIdentifier == idCharSwap)
                {
                    operations += "w" + m.Groups["index"].Value + " "; //operation is a swap (w)
                }

                if ((m = Regex.Match(line, @"\(\w+,(?<index>\d+)\)")).Success && functionIdentifier == idSlice)
                {
                    operations += "s" + m.Groups["index"].Value + " "; //operation is a slice
                }

                if (functionIdentifier == idReverse) //No regex required for reverse (reverse method has no parameters)
                {
                    operations += "r ";              //operation is a reverse
                }
            }

            operations = operations.Trim();

            string magicResult = MagicHands.DecipherWithOperations(encryptedSignatureVideo, operations);

            decryptedVideoUrlResult = HTTPHelperYoutube.ReplaceQueryStringParameter(EncryptUrlForVideo, SignatureQuery, magicResult);
            decryptedUrlForVideo    = true;
        }