diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/linkhandler/ReadyChannelTabListLinkHandler.java b/extractor/src/main/java/org/schabi/newpipe/extractor/linkhandler/ReadyChannelTabListLinkHandler.java index e756ae0f4..48c6d0d4c 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/linkhandler/ReadyChannelTabListLinkHandler.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/linkhandler/ReadyChannelTabListLinkHandler.java @@ -3,6 +3,7 @@ package org.schabi.newpipe.extractor.linkhandler; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.channel.ChannelTabExtractor; +import java.io.Serializable; import java.util.Collections; /** @@ -22,7 +23,7 @@ import java.util.Collections; */ public class ReadyChannelTabListLinkHandler extends ListLinkHandler { - public interface ChannelTabExtractorBuilder { + public interface ChannelTabExtractorBuilder extends Serializable { ChannelTabExtractor build(StreamingService service, ListLinkHandler linkHandler); } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampChannelExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampChannelExtractor.java index a49c7a635..2b25131a4 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampChannelExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampChannelExtractor.java @@ -8,10 +8,6 @@ import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; import org.jsoup.Jsoup; -import org.schabi.newpipe.extractor.InfoItem; -import org.schabi.newpipe.extractor.ListExtractor; -import org.schabi.newpipe.extractor.MultiInfoItemsCollector; -import org.schabi.newpipe.extractor.Page; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.channel.ChannelExtractor; import org.schabi.newpipe.extractor.channel.ChannelTabExtractor; @@ -22,8 +18,6 @@ import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; import org.schabi.newpipe.extractor.linkhandler.ChannelTabs; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.linkhandler.ReadyChannelTabListLinkHandler; -import org.schabi.newpipe.extractor.services.bandcamp.extractors.streaminfoitem.BandcampDiscographStreamInfoItemExtractor; -import org.schabi.newpipe.extractor.services.bandcamp.linkHandler.BandcampChannelTabHandler; import org.schabi.newpipe.extractor.services.bandcamp.linkHandler.BandcampChannelTabLinkHandlerFactory; import java.io.IOException; @@ -117,16 +111,21 @@ public class BandcampChannelExtractor extends ChannelExtractor { @Override public List getTabs() throws ParsingException { final JsonArray discography = channelInfo.getArray("discography"); + final TabExtractorBuilder builder = new TabExtractorBuilder(discography); final List tabs = new ArrayList<>(); - tabs.add(new ReadyChannelTabListLinkHandler(getUrl(), getId(), - ChannelTabs.TRACKS, this::buildTracksTabExtractor)); + + if (discography.stream().anyMatch(o -> ( + (JsonObject) o).getString("item_type").equals("track"))) { + tabs.add(new ReadyChannelTabListLinkHandler(getUrl(), getId(), + ChannelTabs.TRACKS, builder)); + } if (discography.stream().anyMatch(o -> ( (JsonObject) o).getString("item_type").equals("album"))) { - tabs.add(new BandcampChannelTabHandler( + tabs.add(new ReadyChannelTabListLinkHandler( getUrl() + BandcampChannelTabLinkHandlerFactory.URL_SUFFIX, - getId(), ChannelTabs.ALBUMS, discography)); + getId(), ChannelTabs.ALBUMS, builder)); } return tabs; @@ -144,41 +143,18 @@ public class BandcampChannelExtractor extends ChannelExtractor { return channelInfo.getString("name"); } - private ChannelTabExtractor buildTracksTabExtractor(final StreamingService service, - final ListLinkHandler linkHandler) { - return new ChannelTabExtractor(service, linkHandler) { - @Nonnull - @Override - public InfoItemsPage getInitialPage() throws ExtractionException { - final MultiInfoItemsCollector collector = - new MultiInfoItemsCollector(getServiceId()); + private static class TabExtractorBuilder + implements ReadyChannelTabListLinkHandler.ChannelTabExtractorBuilder { + private final JsonArray discography; - final JsonArray discography = channelInfo.getArray("discography"); + TabExtractorBuilder(final JsonArray discography) { + this.discography = discography; + } - for (int i = 0; i < discography.size(); i++) { - // A discograph is as an item appears in a discography - final JsonObject discograph = discography.getObject(i); - - if (!discograph.getString("item_type").equals("track")) { - continue; - } - - collector.commit( - new BandcampDiscographStreamInfoItemExtractor(discograph, getUrl())); - } - - return new InfoItemsPage<>(collector, null); - } - - @Override - public InfoItemsPage getPage(final Page page) { - return ListExtractor.InfoItemsPage.emptyPage(); - } - - @Override - public void onFetchPage(@Nonnull final Downloader downloader) { - // nothing to do here, as data was already fetched - } - }; + @Override + public ChannelTabExtractor build(final StreamingService service, + final ListLinkHandler linkHandler) { + return BandcampChannelTabExtractor.fromDiscography(service, linkHandler, discography); + } } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampChannelTabExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampChannelTabExtractor.java index 7ba9a39d2..61c19c651 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampChannelTabExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampChannelTabExtractor.java @@ -9,34 +9,49 @@ 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.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.ChannelTabs; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; -import org.schabi.newpipe.extractor.services.bandcamp.linkHandler.BandcampChannelTabHandler; +import org.schabi.newpipe.extractor.services.bandcamp.extractors.streaminfoitem.BandcampDiscographStreamInfoItemExtractor; import javax.annotation.Nonnull; import java.io.IOException; public class BandcampChannelTabExtractor extends ChannelTabExtractor { + private JsonArray discography; + private final String filter; + public BandcampChannelTabExtractor(final StreamingService service, final ListLinkHandler linkHandler) { super(service, linkHandler); - } - @Nonnull - private JsonArray getDiscographs() throws ExtractionException { - final ListLinkHandler tabHandler = getLinkHandler(); - if (tabHandler instanceof BandcampChannelTabHandler) { - return ((BandcampChannelTabHandler) tabHandler).getDiscographs(); - } else { - final JsonObject artistDetails = BandcampExtractorHelper.getArtistDetails(getId()); - return artistDetails.getArray("discography"); + final String tab = linkHandler.getContentFilters().get(0); + switch (tab) { + case ChannelTabs.TRACKS: + filter = "track"; + break; + case ChannelTabs.ALBUMS: + filter = "album"; + break; + default: + throw new IllegalArgumentException("unsupported channel tab: " + tab); } } + public static BandcampChannelTabExtractor fromDiscography(final StreamingService service, + final ListLinkHandler linkHandler, + final JsonArray discography) { + final BandcampChannelTabExtractor tabExtractor = + new BandcampChannelTabExtractor(service, linkHandler); + tabExtractor.discography = discography; + return tabExtractor; + } + @Override - public void onFetchPage(@Nonnull final Downloader downloader) { - if (!getTab().equals(ChannelTabs.ALBUMS)) { - throw new IllegalArgumentException("tab " + getTab() + " not supported"); + public void onFetchPage(@Nonnull final Downloader downloader) throws ParsingException { + if (discography == null) { + final JsonObject artistDetails = BandcampExtractorHelper.getArtistDetails(getId()); + discography = artistDetails.getArray("discography"); } } @@ -45,14 +60,26 @@ public class BandcampChannelTabExtractor extends ChannelTabExtractor { public InfoItemsPage getInitialPage() throws IOException, ExtractionException { final MultiInfoItemsCollector collector = new MultiInfoItemsCollector(getServiceId()); - final JsonArray discography = getDiscographs(); - final String baseUrl = getBaseUrl(); - discography.stream() - .filter(discograph -> discograph instanceof JsonObject - && ((JsonObject) discograph).getString("item_type").equals("album")) - .forEach(discograph -> collector.commit(new BandcampAlbumInfoItemExtractor( - (JsonObject) discograph, baseUrl)) - ); + for (int i = 0; i < discography.size(); i++) { + // A discograph is as an item appears in a discography + final JsonObject discograph = discography.getObject(i); + final String itemType = discograph.getString("item_type", ""); + + if (!itemType.equals(filter)) { + continue; + } + + switch (itemType) { + case "track": + collector.commit(new BandcampDiscographStreamInfoItemExtractor( + discograph, getUrl())); + break; + case "album": + collector.commit(new BandcampAlbumInfoItemExtractor( + discograph, getUrl())); + break; + } + } return new InfoItemsPage<>(collector, null); } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampExtractorHelper.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampExtractorHelper.java index aff866053..9040acb6e 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampExtractorHelper.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampExtractorHelper.java @@ -119,6 +119,7 @@ public final class BandcampExtractorHelper { /** * Whether the URL points to a radio kiosk. + * * @param url the URL to check * @return true if the URL matches {@code https://bandcamp.com/?show=SHOW_ID} */ diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampChannelTabHandler.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampChannelTabHandler.java deleted file mode 100644 index cc09a8cef..000000000 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampChannelTabHandler.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.schabi.newpipe.extractor.services.bandcamp.linkHandler; - -import com.grack.nanojson.JsonArray; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; - -import java.util.Collections; - -public class BandcampChannelTabHandler extends ListLinkHandler { - private final JsonArray discographs; - - public BandcampChannelTabHandler(final String url, final String id, final String tab, - final JsonArray discographs) { - super(url, url, id, Collections.singletonList(tab), ""); - this.discographs = discographs; - } - - public JsonArray getDiscographs() { - return discographs; - } -} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCConferenceExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCConferenceExtractor.java index f8d5fef80..6cef83497 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCConferenceExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCConferenceExtractor.java @@ -83,7 +83,7 @@ public class MediaCCCConferenceExtractor extends ChannelExtractor { @Override public List getTabs() throws ParsingException { return Collections.singletonList(new ReadyChannelTabListLinkHandler(getUrl(), getId(), - ChannelTabs.VIDEOS, this::buildEventsTabExtractor)); + ChannelTabs.VIDEOS, new VideoTabExtractorBuilder(conferenceData))); } @Override @@ -104,30 +104,51 @@ public class MediaCCCConferenceExtractor extends ChannelExtractor { return conferenceData.getString("title"); } - private ChannelTabExtractor buildEventsTabExtractor(final StreamingService service, - final ListLinkHandler linkHandler) { - return new ChannelTabExtractor(service, linkHandler) { - @Nonnull - @Override - public InfoItemsPage getInitialPage() { - final MultiInfoItemsCollector collector = - new MultiInfoItemsCollector(getServiceId()); - final JsonArray events = conferenceData.getArray("events"); - for (int i = 0; i < events.size(); i++) { - collector.commit(new MediaCCCStreamInfoItemExtractor(events.getObject(i))); - } - return new InfoItemsPage<>(collector, null); - } + private static class VideoTabExtractorBuilder + implements ReadyChannelTabListLinkHandler.ChannelTabExtractorBuilder { + private final JsonObject conferenceData; - @Override - public InfoItemsPage getPage(final Page page) { - return InfoItemsPage.emptyPage(); - } + VideoTabExtractorBuilder(final JsonObject conferenceData) { + this.conferenceData = conferenceData; + } - @Override - public void onFetchPage(@Nonnull final Downloader downloader) { - // nothing to do here, as data was already fetched + @Override + public ChannelTabExtractor build(final StreamingService service, + final ListLinkHandler linkHandler) { + return new VideoTabExtractor(service, linkHandler, conferenceData); + } + } + + private static class VideoTabExtractor extends ChannelTabExtractor { + private final JsonObject conferenceData; + + VideoTabExtractor(final StreamingService service, + final ListLinkHandler linkHandler, + final JsonObject conferenceData) { + super(service, linkHandler); + this.conferenceData = conferenceData; + } + + @Override + public void onFetchPage(@Nonnull final Downloader downloader) { + // nothing to do here, as data was already fetched + } + + @Nonnull + @Override + public InfoItemsPage getInitialPage() { + final MultiInfoItemsCollector collector = + new MultiInfoItemsCollector(getServiceId()); + final JsonArray events = conferenceData.getArray("events"); + for (int i = 0; i < events.size(); i++) { + collector.commit(new MediaCCCStreamInfoItemExtractor(events.getObject(i))); } - }; + return new InfoItemsPage<>(collector, null); + } + + @Override + public InfoItemsPage getPage(final Page page) { + return InfoItemsPage.emptyPage(); + } } } 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 3cde88b75..bfd9f5a32 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 @@ -12,6 +12,7 @@ import com.grack.nanojson.JsonObject; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.channel.ChannelExtractor; +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.exceptions.ParsingException; @@ -249,8 +250,7 @@ public class YoutubeChannelExtractor extends ChannelExtractor { final String url = getUrl(); tabs.add(0, new ReadyChannelTabListLinkHandler(tabUrl, redirectedChannelId, ChannelTabs.VIDEOS, - (service, linkHandler) -> new YoutubeChannelVideosTabExtractor( - service, linkHandler, tabRenderer, name, url))); + new VideoTabExtractorBuilder(name, url, tabRenderer))); break; case "playlists": addTab.accept(ChannelTabs.PLAYLISTS); @@ -280,4 +280,25 @@ public class YoutubeChannelExtractor extends ChannelExtractor { return tags.stream().map(Object::toString).collect(Collectors.toList()); } + + private static class VideoTabExtractorBuilder + implements ReadyChannelTabListLinkHandler.ChannelTabExtractorBuilder { + private final String channelName; + private final String channelUrl; + private final JsonObject tabRenderer; + + VideoTabExtractorBuilder(final String channelName, final String channelUrl, + final JsonObject tabRenderer) { + this.channelName = channelName; + this.channelUrl = channelUrl; + this.tabRenderer = tabRenderer; + } + + @Override + public ChannelTabExtractor build(final StreamingService service, + final ListLinkHandler linkHandler) { + return new YoutubeChannelVideosTabExtractor( + service, linkHandler, tabRenderer, channelName, channelUrl); + } + } } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/bandcamp/BandcampChannelExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/bandcamp/BandcampChannelExtractorTest.java index f9d08c946..5bbed88c6 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/bandcamp/BandcampChannelExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/bandcamp/BandcampChannelExtractorTest.java @@ -67,11 +67,10 @@ public class BandcampChannelExtractorTest implements BaseChannelExtractorTest { public void testTabs() throws Exception { Set tabs = extractor.getTabs().stream() .map(linkHandler -> linkHandler.getContentFilters().get(0)).collect(Collectors.toSet()); - assertTrue(tabs.contains(ChannelTabs.TRACKS)); - assertTrue(tabs.contains(ChannelTabs.ALBUMS)); + assertTrue(tabs.contains(ChannelTabs.ALBUMS), "albums"); } - @Override + @Test public void testRelatedItems() throws Exception { defaultTestRelatedItems(tabExtractor); }