Пример #1
0
        /// <summary>
        /// Downloads video's embed page and extracts useful data.
        /// </summary>
        protected virtual async Task <YouTubeEmbedPageData> DownloadEmbedPage(string id)
        {
            var result = new YouTubeEmbedPageData();

            // get embed uri
            var embedUri = GetYouTubeEmbedUri(id);

            // download embed page
            var client           = HttpHelper.CreateClient();
            var embedPageContent = await client.GetStringAsync(embedUri);

            // find base.js
            var match = BaseJsLocatorRegex.Match(embedPageContent);

            if (!match.Success)
            {
                throw new GrabParseException("Failed to find base.js script reference.");
            }
            result.BaseJsUri = new Uri(embedUri, match.Groups[1].Value);

            return(result);
        }
Пример #2
0
        /// <summary>
        /// Invoked by <see cref="GrabAsync"/> method when the target video has a signature.
        /// This method downloads the necessary script (base.js) and decipher all grabbed links.
        /// </summary>
        protected virtual async Task Decipher(YouTubeEmbedPageData embedPageData, YouTubeMetadata metaData, CancellationToken cancellationToken)
        {
            // download base.js
            var client = HttpHelper.CreateClient();

            using var response = await client.GetAsync(embedPageData.BaseJsUri, cancellationToken);

            var scriptContent = await response.Content.ReadAsStringAsync();

            var script = new YouTubeScript(scriptContent);

            // find decipher function name
            var match = DecipherFunctionRegex.Match(scriptContent);

            if (!match.Success)
            {
                throw new GrabParseException("Failed to locate decipher function.");
            }
            var fn = match.Groups[1].Value;

            // prepare script host to execute the decipher function along with its used functions
            script.PrepareDecipherFunctionCall(fn);

            // call decipher function
            foreach (var streamInfo in metaData.AllStreams)
            {
                if (string.IsNullOrEmpty(streamInfo.Signature))
                {
                    continue;
                }

                // calculate decipher
                streamInfo.Decipher = script.CallDecipherFunction(fn, streamInfo.Signature);

                // update uri
                streamInfo.Url += $"&sig={Uri.EscapeDataString(streamInfo.Decipher)}";
            }
        }