From 2ad496fc2b932dd89009f3892462014cb231f6ca Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Sun, 16 Apr 2023 15:54:00 +0200 Subject: [PATCH] refactor: merge YoutubeChannelTabExtractor and YoutubeChannelVideosTabExtractor --- .../extractors/YoutubeChannelExtractor.java | 2 +- .../YoutubeChannelTabExtractor.java | 42 +++- .../YoutubeChannelVideosTabExtractor.java | 180 ------------------ 3 files changed, 41 insertions(+), 183 deletions(-) delete mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelVideosTabExtractor.java diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java index a5ac98b09..60e562c47 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java @@ -306,7 +306,7 @@ public class YoutubeChannelExtractor extends ChannelExtractor { @Override public ChannelTabExtractor build(final StreamingService service, final ListLinkHandler linkHandler) { - return new YoutubeChannelVideosTabExtractor( + return new YoutubeChannelTabExtractor.VideoTabExtractor( service, linkHandler, tabRenderer, channelName, channelUrl); } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelTabExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelTabExtractor.java index ad13688f3..fb5286526 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelTabExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelTabExtractor.java @@ -128,7 +128,7 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor { } } - private String getChannelName() { + protected String getChannelName() { final String mdName = initialData .getObject("metadata") .getObject("channelMetadataRenderer") @@ -234,7 +234,7 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor { getNextPageFrom(continuation, channelIds)); } - private Optional getTabData() throws ParsingException { + Optional getTabData() throws ParsingException { final String urlSuffix = YoutubeChannelTabLinkHandlerFactory.getUrlSuffix(getTab()); final JsonArray tabs = initialData.getObject("contents") @@ -353,4 +353,42 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor { return new Page(YOUTUBEI_V1_URL + "browse?key=" + getKey() + DISABLE_PRETTY_PRINT_PARAMETER, null, channelIds, null, body); } + + public static class VideoTabExtractor extends YoutubeChannelTabExtractor { + private final JsonObject tabRenderer; + private final String channelName; + private final String channelUrl; + + VideoTabExtractor(final StreamingService service, + final ListLinkHandler linkHandler, + final JsonObject tabRenderer, + final String channelName, + final String channelUrl) { + super(service, linkHandler); + this.tabRenderer = tabRenderer; + this.channelName = channelName; + this.channelUrl = channelUrl; + } + + @Override + public void onFetchPage(@Nonnull final Downloader downloader) { + // nothing to do, all data was already fetched and is stored in the link handler + } + + @Nonnull + @Override + public String getUrl() throws ParsingException { + return channelUrl; + } + + @Override + protected String getChannelName() { + return channelName; + } + + @Override + Optional getTabData() { + return Optional.of(tabRenderer); + } + } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelVideosTabExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelVideosTabExtractor.java deleted file mode 100644 index 757936985..000000000 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelVideosTabExtractor.java +++ /dev/null @@ -1,180 +0,0 @@ -package org.schabi.newpipe.extractor.services.youtube.extractors; - -import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.DISABLE_PRETTY_PRINT_PARAMETER; -import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.YOUTUBEI_V1_URL; -import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonPostResponse; -import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getKey; -import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.prepareDesktopJsonBuilder; -import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; - -import com.grack.nanojson.JsonArray; -import com.grack.nanojson.JsonObject; -import com.grack.nanojson.JsonWriter; - -import org.schabi.newpipe.extractor.InfoItem; -import org.schabi.newpipe.extractor.MultiInfoItemsCollector; -import org.schabi.newpipe.extractor.Page; -import org.schabi.newpipe.extractor.StreamingService; -import org.schabi.newpipe.extractor.channel.ChannelTabExtractor; -import org.schabi.newpipe.extractor.downloader.Downloader; -import org.schabi.newpipe.extractor.exceptions.ExtractionException; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; -import org.schabi.newpipe.extractor.localization.TimeAgoParser; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class YoutubeChannelVideosTabExtractor extends ChannelTabExtractor { - private final JsonObject tabRenderer; - private final String channelName; - private final String channelUrl; - - public YoutubeChannelVideosTabExtractor(final StreamingService service, - final ListLinkHandler linkHandler, - final JsonObject tabRenderer, - final String channelName, - final String channelUrl) { - super(service, linkHandler); - this.tabRenderer = tabRenderer; - this.channelName = channelName; - this.channelUrl = channelUrl; - } - - @Override - public void onFetchPage(@Nonnull final Downloader downloader) - throws IOException, ExtractionException { - // nothing to do, all data was already fetched and is stored in the link handler - } - - @Nonnull - @Override - public InfoItemsPage getInitialPage() throws IOException, ExtractionException { - final MultiInfoItemsCollector collector = new MultiInfoItemsCollector(getServiceId()); - - final JsonObject tabContent = tabRenderer.getObject("content"); - - JsonArray items = tabContent - .getObject("sectionListRenderer") - .getArray("contents").getObject(0).getObject("itemSectionRenderer") - .getArray("contents").getObject(0).getObject("gridRenderer").getArray("items"); - - if (items.isEmpty()) { - items = tabContent.getObject("richGridRenderer").getArray("contents"); - } - - final List channelIds = new ArrayList<>(); - channelIds.add(channelName); - channelIds.add(channelUrl); - final JsonObject continuation = collectStreamsFrom(collector, items, channelIds); - - return new InfoItemsPage<>(collector, getNextPageFrom(continuation, channelIds)); - } - - @Override - public InfoItemsPage getPage(final Page page) - throws IOException, ExtractionException { - if (page == null || isNullOrEmpty(page.getUrl())) { - throw new IllegalArgumentException("Page doesn't contain an URL"); - } - - final List channelIds = page.getIds(); - - final MultiInfoItemsCollector collector = new MultiInfoItemsCollector(getServiceId()); - - final JsonObject ajaxJson = getJsonPostResponse("browse", page.getBody(), - getExtractorLocalization()); - - final JsonObject sectionListContinuation = ajaxJson.getArray("onResponseReceivedActions") - .getObject(0) - .getObject("appendContinuationItemsAction"); - - final JsonObject continuation = collectStreamsFrom(collector, sectionListContinuation - .getArray("continuationItems"), channelIds); - - return new InfoItemsPage<>(collector, getNextPageFrom(continuation, channelIds)); - } - - @Nullable - private Page getNextPageFrom(final JsonObject continuations, - final List channelIds) - throws IOException, ExtractionException { - if (isNullOrEmpty(continuations)) { - return null; - } - - final JsonObject continuationEndpoint = continuations.getObject("continuationEndpoint"); - final String continuation = continuationEndpoint.getObject("continuationCommand") - .getString("token"); - - final byte[] body = JsonWriter.string(prepareDesktopJsonBuilder(getExtractorLocalization(), - getExtractorContentCountry()) - .value("continuation", continuation) - .done()) - .getBytes(StandardCharsets.UTF_8); - - return new Page(YOUTUBEI_V1_URL + "browse?key=" + getKey() - + DISABLE_PRETTY_PRINT_PARAMETER, null, channelIds, null, body); - } - - /** - * Collect streams from an array of items - * - * @param collector the collector where videos will be committed - * @param videos the array to get videos from - * @param channelIds the ids of the channel, which are its name and its URL - * @return the continuation object - */ - private JsonObject collectStreamsFrom(@Nonnull final MultiInfoItemsCollector collector, - @Nonnull final JsonArray videos, - @Nonnull final List channelIds) { - collector.reset(); - - final String uploaderName = channelIds.get(0); - final String uploaderUrl = channelIds.get(1); - final TimeAgoParser timeAgoParser = getTimeAgoParser(); - - JsonObject continuation = null; - - for (final Object object : videos) { - final JsonObject video = (JsonObject) object; - if (video.has("gridVideoRenderer")) { - collector.commit(new YoutubeStreamInfoItemExtractor( - video.getObject("gridVideoRenderer"), timeAgoParser) { - @Override - public String getUploaderName() { - return uploaderName; - } - - @Override - public String getUploaderUrl() { - return uploaderUrl; - } - }); - } else if (video.has("richItemRenderer")) { - collector.commit(new YoutubeStreamInfoItemExtractor( - video.getObject("richItemRenderer") - .getObject("content").getObject("videoRenderer"), timeAgoParser) { - @Override - public String getUploaderName() { - return uploaderName; - } - - @Override - public String getUploaderUrl() { - return uploaderUrl; - } - }); - - } else if (video.has("continuationItemRenderer")) { - continuation = video.getObject("continuationItemRenderer"); - } - } - - return continuation; - } -}