public static void IsSet(this Assert assert, VideoInfoSnippet videoInfoSnippet) { Assert.IsNotNull(videoInfoSnippet); Assert.That.IsNotBlank(videoInfoSnippet.Id); Assert.That.IsNotBlank(videoInfoSnippet.Title); Assert.IsNotNull(videoInfoSnippet.Description); Assert.IsNotNull(videoInfoSnippet.Keywords); }
/// <summary> /// Gets playlist info by ID, truncating resulting video list at given number of pages (1 page ≤ 200 videos) /// </summary> public async Task <PlaylistInfo> GetPlaylistInfoAsync(string playlistId, int maxPages) { if (playlistId == null) { throw new ArgumentNullException(nameof(playlistId)); } if (!ValidatePlaylistId(playlistId)) { throw new ArgumentException("Invalid Youtube playlist ID", nameof(playlistId)); } if (maxPages <= 0) { throw new ArgumentOutOfRangeException(nameof(maxPages), "Needs to be a positive number"); } // Get all videos across pages int pagesDone = 0; int offset = 0; XElement playlistInfoXml; var videos = new List <VideoInfoSnippet>(); var videoIds = new HashSet <string>(); do { // Get string request = $"https://www.youtube.com/list_ajax?style=xml&action_get_list=1&list={playlistId}&index={offset}"; string response = await _httpService.GetStringAsync(request).ConfigureAwait(false); playlistInfoXml = XElement.Parse(response).StripNamespaces(); // Parse videos int total = 0; int delta = 0; foreach (var videoInfoSnippetXml in playlistInfoXml.Elements("video")) { // Basic info string videoId = videoInfoSnippetXml.ElementStrict("encrypted_id").Value; string videoTitle = videoInfoSnippetXml.ElementStrict("title").Value; string videoDescription = videoInfoSnippetXml.ElementStrict("description").Value; long videoViewCount = Regex.Replace(videoInfoSnippetXml.ElementStrict("views").Value, @"\D", "") .ParseLong(); long videoLikeCount = Regex.Replace(videoInfoSnippetXml.ElementStrict("likes").Value, @"\D", "") .ParseLong(); long videoDislikeCount = Regex.Replace(videoInfoSnippetXml.ElementStrict("dislikes").Value, @"\D", "") .ParseLong(); // Keywords string videoKeywordsJoined = videoInfoSnippetXml.ElementStrict("keywords").Value; var videoKeywords = Regex .Matches(videoKeywordsJoined, @"(?<=(^|\s)(?<quote>""?))([^""]|(""""))*?(?=\<quote>(?=\s|$))") .Cast <Match>() .Select(m => m.Value) .Where(s => s.IsNotBlank()); var snippet = new VideoInfoSnippet(videoId, videoTitle, videoDescription, videoKeywords, videoViewCount, videoLikeCount, videoDislikeCount); // Add to list if not already there if (videoIds.Add(snippet.Id)) { videos.Add(snippet); delta++; } total++; } // Break if the videos started repeating if (delta <= 0) { break; } // Prepare for next page pagesDone++; offset += total; } while (pagesDone <= maxPages); // Parse metadata string title = playlistInfoXml.ElementStrict("title").Value; string author = playlistInfoXml.Element("author")?.Value ?? ""; string description = playlistInfoXml.ElementStrict("description").Value; long viewCount = (long)playlistInfoXml.ElementStrict("views"); return(new PlaylistInfo(playlistId, title, author, description, viewCount, videos)); }