diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCService.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCService.java index ad745b70d..3e3a4726e 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCService.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCService.java @@ -6,6 +6,7 @@ import static java.util.Arrays.asList; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.channel.ChannelExtractor; +import org.schabi.newpipe.extractor.channel.tabs.ChannelTabExtractor; import org.schabi.newpipe.extractor.comments.CommentsExtractor; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.kiosk.KioskList; @@ -13,6 +14,7 @@ import org.schabi.newpipe.extractor.linkhandler.LinkHandler; import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; +import org.schabi.newpipe.extractor.linkhandler.ReadyChannelTabListLinkHandler; import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler; import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandlerFactory; import org.schabi.newpipe.extractor.playlist.PlaylistExtractor; @@ -27,8 +29,6 @@ import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCSearch import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCStreamExtractor; import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCConferenceLinkHandlerFactory; import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCConferencesListLinkHandlerFactory; -import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCLiveListLinkHandlerFactory; -import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCRecentListLinkHandlerFactory; import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCSearchQueryHandlerFactory; import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCStreamLinkHandlerFactory; import org.schabi.newpipe.extractor.stream.StreamExtractor; @@ -47,12 +47,17 @@ public class MediaCCCService extends StreamingService { @Override public LinkHandlerFactory getStreamLHFactory() { - return new MediaCCCStreamLinkHandlerFactory(); + return MediaCCCStreamLinkHandlerFactory.getInstance(); } @Override public ListLinkHandlerFactory getChannelLHFactory() { - return new MediaCCCConferenceLinkHandlerFactory(); + return MediaCCCConferenceLinkHandlerFactory.getInstance(); + } + + @Override + public ListLinkHandlerFactory getChannelTabLHFactory() { + return null; } @Override @@ -62,7 +67,7 @@ public class MediaCCCService extends StreamingService { @Override public SearchQueryHandlerFactory getSearchQHFactory() { - return new MediaCCCSearchQueryHandlerFactory(); + return MediaCCCSearchQueryHandlerFactory.getInstance(); } @Override @@ -78,6 +83,22 @@ public class MediaCCCService extends StreamingService { return new MediaCCCConferenceExtractor(this, linkHandler); } + @Override + public ChannelTabExtractor getChannelTabExtractor(final ListLinkHandler linkHandler) { + if (linkHandler instanceof ReadyChannelTabListLinkHandler) { + return ((ReadyChannelTabListLinkHandler) linkHandler).getChannelTabExtractor(this); + } + + /* + Channel tab extractors are only supported in conferences and should only come from a + ReadyChannelTabListLinkHandler instance with a ChannelTabExtractorBuilder instance of the + conferences extractor + + If that's not the case, return null in this case, so no channel tabs support + */ + return null; + } + @Override public PlaylistExtractor getPlaylistExtractor(final ListLinkHandler linkHandler) { return null; @@ -91,36 +112,37 @@ public class MediaCCCService extends StreamingService { @Override public KioskList getKioskList() throws ExtractionException { final KioskList list = new KioskList(this); + final ListLinkHandlerFactory h = MediaCCCConferencesListLinkHandlerFactory.getInstance(); // add kiosks here e.g.: try { list.addKioskEntry( (streamingService, url, kioskId) -> new MediaCCCConferenceKiosk( MediaCCCService.this, - new MediaCCCConferencesListLinkHandlerFactory().fromUrl(url), + h.fromUrl(url), kioskId ), - new MediaCCCConferencesListLinkHandlerFactory(), + h, MediaCCCConferenceKiosk.KIOSK_ID ); list.addKioskEntry( (streamingService, url, kioskId) -> new MediaCCCRecentKiosk( MediaCCCService.this, - new MediaCCCRecentListLinkHandlerFactory().fromUrl(url), + h.fromUrl(url), kioskId ), - new MediaCCCRecentListLinkHandlerFactory(), + h, MediaCCCRecentKiosk.KIOSK_ID ); list.addKioskEntry( (streamingService, url, kioskId) -> new MediaCCCLiveStreamKiosk( MediaCCCService.this, - new MediaCCCLiveListLinkHandlerFactory().fromUrl(url), + h.fromUrl(url), kioskId ), - new MediaCCCLiveListLinkHandlerFactory(), + h, MediaCCCLiveStreamKiosk.KIOSK_ID ); 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 014affc96..48d85f7ca 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 @@ -1,23 +1,29 @@ package org.schabi.newpipe.extractor.services.media_ccc.extractors; -import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; + +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.tabs.ChannelTabExtractor; +import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs; 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.ListLinkHandler; +import org.schabi.newpipe.extractor.linkhandler.ReadyChannelTabListLinkHandler; import org.schabi.newpipe.extractor.services.media_ccc.extractors.infoItems.MediaCCCStreamInfoItemExtractor; import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCConferenceLinkHandlerFactory; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; + +import java.io.IOException; +import java.util.List; import javax.annotation.Nonnull; -import java.io.IOException; public class MediaCCCConferenceExtractor extends ChannelExtractor { private JsonObject conferenceData; @@ -74,18 +80,9 @@ public class MediaCCCConferenceExtractor extends ChannelExtractor { @Nonnull @Override - public InfoItemsPage getInitialPage() { - final StreamInfoItemsCollector collector = new StreamInfoItemsCollector(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(); + public List getTabs() throws ParsingException { + return List.of(new ReadyChannelTabListLinkHandler(getUrl(), getId(), + ChannelTabs.VIDEOS, new VideosTabExtractorBuilder(conferenceData))); } @Override @@ -105,4 +102,55 @@ public class MediaCCCConferenceExtractor extends ChannelExtractor { public String getName() throws ParsingException { return conferenceData.getString("title"); } + + private static final class VideosTabExtractorBuilder + implements ReadyChannelTabListLinkHandler.ChannelTabExtractorBuilder { + + private final JsonObject conferenceData; + + VideosTabExtractorBuilder(final JsonObject conferenceData) { + this.conferenceData = conferenceData; + } + + @Nonnull + @Override + public ChannelTabExtractor build(@Nonnull final StreamingService service, + @Nonnull final ListLinkHandler linkHandler) { + return new VideosChannelTabExtractor(service, linkHandler, conferenceData); + } + } + + private static final class VideosChannelTabExtractor extends ChannelTabExtractor { + private final JsonObject conferenceData; + + VideosChannelTabExtractor(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 ListExtractor.InfoItemsPage getInitialPage() { + final MultiInfoItemsCollector collector = + new MultiInfoItemsCollector(getServiceId()); + conferenceData.getArray("events") + .stream() + .filter(JsonObject.class::isInstance) + .map(JsonObject.class::cast) + .forEach(event -> collector.commit(new MediaCCCStreamInfoItemExtractor(event))); + 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/media_ccc/extractors/MediaCCCRecentKioskExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCRecentKioskExtractor.java index 1e18f8da1..cef496d9d 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCRecentKioskExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCRecentKioskExtractor.java @@ -65,7 +65,7 @@ public class MediaCCCRecentKioskExtractor implements StreamInfoItemExtractor { @Override public String getUploaderUrl() throws ParsingException { - return new MediaCCCConferenceLinkHandlerFactory() + return MediaCCCConferenceLinkHandlerFactory.getInstance() .fromUrl(event.getString("conference_url")) // API URL .getUrl(); // web URL } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCSearchExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCSearchExtractor.java index e9c300b8a..c4501f5c2 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCSearchExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCSearchExtractor.java @@ -38,7 +38,8 @@ public class MediaCCCSearchExtractor extends SearchExtractor { super(service, linkHandler); try { conferenceKiosk = new MediaCCCConferenceKiosk(service, - new MediaCCCConferencesListLinkHandlerFactory().fromId("conferences"), + MediaCCCConferencesListLinkHandlerFactory.getInstance() + .fromId("conferences"), "conferences"); } catch (final Exception e) { e.printStackTrace(); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCConferenceLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCConferenceLinkHandlerFactory.java index ddbd2e8e6..b6f88c331 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCConferenceLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCConferenceLinkHandlerFactory.java @@ -6,7 +6,11 @@ import org.schabi.newpipe.extractor.utils.Parser; import java.util.List; -public class MediaCCCConferenceLinkHandlerFactory extends ListLinkHandlerFactory { +public final class MediaCCCConferenceLinkHandlerFactory extends ListLinkHandlerFactory { + + private static final MediaCCCConferenceLinkHandlerFactory INSTANCE + = new MediaCCCConferenceLinkHandlerFactory(); + public static final String CONFERENCE_API_ENDPOINT = "https://api.media.ccc.de/public/conferences/"; public static final String CONFERENCE_PATH = "https://media.ccc.de/c/"; @@ -14,15 +18,23 @@ public class MediaCCCConferenceLinkHandlerFactory extends ListLinkHandlerFactory = "(?:(?:(?:api\\.)?media\\.ccc\\.de/public/conferences/)" + "|(?:media\\.ccc\\.de/[bc]/))([^/?&#]*)"; + private MediaCCCConferenceLinkHandlerFactory() { + } + + public static MediaCCCConferenceLinkHandlerFactory getInstance() { + return INSTANCE; + } + @Override public String getUrl(final String id, final List contentFilter, - final String sortFilter) throws ParsingException { + final String sortFilter) + throws ParsingException, UnsupportedOperationException { return CONFERENCE_PATH + id; } @Override - public String getId(final String url) throws ParsingException { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { return Parser.matchGroup1(ID_PATTERN, url); } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCConferencesListLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCConferencesListLinkHandlerFactory.java index f5dc8c6cf..f2b1e3b20 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCConferencesListLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCConferencesListLinkHandlerFactory.java @@ -5,15 +5,28 @@ import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; import java.util.List; -public class MediaCCCConferencesListLinkHandlerFactory extends ListLinkHandlerFactory { +public final class MediaCCCConferencesListLinkHandlerFactory extends ListLinkHandlerFactory { + + private static final MediaCCCConferencesListLinkHandlerFactory INSTANCE = + new MediaCCCConferencesListLinkHandlerFactory(); + + private MediaCCCConferencesListLinkHandlerFactory() { + } + + public static MediaCCCConferencesListLinkHandlerFactory getInstance() { + return INSTANCE; + } + @Override - public String getId(final String url) throws ParsingException { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { return "conferences"; } @Override - public String getUrl(final String id, final List contentFilter, - final String sortFilter) throws ParsingException { + public String getUrl(final String id, + final List contentFilter, + final String sortFilter) + throws ParsingException, UnsupportedOperationException { return "https://media.ccc.de/public/conferences"; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCLiveListLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCLiveListLinkHandlerFactory.java index f66e5c808..e92d2dfef 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCLiveListLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCLiveListLinkHandlerFactory.java @@ -6,11 +6,22 @@ import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; import java.util.List; import java.util.regex.Pattern; -public class MediaCCCLiveListLinkHandlerFactory extends ListLinkHandlerFactory { +public final class MediaCCCLiveListLinkHandlerFactory extends ListLinkHandlerFactory { + + private static final MediaCCCLiveListLinkHandlerFactory INSTANCE = + new MediaCCCLiveListLinkHandlerFactory(); + private static final String STREAM_PATTERN = "^(?:https?://)?media\\.ccc\\.de/live$"; + private MediaCCCLiveListLinkHandlerFactory() { + } + + public static MediaCCCLiveListLinkHandlerFactory getInstance() { + return INSTANCE; + } + @Override - public String getId(final String url) throws ParsingException { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { return "live"; } @@ -22,7 +33,8 @@ public class MediaCCCLiveListLinkHandlerFactory extends ListLinkHandlerFactory { @Override public String getUrl(final String id, final List contentFilter, - final String sortFilter) throws ParsingException { + final String sortFilter) + throws ParsingException, UnsupportedOperationException { // FIXME: wrong URL; should be https://streaming.media.ccc.de/{conference_slug}/{room_slug} return "https://media.ccc.de/live"; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCLiveStreamLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCLiveStreamLinkHandlerFactory.java deleted file mode 100644 index f7b0c1f18..000000000 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCLiveStreamLinkHandlerFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.schabi.newpipe.extractor.services.media_ccc.linkHandler; - -import org.schabi.newpipe.extractor.exceptions.ParsingException; -import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory; -import org.schabi.newpipe.extractor.utils.Parser; - -public class MediaCCCLiveStreamLinkHandlerFactory extends LinkHandlerFactory { - public static final String VIDEO_API_ENDPOINT = "https://api.media.ccc.de/public/events/"; - private static final String VIDEO_PATH = "https://streaming.media.ccc.de/v/"; - private static final String ID_PATTERN - = "(?:(?:(?:api\\.)?media\\.ccc\\.de/public/events/)" - + "|(?:media\\.ccc\\.de/v/))([^/?&#]*)"; - - @Override - public String getId(final String url) throws ParsingException { - return Parser.matchGroup1(ID_PATTERN, url); - } - - @Override - public String getUrl(final String id) throws ParsingException { - return VIDEO_PATH + id; - } - - @Override - public boolean onAcceptUrl(final String url) { - try { - return getId(url) != null; - } catch (final ParsingException e) { - return false; - } - } -} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCRecentListLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCRecentListLinkHandlerFactory.java index be2b10044..15b5ecf7d 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCRecentListLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCRecentListLinkHandlerFactory.java @@ -1,15 +1,27 @@ package org.schabi.newpipe.extractor.services.media_ccc.linkHandler; +import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; import java.util.List; import java.util.regex.Pattern; -public class MediaCCCRecentListLinkHandlerFactory extends ListLinkHandlerFactory { +public final class MediaCCCRecentListLinkHandlerFactory extends ListLinkHandlerFactory { + + private static final MediaCCCRecentListLinkHandlerFactory INSTANCE = + new MediaCCCRecentListLinkHandlerFactory(); + private static final String PATTERN = "^(https?://)?media\\.ccc\\.de/recent/?$"; + private MediaCCCRecentListLinkHandlerFactory() { + } + + public static MediaCCCRecentListLinkHandlerFactory getInstance() { + return INSTANCE; + } + @Override - public String getId(final String url) { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { return "recent"; } @@ -21,7 +33,8 @@ public class MediaCCCRecentListLinkHandlerFactory extends ListLinkHandlerFactory @Override public String getUrl(final String id, final List contentFilter, - final String sortFilter) { + final String sortFilter) + throws ParsingException, UnsupportedOperationException { return "https://media.ccc.de/recent"; } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCSearchQueryHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCSearchQueryHandlerFactory.java index 5a395dae6..3d9e76bfb 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCSearchQueryHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCSearchQueryHandlerFactory.java @@ -7,11 +7,22 @@ import org.schabi.newpipe.extractor.utils.Utils; import java.io.UnsupportedEncodingException; import java.util.List; -public class MediaCCCSearchQueryHandlerFactory extends SearchQueryHandlerFactory { +public final class MediaCCCSearchQueryHandlerFactory extends SearchQueryHandlerFactory { + + private static final MediaCCCSearchQueryHandlerFactory INSTANCE = + new MediaCCCSearchQueryHandlerFactory(); + public static final String ALL = "all"; public static final String CONFERENCES = "conferences"; public static final String EVENTS = "events"; + private MediaCCCSearchQueryHandlerFactory() { + } + + public static MediaCCCSearchQueryHandlerFactory getInstance() { + return INSTANCE; + } + @Override public String[] getAvailableContentFilter() { return new String[]{ @@ -27,8 +38,10 @@ public class MediaCCCSearchQueryHandlerFactory extends SearchQueryHandlerFactory } @Override - public String getUrl(final String query, final List contentFilter, - final String sortFilter) throws ParsingException { + public String getUrl(final String query, + final List contentFilter, + final String sortFilter) + throws ParsingException, UnsupportedOperationException { try { return "https://media.ccc.de/public/events/search?q=" + Utils.encodeUrlUtf8(query); } catch (final UnsupportedEncodingException e) { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCStreamLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCStreamLinkHandlerFactory.java index 3ae9c37d1..d433e69b5 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCStreamLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCStreamLinkHandlerFactory.java @@ -5,7 +5,11 @@ import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory; import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCParsingHelper; import org.schabi.newpipe.extractor.utils.Parser; -public class MediaCCCStreamLinkHandlerFactory extends LinkHandlerFactory { +public final class MediaCCCStreamLinkHandlerFactory extends LinkHandlerFactory { + + private static final MediaCCCStreamLinkHandlerFactory INSTANCE = + new MediaCCCStreamLinkHandlerFactory(); + public static final String VIDEO_API_ENDPOINT = "https://api.media.ccc.de/public/events/"; private static final String VIDEO_PATH = "https://media.ccc.de/v/"; private static final String RECORDING_ID_PATTERN @@ -15,8 +19,15 @@ public class MediaCCCStreamLinkHandlerFactory extends LinkHandlerFactory { private static final String LIVE_STREAM_ID_PATTERN = "streaming\\.media\\.ccc\\.de\\/(\\w+\\/\\w+)"; + private MediaCCCStreamLinkHandlerFactory() { + } + + public static MediaCCCStreamLinkHandlerFactory getInstance() { + return INSTANCE; + } + @Override - public String getId(final String url) throws ParsingException { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { String streamId = null; try { streamId = Parser.matchGroup1(LIVE_STREAM_ID_PATTERN, url); @@ -30,7 +41,7 @@ public class MediaCCCStreamLinkHandlerFactory extends LinkHandlerFactory { } @Override - public String getUrl(final String id) throws ParsingException { + public String getUrl(final String id) throws ParsingException, UnsupportedOperationException { if (MediaCCCParsingHelper.isLiveStreamId(id)) { return LIVE_STREAM_PATH + id; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeParsingHelper.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeParsingHelper.java index 260c3409a..b57aa6b88 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeParsingHelper.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeParsingHelper.java @@ -72,24 +72,29 @@ public final class PeertubeParsingHelper { } } - public static void collectStreamsFrom(final InfoItemsCollector collector, - final JsonObject json, - final String baseUrl) throws ParsingException { - collectStreamsFrom(collector, json, baseUrl, false); + public static void collectItemsFrom(final InfoItemsCollector collector, + final JsonObject json, + final String baseUrl) throws ParsingException { + collectItemsFrom(collector, json, baseUrl, false); } /** - * Collect stream from json with collector + * Collect items from the given JSON object with the given collector. + * + *

+ * Supported info item types are streams with their Sepia variant, channels and playlists. + *

* * @param collector the collector used to collect information - * @param json the file to retrieve data from - * @param baseUrl the base Url of the instance - * @param sepia if we should use PeertubeSepiaStreamInfoItemExtractor + * @param json the JSOn response to retrieve data from + * @param baseUrl the base URL of the instance + * @param sepia if we should use {@code PeertubeSepiaStreamInfoItemExtractor} to extract + * streams or {@code PeertubeStreamInfoItemExtractor} otherwise */ - public static void collectStreamsFrom(final InfoItemsCollector collector, - final JsonObject json, - final String baseUrl, - final boolean sepia) throws ParsingException { + public static void collectItemsFrom(final InfoItemsCollector collector, + final JsonObject json, + final String baseUrl, + final boolean sepia) throws ParsingException { final JsonArray contents; try { contents = (JsonArray) JsonUtils.getValue(json, "data"); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeService.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeService.java index de25e2799..ddd9d5395 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeService.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeService.java @@ -6,6 +6,7 @@ import static java.util.Arrays.asList; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.channel.ChannelExtractor; +import org.schabi.newpipe.extractor.channel.tabs.ChannelTabExtractor; import org.schabi.newpipe.extractor.comments.CommentsExtractor; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.kiosk.KioskList; @@ -19,6 +20,7 @@ import org.schabi.newpipe.extractor.playlist.PlaylistExtractor; import org.schabi.newpipe.extractor.search.SearchExtractor; import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubeAccountExtractor; import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubeChannelExtractor; +import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubeChannelTabExtractor; import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubeCommentsExtractor; import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubePlaylistExtractor; import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubeSearchExtractor; @@ -26,6 +28,7 @@ import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubeStreamE import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubeSuggestionExtractor; import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubeTrendingExtractor; import org.schabi.newpipe.extractor.services.peertube.linkHandler.PeertubeChannelLinkHandlerFactory; +import org.schabi.newpipe.extractor.services.peertube.linkHandler.PeertubeChannelTabLinkHandlerFactory; import org.schabi.newpipe.extractor.services.peertube.linkHandler.PeertubeCommentsLinkHandlerFactory; import org.schabi.newpipe.extractor.services.peertube.linkHandler.PeertubePlaylistLinkHandlerFactory; import org.schabi.newpipe.extractor.services.peertube.linkHandler.PeertubeSearchQueryHandlerFactory; @@ -60,6 +63,11 @@ public class PeertubeService extends StreamingService { return PeertubeChannelLinkHandlerFactory.getInstance(); } + @Override + public ListLinkHandlerFactory getChannelTabLHFactory() { + return PeertubeChannelTabLinkHandlerFactory.getInstance(); + } + @Override public ListLinkHandlerFactory getPlaylistLHFactory() { return PeertubePlaylistLinkHandlerFactory.getInstance(); @@ -103,6 +111,12 @@ public class PeertubeService extends StreamingService { } } + @Override + public ChannelTabExtractor getChannelTabExtractor(final ListLinkHandler linkHandler) + throws ExtractionException { + return new PeertubeChannelTabExtractor(this, linkHandler); + } + @Override public PlaylistExtractor getPlaylistExtractor(final ListLinkHandler linkHandler) throws ExtractionException { @@ -136,17 +150,20 @@ public class PeertubeService extends StreamingService { @Override public KioskList getKioskList() throws ExtractionException { + final PeertubeTrendingLinkHandlerFactory h = + PeertubeTrendingLinkHandlerFactory.getInstance(); + final KioskList.KioskExtractorFactory kioskFactory = (streamingService, url, id) -> new PeertubeTrendingExtractor( PeertubeService.this, - new PeertubeTrendingLinkHandlerFactory().fromId(id), + h.fromId(id), id ); final KioskList list = new KioskList(this); // add kiosks here e.g.: - final PeertubeTrendingLinkHandlerFactory h = new PeertubeTrendingLinkHandlerFactory(); + try { list.addKioskEntry(kioskFactory, h, PeertubeTrendingLinkHandlerFactory.KIOSK_TRENDING); list.addKioskEntry(kioskFactory, h, @@ -160,6 +177,4 @@ public class PeertubeService extends StreamingService { return list; } - - } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeAccountExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeAccountExtractor.java index 6a8c2dcf2..eb95dcbe9 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeAccountExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeAccountExtractor.java @@ -4,31 +4,23 @@ import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; -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.tabs.ChannelTabs; import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.downloader.Response; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; -import org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper; import org.schabi.newpipe.extractor.services.peertube.linkHandler.PeertubeChannelLinkHandlerFactory; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; +import org.schabi.newpipe.extractor.services.peertube.linkHandler.PeertubeChannelTabLinkHandlerFactory; import org.schabi.newpipe.extractor.utils.JsonUtils; -import org.schabi.newpipe.extractor.utils.Utils; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.IOException; - -import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.COUNT_KEY; -import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.ITEMS_PER_PAGE; -import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.START_KEY; -import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.collectStreamsFrom; -import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; +import java.util.List; public class PeertubeAccountExtractor extends ChannelExtractor { private JsonObject json; @@ -119,54 +111,19 @@ public class PeertubeAccountExtractor extends ChannelExtractor { @Nonnull @Override - public InfoItemsPage getInitialPage() throws IOException, ExtractionException { - return getPage(new Page(baseUrl + "/api/v1/" + getId() + "/videos?" + START_KEY + "=0&" - + COUNT_KEY + "=" + ITEMS_PER_PAGE)); - } - - @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 Response response = getDownloader().get(page.getUrl()); - - JsonObject pageJson = null; - if (response != null && !Utils.isBlank(response.responseBody())) { - try { - pageJson = JsonParser.object().from(response.responseBody()); - } catch (final Exception e) { - throw new ParsingException("Could not parse json data for account info", e); - } - } - - if (pageJson != null) { - PeertubeParsingHelper.validate(pageJson); - final long total = pageJson.getLong("total"); - - final StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId()); - collectStreamsFrom(collector, pageJson, getBaseUrl()); - - return new InfoItemsPage<>(collector, - PeertubeParsingHelper.getNextPage(page.getUrl(), total)); - } else { - throw new ExtractionException("Unable to get PeerTube account info"); - } + public List getTabs() throws ParsingException { + return List.of( + PeertubeChannelTabLinkHandlerFactory.getInstance().fromQuery(getId(), + List.of(ChannelTabs.VIDEOS), "", getBaseUrl()), + PeertubeChannelTabLinkHandlerFactory.getInstance().fromQuery(getId(), + List.of(ChannelTabs.CHANNELS), "", getBaseUrl())); } @Override public void onFetchPage(@Nonnull final Downloader downloader) throws IOException, ExtractionException { - String accountUrl = baseUrl + PeertubeChannelLinkHandlerFactory.API_ENDPOINT; - if (getId().contains(ACCOUNTS)) { - accountUrl += getId(); - } else { - accountUrl += ACCOUNTS + getId(); - } - - final Response response = downloader.get(accountUrl); + final Response response = downloader.get(baseUrl + + PeertubeChannelLinkHandlerFactory.API_ENDPOINT + getId()); if (response != null) { setInitialData(response.responseBody()); } else { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelExtractor.java index f2a7b07e2..e7de3f061 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelExtractor.java @@ -3,30 +3,22 @@ package org.schabi.newpipe.extractor.services.peertube.extractors; import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; -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.tabs.ChannelTabs; import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.downloader.Response; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; -import org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper; import org.schabi.newpipe.extractor.services.peertube.linkHandler.PeertubeChannelLinkHandlerFactory; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; +import org.schabi.newpipe.extractor.services.peertube.linkHandler.PeertubeChannelTabLinkHandlerFactory; import org.schabi.newpipe.extractor.utils.JsonUtils; -import org.schabi.newpipe.extractor.utils.Utils; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.IOException; - -import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.COUNT_KEY; -import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.ITEMS_PER_PAGE; -import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.START_KEY; -import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.collectStreamsFrom; -import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; +import java.util.List; public class PeertubeChannelExtractor extends ChannelExtractor { private JsonObject json; @@ -98,41 +90,12 @@ public class PeertubeChannelExtractor extends ChannelExtractor { @Nonnull @Override - public InfoItemsPage getInitialPage() throws IOException, ExtractionException { - return getPage(new Page(baseUrl + "/api/v1/" + getId() + "/videos?" + START_KEY + "=0&" - + COUNT_KEY + "=" + ITEMS_PER_PAGE)); - } - - @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 Response response = getDownloader().get(page.getUrl()); - - JsonObject pageJson = null; - if (response != null && !Utils.isBlank(response.responseBody())) { - try { - pageJson = JsonParser.object().from(response.responseBody()); - } catch (final Exception e) { - throw new ParsingException("Could not parse json data for channel info", e); - } - } - - if (pageJson != null) { - PeertubeParsingHelper.validate(pageJson); - final long total = pageJson.getLong("total"); - - final StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId()); - collectStreamsFrom(collector, pageJson, getBaseUrl()); - - return new InfoItemsPage<>(collector, - PeertubeParsingHelper.getNextPage(page.getUrl(), total)); - } else { - throw new ExtractionException("Unable to get PeerTube channel info"); - } + public List getTabs() throws ParsingException { + return List.of( + PeertubeChannelTabLinkHandlerFactory.getInstance().fromQuery(getId(), + List.of(ChannelTabs.VIDEOS), "", getBaseUrl()), + PeertubeChannelTabLinkHandlerFactory.getInstance().fromQuery(getId(), + List.of(ChannelTabs.PLAYLISTS), "", getBaseUrl())); } @Override diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelInfoItemExtractor.java index 3ab1be539..0faa25ea8 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelInfoItemExtractor.java @@ -1,7 +1,7 @@ package org.schabi.newpipe.extractor.services.peertube.extractors; import com.grack.nanojson.JsonObject; -import org.schabi.newpipe.extractor.channel.ChannelExtractor; +import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor; import org.schabi.newpipe.extractor.exceptions.ParsingException; @@ -52,7 +52,7 @@ public class PeertubeChannelInfoItemExtractor implements ChannelInfoItemExtracto @Override public long getStreamCount() throws ParsingException { - return ChannelExtractor.ITEM_COUNT_UNKNOWN; + return ListExtractor.ITEM_COUNT_UNKNOWN; } @Override diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelTabExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelTabExtractor.java new file mode 100644 index 000000000..fe8462bf8 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelTabExtractor.java @@ -0,0 +1,80 @@ +package org.schabi.newpipe.extractor.services.peertube.extractors; + +import com.grack.nanojson.JsonObject; +import com.grack.nanojson.JsonParser; +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.tabs.ChannelTabExtractor; +import org.schabi.newpipe.extractor.downloader.Downloader; +import org.schabi.newpipe.extractor.downloader.Response; +import org.schabi.newpipe.extractor.exceptions.ExtractionException; +import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; +import org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper; +import org.schabi.newpipe.extractor.services.peertube.linkHandler.PeertubeChannelLinkHandlerFactory; +import org.schabi.newpipe.extractor.utils.Utils; + +import javax.annotation.Nonnull; +import java.io.IOException; + +import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.COUNT_KEY; +import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.ITEMS_PER_PAGE; +import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.START_KEY; +import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.collectItemsFrom; +import static org.schabi.newpipe.extractor.services.peertube.linkHandler.PeertubeChannelTabLinkHandlerFactory.getUrlSuffix; +import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; + +public class PeertubeChannelTabExtractor extends ChannelTabExtractor { + private final String baseUrl; + + public PeertubeChannelTabExtractor(final StreamingService service, + final ListLinkHandler linkHandler) + throws ParsingException { + super(service, linkHandler); + baseUrl = getBaseUrl(); + } + + @Override + public void onFetchPage(@Nonnull final Downloader downloader) { + } + + @Nonnull + @Override + public InfoItemsPage getInitialPage() throws IOException, ExtractionException { + return getPage(new Page(baseUrl + PeertubeChannelLinkHandlerFactory.API_ENDPOINT + + getId() + getUrlSuffix(getName()) + "?" + START_KEY + "=0&" + COUNT_KEY + "=" + + ITEMS_PER_PAGE)); + } + + @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 Response response = getDownloader().get(page.getUrl()); + + JsonObject pageJson = null; + if (response != null && !Utils.isBlank(response.responseBody())) { + try { + pageJson = JsonParser.object().from(response.responseBody()); + } catch (final Exception e) { + throw new ParsingException("Could not parse json data for account info", e); + } + } + + if (pageJson == null) { + throw new ExtractionException("Unable to get account channel list"); + } + PeertubeParsingHelper.validate(pageJson); + + final MultiInfoItemsCollector collector = new MultiInfoItemsCollector(getServiceId()); + collectItemsFrom(collector, pageJson, getBaseUrl()); + + return new InfoItemsPage<>(collector, + PeertubeParsingHelper.getNextPage(page.getUrl(), pageJson.getLong("total"))); + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubePlaylistExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubePlaylistExtractor.java index 3d4ff9d19..a950375f0 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubePlaylistExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubePlaylistExtractor.java @@ -23,7 +23,7 @@ import java.io.IOException; import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.COUNT_KEY; import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.ITEMS_PER_PAGE; import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.START_KEY; -import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.collectStreamsFrom; +import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.collectItemsFrom; import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; public class PeertubePlaylistExtractor extends PlaylistExtractor { @@ -125,7 +125,7 @@ public class PeertubePlaylistExtractor extends PlaylistExtractor { final long total = json.getLong("total"); final StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId()); - collectStreamsFrom(collector, json, getBaseUrl()); + collectItemsFrom(collector, json, getBaseUrl()); return new InfoItemsPage<>(collector, PeertubeParsingHelper.getNextPage(page.getUrl(), total)); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeSearchExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeSearchExtractor.java index 8be07855d..5f7ac45d4 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeSearchExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeSearchExtractor.java @@ -26,7 +26,7 @@ import javax.annotation.Nonnull; import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.COUNT_KEY; import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.ITEMS_PER_PAGE; import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.START_KEY; -import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.collectStreamsFrom; +import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.collectItemsFrom; import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; public class PeertubeSearchExtractor extends SearchExtractor { @@ -93,7 +93,7 @@ public class PeertubeSearchExtractor extends SearchExtractor { final long total = json.getLong("total"); final MultiInfoItemsCollector collector = new MultiInfoItemsCollector(getServiceId()); - collectStreamsFrom(collector, json, getBaseUrl(), sepia); + collectItemsFrom(collector, json, getBaseUrl(), sepia); return new InfoItemsPage<>(collector, PeertubeParsingHelper.getNextPage(page.getUrl(), total)); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeTrendingExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeTrendingExtractor.java index 2baca78ad..df4e4b7ea 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeTrendingExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeTrendingExtractor.java @@ -23,7 +23,7 @@ import javax.annotation.Nonnull; import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.COUNT_KEY; import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.ITEMS_PER_PAGE; import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.START_KEY; -import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.collectStreamsFrom; +import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.collectItemsFrom; import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; public class PeertubeTrendingExtractor extends KioskExtractor { @@ -69,7 +69,7 @@ public class PeertubeTrendingExtractor extends KioskExtractor { final long total = json.getLong("total"); final StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId()); - collectStreamsFrom(collector, json, getBaseUrl()); + collectItemsFrom(collector, json, getBaseUrl()); return new InfoItemsPage<>(collector, PeertubeParsingHelper.getNextPage(page.getUrl(), total)); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeChannelLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeChannelLinkHandlerFactory.java index 57a15d16d..8d858f89d 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeChannelLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeChannelLinkHandlerFactory.java @@ -22,14 +22,15 @@ public final class PeertubeChannelLinkHandlerFactory extends ListLinkHandlerFact } @Override - public String getId(final String url) throws ParsingException { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { return fixId(Parser.matchGroup(ID_PATTERN, url, 0)); } @Override public String getUrl(final String id, final List contentFilters, - final String searchFilter) throws ParsingException { + final String searchFilter) + throws ParsingException, UnsupportedOperationException { return getUrl(id, contentFilters, searchFilter, ServiceList.PeerTube.getBaseUrl()); } @@ -38,7 +39,7 @@ public final class PeertubeChannelLinkHandlerFactory extends ListLinkHandlerFact final List contentFilter, final String sortFilter, final String baseUrl) - throws ParsingException { + throws ParsingException, UnsupportedOperationException { if (id.matches(ID_PATTERN)) { return baseUrl + "/" + fixId(id); } else { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeChannelTabLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeChannelTabLinkHandlerFactory.java new file mode 100644 index 000000000..b924e1ac7 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeChannelTabLinkHandlerFactory.java @@ -0,0 +1,71 @@ +package org.schabi.newpipe.extractor.services.peertube.linkHandler; + +import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs; +import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.exceptions.UnsupportedTabException; +import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; + +import javax.annotation.Nonnull; +import java.util.List; + +public final class PeertubeChannelTabLinkHandlerFactory extends ListLinkHandlerFactory { + private static final PeertubeChannelTabLinkHandlerFactory INSTANCE + = new PeertubeChannelTabLinkHandlerFactory(); + + private PeertubeChannelTabLinkHandlerFactory() { + } + + public static PeertubeChannelTabLinkHandlerFactory getInstance() { + return INSTANCE; + } + + @Nonnull + public static String getUrlSuffix(@Nonnull final String tab) + throws UnsupportedTabException { + switch (tab) { + case ChannelTabs.VIDEOS: + return "/videos"; + case ChannelTabs.CHANNELS: // only available on accounts + return "/video-channels"; + case ChannelTabs.PLAYLISTS: // only available on channels + return "/video-playlists"; + } + throw new UnsupportedTabException(tab); + } + + @Override + public String getId(final String url) throws ParsingException, UnsupportedOperationException { + return PeertubeChannelLinkHandlerFactory.getInstance().getId(url); + } + + @Override + public String getUrl(final String id, final List contentFilter, final String sortFilter) + throws ParsingException, UnsupportedOperationException { + return PeertubeChannelLinkHandlerFactory.getInstance().getUrl(id) + + getUrlSuffix(contentFilter.get(0)); + } + + @Override + public String getUrl(final String id, + final List contentFilter, + final String sortFilter, + final String baseUrl) + throws ParsingException, UnsupportedOperationException { + return PeertubeChannelLinkHandlerFactory.getInstance().getUrl(id, null, null, baseUrl) + + getUrlSuffix(contentFilter.get(0)); + } + + @Override + public boolean onAcceptUrl(final String url) throws ParsingException { + return PeertubeChannelLinkHandlerFactory.getInstance().onAcceptUrl(url); + } + + @Override + public String[] getAvailableContentFilter() { + return new String[] { + ChannelTabs.VIDEOS, + ChannelTabs.CHANNELS, + ChannelTabs.PLAYLISTS, + }; + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeCommentsLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeCommentsLinkHandlerFactory.java index 366b0a159..816bcb183 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeCommentsLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeCommentsLinkHandlerFactory.java @@ -21,7 +21,7 @@ public final class PeertubeCommentsLinkHandlerFactory extends ListLinkHandlerFac } @Override - public String getId(final String url) throws ParsingException, IllegalArgumentException { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { return PeertubeStreamLinkHandlerFactory.getInstance().getId(url); // the same id is needed } @@ -33,7 +33,8 @@ public final class PeertubeCommentsLinkHandlerFactory extends ListLinkHandlerFac @Override public String getUrl(final String id, final List contentFilter, - final String sortFilter) throws ParsingException { + final String sortFilter) + throws ParsingException, UnsupportedOperationException { return getUrl(id, contentFilter, sortFilter, ServiceList.PeerTube.getBaseUrl()); } @@ -41,7 +42,8 @@ public final class PeertubeCommentsLinkHandlerFactory extends ListLinkHandlerFac public String getUrl(final String id, final List contentFilter, final String sortFilter, - final String baseUrl) throws ParsingException { + final String baseUrl) + throws ParsingException, UnsupportedOperationException { return baseUrl + String.format(COMMENTS_ENDPOINT, id); } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubePlaylistLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubePlaylistLinkHandlerFactory.java index a5318e581..c6183b140 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubePlaylistLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubePlaylistLinkHandlerFactory.java @@ -25,7 +25,8 @@ public final class PeertubePlaylistLinkHandlerFactory extends ListLinkHandlerFac @Override public String getUrl(final String id, final List contentFilters, - final String sortFilter) { + final String sortFilter) + throws ParsingException, UnsupportedOperationException { return getUrl(id, contentFilters, sortFilter, ServiceList.PeerTube.getBaseUrl()); } @@ -33,12 +34,13 @@ public final class PeertubePlaylistLinkHandlerFactory extends ListLinkHandlerFac public String getUrl(final String id, final List contentFilters, final String sortFilter, - final String baseUrl) { + final String baseUrl) + throws ParsingException, UnsupportedOperationException { return baseUrl + "/api/v1/video-playlists/" + id; } @Override - public String getId(final String url) throws ParsingException { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { try { return Parser.matchGroup(ID_PATTERN, url, 2); } catch (final ParsingException ignored) { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeSearchQueryHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeSearchQueryHandlerFactory.java index db9dfe38c..6e1354665 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeSearchQueryHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeSearchQueryHandlerFactory.java @@ -10,6 +10,9 @@ import java.util.List; public final class PeertubeSearchQueryHandlerFactory extends SearchQueryHandlerFactory { + private static final PeertubeSearchQueryHandlerFactory INSTANCE = + new PeertubeSearchQueryHandlerFactory(); + public static final String VIDEOS = "videos"; public static final String SEPIA_VIDEOS = "sepia_videos"; // sepia is the global index public static final String PLAYLISTS = "playlists"; @@ -23,13 +26,14 @@ public final class PeertubeSearchQueryHandlerFactory extends SearchQueryHandlerF } public static PeertubeSearchQueryHandlerFactory getInstance() { - return new PeertubeSearchQueryHandlerFactory(); + return INSTANCE; } @Override public String getUrl(final String searchString, final List contentFilters, - final String sortFilter) throws ParsingException { + final String sortFilter) + throws ParsingException, UnsupportedOperationException { final String baseUrl; if (!contentFilters.isEmpty() && contentFilters.get(0).startsWith("sepia_")) { baseUrl = SEPIA_BASE_URL; @@ -43,7 +47,8 @@ public final class PeertubeSearchQueryHandlerFactory extends SearchQueryHandlerF public String getUrl(final String searchString, final List contentFilters, final String sortFilter, - final String baseUrl) throws ParsingException { + final String baseUrl) + throws ParsingException, UnsupportedOperationException { try { final String endpoint; if (contentFilters.isEmpty() diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeStreamLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeStreamLinkHandlerFactory.java index aee042a03..6bc2ffa12 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeStreamLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeStreamLinkHandlerFactory.java @@ -27,7 +27,7 @@ public final class PeertubeStreamLinkHandlerFactory extends LinkHandlerFactory { } @Override - public String getUrl(final String id) { + public String getUrl(final String id) throws ParsingException, UnsupportedOperationException { return getUrl(id, ServiceList.PeerTube.getBaseUrl()); } @@ -37,7 +37,7 @@ public final class PeertubeStreamLinkHandlerFactory extends LinkHandlerFactory { } @Override - public String getId(final String url) throws ParsingException, IllegalArgumentException { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { return Parser.matchGroup(ID_PATTERN, url, 4); } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeTrendingLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeTrendingLinkHandlerFactory.java index bded13ff2..cb58af4ed 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeTrendingLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeTrendingLinkHandlerFactory.java @@ -23,6 +23,9 @@ public final class PeertubeTrendingLinkHandlerFactory extends ListLinkHandlerFac KIOSK_RECENT, "%s/api/v1/videos?sort=-publishedAt", KIOSK_LOCAL, "%s/api/v1/videos?sort=-publishedAt&filter=local"); + private PeertubeTrendingLinkHandlerFactory() { + } + public static PeertubeTrendingLinkHandlerFactory getInstance() { return INSTANCE; } @@ -30,7 +33,8 @@ public final class PeertubeTrendingLinkHandlerFactory extends ListLinkHandlerFac @Override public String getUrl(final String id, final List contentFilters, - final String sortFilter) { + final String sortFilter) + throws ParsingException, UnsupportedOperationException { return getUrl(id, contentFilters, sortFilter, ServiceList.PeerTube.getBaseUrl()); } @@ -38,12 +42,13 @@ public final class PeertubeTrendingLinkHandlerFactory extends ListLinkHandlerFac public String getUrl(final String id, final List contentFilters, final String sortFilter, - final String baseUrl) { + final String baseUrl) + throws ParsingException, UnsupportedOperationException { return String.format(KIOSK_MAP.get(id), baseUrl); } @Override - public String getId(final String url) throws ParsingException { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { final String cleanUrl = url.replace(ServiceList.PeerTube.getBaseUrl(), "%s"); if (cleanUrl.contains("/videos/trending")) { return KIOSK_TRENDING;