diff --git a/YoutubeExplode.Tests/PlaylistSpecs.cs b/YoutubeExplode.Tests/PlaylistSpecs.cs index 015a9033..acf69d3b 100644 --- a/YoutubeExplode.Tests/PlaylistSpecs.cs +++ b/YoutubeExplode.Tests/PlaylistSpecs.cs @@ -189,4 +189,18 @@ public async Task I_can_get_a_subset_of_videos_included_in_a_playlist() // Assert videos.Should().HaveCount(10); } + + [Fact] + public async Task I_can_get_videos_included_in_a_playlist_with_a_lot_of_duplicate() + { + // Arrange + var youtube = new YoutubeClient(); + + // Act + var videos = await youtube.Playlists.GetVideosAsync(PlaylistIds.EnormousDuplicates); + + // Assert + videos.Should().HaveCountGreaterOrEqualTo(3_900); + videos.Should().OnlyHaveUniqueItems(); + } } diff --git a/YoutubeExplode.Tests/TestData/PlaylistIds.cs b/YoutubeExplode.Tests/TestData/PlaylistIds.cs index f6ed9f35..46c0dedb 100644 --- a/YoutubeExplode.Tests/TestData/PlaylistIds.cs +++ b/YoutubeExplode.Tests/TestData/PlaylistIds.cs @@ -12,4 +12,5 @@ internal static class PlaylistIds public const string UserUploads = "UUTMt7iMWa7jy0fNXIktwyLA"; public const string Weird = "PL601B2E69B03FAB9D"; public const string ContainsLongVideos = "PLkk2FsMngwGi9FNkWIoNZlfqglcldj_Zs"; + public const string EnormousDuplicates = "PLI_eFW8NAFzYAXZ5DrU6E6mQ_XfhaLBUX"; } diff --git a/YoutubeExplode/Playlists/PlaylistClient.cs b/YoutubeExplode/Playlists/PlaylistClient.cs index 38c60085..bb195936 100644 --- a/YoutubeExplode/Playlists/PlaylistClient.cs +++ b/YoutubeExplode/Playlists/PlaylistClient.cs @@ -4,6 +4,7 @@ using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; +using YoutubeExplode.Bridge; using YoutubeExplode.Common; using YoutubeExplode.Exceptions; using YoutubeExplode.Videos; @@ -92,8 +93,20 @@ public async IAsyncEnumerable> GetVideoBatchesAsync( ); var videos = new List(); + IEnumerable originalVideos; + if (!encounteredIds.Any()) + { + originalVideos = response.Videos.DistinctBy(v => v.Id); + } + else + { + originalVideos = response.Videos.Where(v => + { + return !encounteredIds.Any(e => string.Equals(e.Value, v.Id)); + }); + } - foreach (var videoData in response.Videos) + foreach (var videoData in originalVideos) { var videoId = videoData.Id @@ -105,9 +118,7 @@ public async IAsyncEnumerable> GetVideoBatchesAsync( videoData.Index ?? throw new YoutubeExplodeException("Failed to extract the video index."); - // Don't yield the same video twice - if (!encounteredIds.Add(videoId)) - continue; + encounteredIds.Add(videoId); var videoTitle = videoData.Title