diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistExtractor.java index 06f055f14..bbb5955e0 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistExtractor.java @@ -41,6 +41,9 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor { // Names of some objects in JSON response frequently used in this class private static final String PLAYLIST_VIDEO_RENDERER = "playlistVideoRenderer"; private static final String PLAYLIST_VIDEO_LIST_RENDERER = "playlistVideoListRenderer"; + private static final String RICH_GRID_RENDERER = "richGridRenderer"; + private static final String RICH_ITEM_RENDERER = "richItemRenderer"; + private static final String REEL_ITEM_RENDERER = "reelItemRenderer"; private static final String SIDEBAR = "sidebar"; private static final String VIDEO_OWNER_RENDERER = "videoOwnerRenderer"; @@ -85,10 +88,6 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor { * browse response (the old returns instead a sidebar one). *

* - *

- * This new playlist UI is currently A/B tested. - *

- * * @return Whether the playlist response is using only the new playlist design */ private boolean checkIfResponseIsNewPlaylistInterface() { @@ -327,17 +326,22 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor { .map(content -> content.getObject("itemSectionRenderer") .getArray("contents") .getObject(0)) - .filter(contentItemSectionRendererContents -> - contentItemSectionRendererContents.has(PLAYLIST_VIDEO_LIST_RENDERER) - || contentItemSectionRendererContents.has( - "playlistSegmentRenderer")) + .filter(content -> content.has(PLAYLIST_VIDEO_LIST_RENDERER) + || content.has(RICH_GRID_RENDERER)) .findFirst() .orElse(null); - if (videoPlaylistObject != null && videoPlaylistObject.has(PLAYLIST_VIDEO_LIST_RENDERER)) { - final JsonArray videosArray = videoPlaylistObject - .getObject(PLAYLIST_VIDEO_LIST_RENDERER) - .getArray("contents"); + if (videoPlaylistObject != null) { + final JsonObject renderer; + if (videoPlaylistObject.has(PLAYLIST_VIDEO_LIST_RENDERER)) { + renderer = videoPlaylistObject.getObject(PLAYLIST_VIDEO_LIST_RENDERER); + } else if (videoPlaylistObject.has(RICH_GRID_RENDERER)) { + renderer = videoPlaylistObject.getObject(RICH_GRID_RENDERER); + } else { + return new InfoItemsPage<>(collector, null); + } + + final JsonArray videosArray = renderer.getArray("contents"); collectStreamsFrom(collector, videosArray); nextPage = getNextPageFrom(videosArray); @@ -399,14 +403,26 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor { private void collectStreamsFrom(@Nonnull final StreamInfoItemsCollector collector, @Nonnull final JsonArray videos) { final TimeAgoParser timeAgoParser = getTimeAgoParser(); - videos.stream() .filter(JsonObject.class::isInstance) .map(JsonObject.class::cast) - .filter(video -> video.has(PLAYLIST_VIDEO_RENDERER)) - .map(video -> new YoutubeStreamInfoItemExtractor( - video.getObject(PLAYLIST_VIDEO_RENDERER), timeAgoParser)) - .forEachOrdered(collector::commit); + .forEach(video -> { + if (video.has(PLAYLIST_VIDEO_RENDERER)) { + collector.commit(new YoutubeStreamInfoItemExtractor( + video.getObject(PLAYLIST_VIDEO_RENDERER), timeAgoParser)); + } else if (video.has(RICH_ITEM_RENDERER)) { + final JsonObject richItemRenderer = video.getObject(RICH_ITEM_RENDERER); + if (richItemRenderer.has("content")) { + final JsonObject richItemRendererContent = + richItemRenderer.getObject("content"); + if (richItemRendererContent.has(REEL_ITEM_RENDERER)) { + collector.commit(new YoutubeReelInfoItemExtractor( + richItemRendererContent.getObject(REEL_ITEM_RENDERER), + timeAgoParser)); + } + } + } + }); } @Nonnull