コード例 #1
0
 public VideoDownloadInfo(VideoAvailabilityEnum availability, string contentId, string contentTitle, string errorMessage, List <VideoMetadata> videos)
 {
     Availability = availability;
     ContentId    = contentId;
     ContentTitle = contentTitle;
     ErrorMessage = errorMessage;
     Videos       = (videos?.Count ?? 0) > 0 ? new List <VideoMetadata>(videos) : null;
 }
コード例 #2
0
        // Retrieves the available download urls by decoding the video info DOM for the 'contentId' to parse for itags.
        public VideoDownloadInfo GetVideoDownloadInfo(string contentId, string contentTitle, string dom)
        {
            const string _responseError     = "&errorcode";
            const string _responseErrorCode = "&errorcode=150";
            const string _responsePurchase  = "&requires_purchase";
            const string _url = "url=";

            const string _streamMapPattern = "(?<=url_encoded_fmt_stream_map=).*";


            if (string.IsNullOrEmpty(contentId))
            {
                return(new VideoDownloadInfo(VideoAvailabilityEnum.NotAvailable, null, contentTitle, "Missing content id.", null));
            }
            if (string.IsNullOrEmpty(contentTitle))
            {
                return(new VideoDownloadInfo(VideoAvailabilityEnum.NotAvailable, contentId, null, "Missing content title.", null));
            }
            if (string.IsNullOrEmpty(dom))
            {
                return(new VideoDownloadInfo(VideoAvailabilityEnum.NotAvailable, contentId, contentTitle, "Missing dom.", null));
            }

            // Decode pass 1.
            dom = WebUtility.UrlDecode(dom);

            // Check for errors and specific messages.
            if (dom.Contains(_responseError) || dom.Contains(_responsePurchase))
            {
                string errorMessage = string.Empty;
                VideoAvailabilityEnum errorStatus = VideoAvailabilityEnum.NotAvailable;

                if (dom.Contains(_responseErrorCode))
                {
                    errorStatus  = VideoAvailabilityEnum.ErrorCode;
                    errorMessage = "YouTube video info response contains errorcode 150.";
                }
                else if (_responseError.Contains(_responsePurchase))
                {
                    errorStatus  = VideoAvailabilityEnum.RequiresPurchase;
                    errorMessage = "YouTube content requires purchase.";
                }
                else
                {
                    errorStatus  = VideoAvailabilityEnum.ErrorCode;
                    errorMessage = "The dom contains an error in the response.";
                }

                return(new VideoDownloadInfo(errorStatus, contentId, contentTitle, errorMessage, null));
            }

            // Get everything after "url_encoded_fmt_stream_map=".
            dom = Regex.Match(dom, _streamMapPattern).Value;

            // Decode pass 2.
            dom = WebUtility.UrlDecode(dom);

            // Split.
            string[] responseUrls = Regex.Split(dom, _url);

            // Clean up the URLs and place them in a new list.
            var data = new List <VideoMetadata>(responseUrls.Length);

            foreach (var response in responseUrls)
            {
                string url = RemoveQueryParameters(response);

                // Check the results after removing unnecessary query parameters and gather the metadata for the url.
                if (!string.IsNullOrEmpty(url))
                {
                    if (MediaQualityEnumHelpers.TryParseUrlForItag(url, out string itag))
                    {
                        if (MediaQualityEnumHelpers.TryMapItagToEnum(itag, out MediaQualityEnum quality))
                        {
                            data.Add(new VideoMetadata(contentId, contentTitle, quality, url));     // Hope
                        }
                    }
                }
            }

            // Check if there are urls.
            if (data.Count < 1)
            {
                return(new VideoDownloadInfo(VideoAvailabilityEnum.NotAvailable, contentId, contentTitle, "Download urls are not available.", null));
            }

            // Lower the capacity of the metadata list.
            data.TrimExcess();

            return(new VideoDownloadInfo(
                       VideoAvailabilityEnum.Available,
                       contentId,
                       contentTitle,
                       null,
                       data));
        }