From 6f7d1f079f6c4057c90729338d50b3433b9f4ebc Mon Sep 17 00:00:00 2001 From: AudricV <74829229+AudricV@users.noreply.github.com> Date: Thu, 29 Jun 2023 21:52:24 +0200 Subject: [PATCH] [Bandcamp] Add tabs support for artists Support of tracks and albums has been added for artists. Also use the singleton pattern and add the declaration of the UnsupportedOperationException exception to the service's LinkHandlers and improved some code in the files changed. Co-authored-by: ThetaDev Co-authored-by: Stypox --- .../services/bandcamp/BandcampService.java | 38 ++++++-- .../BandcampAlbumInfoItemExtractor.java | 55 +++++++++++ .../extractors/BandcampChannelExtractor.java | 79 +++++++++++---- .../BandcampChannelTabExtractor.java | 95 +++++++++++++++++++ .../BandcampChannelLinkHandlerFactory.java | 44 +++++---- .../BandcampChannelTabLinkHandlerFactory.java | 72 ++++++++++++++ .../BandcampCommentsLinkHandlerFactory.java | 17 +++- .../BandcampFeaturedLinkHandlerFactory.java | 18 +++- .../BandcampPlaylistLinkHandlerFactory.java | 18 +++- .../BandcampSearchQueryHandlerFactory.java | 16 +++- .../BandcampStreamLinkHandlerFactory.java | 17 +++- 11 files changed, 405 insertions(+), 64 deletions(-) create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampAlbumInfoItemExtractor.java create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampChannelTabExtractor.java create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampChannelTabLinkHandlerFactory.java diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/BandcampService.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/BandcampService.java index 8b2758796..92e171d65 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/BandcampService.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/BandcampService.java @@ -12,6 +12,7 @@ import static org.schabi.newpipe.extractor.services.bandcamp.extractors.Bandcamp 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,11 +20,13 @@ 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; import org.schabi.newpipe.extractor.search.SearchExtractor; import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampChannelExtractor; +import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampChannelTabExtractor; import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampCommentsExtractor; import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper; import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampFeaturedExtractor; @@ -34,6 +37,7 @@ import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampSearchE import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampStreamExtractor; import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampSuggestionExtractor; import org.schabi.newpipe.extractor.services.bandcamp.linkHandler.BandcampChannelLinkHandlerFactory; +import org.schabi.newpipe.extractor.services.bandcamp.linkHandler.BandcampChannelTabLinkHandlerFactory; import org.schabi.newpipe.extractor.services.bandcamp.linkHandler.BandcampCommentsLinkHandlerFactory; import org.schabi.newpipe.extractor.services.bandcamp.linkHandler.BandcampFeaturedLinkHandlerFactory; import org.schabi.newpipe.extractor.services.bandcamp.linkHandler.BandcampPlaylistLinkHandlerFactory; @@ -58,27 +62,32 @@ public class BandcampService extends StreamingService { @Override public LinkHandlerFactory getStreamLHFactory() { - return new BandcampStreamLinkHandlerFactory(); + return BandcampStreamLinkHandlerFactory.getInstance(); } @Override public ListLinkHandlerFactory getChannelLHFactory() { - return new BandcampChannelLinkHandlerFactory(); + return BandcampChannelLinkHandlerFactory.getInstance(); + } + + @Override + public ListLinkHandlerFactory getChannelTabLHFactory() { + return BandcampChannelTabLinkHandlerFactory.getInstance(); } @Override public ListLinkHandlerFactory getPlaylistLHFactory() { - return new BandcampPlaylistLinkHandlerFactory(); + return BandcampPlaylistLinkHandlerFactory.getInstance(); } @Override public SearchQueryHandlerFactory getSearchQHFactory() { - return new BandcampSearchQueryHandlerFactory(); + return BandcampSearchQueryHandlerFactory.getInstance(); } @Override public ListLinkHandlerFactory getCommentsLHFactory() { - return new BandcampCommentsLinkHandlerFactory(); + return BandcampCommentsLinkHandlerFactory.getInstance(); } @Override @@ -98,27 +107,27 @@ public class BandcampService extends StreamingService { @Override public KioskList getKioskList() throws ExtractionException { - final KioskList kioskList = new KioskList(this); + final ListLinkHandlerFactory h = BandcampFeaturedLinkHandlerFactory.getInstance(); try { kioskList.addKioskEntry( (streamingService, url, kioskId) -> new BandcampFeaturedExtractor( BandcampService.this, - new BandcampFeaturedLinkHandlerFactory().fromUrl(FEATURED_API_URL), + h.fromUrl(FEATURED_API_URL), kioskId ), - new BandcampFeaturedLinkHandlerFactory(), + h, KIOSK_FEATURED ); kioskList.addKioskEntry( (streamingService, url, kioskId) -> new BandcampRadioExtractor( BandcampService.this, - new BandcampFeaturedLinkHandlerFactory().fromUrl(RADIO_API_URL), + h.fromUrl(RADIO_API_URL), kioskId ), - new BandcampFeaturedLinkHandlerFactory(), + h, KIOSK_RADIO ); @@ -136,6 +145,15 @@ public class BandcampService extends StreamingService { return new BandcampChannelExtractor(this, linkHandler); } + @Override + public ChannelTabExtractor getChannelTabExtractor(final ListLinkHandler linkHandler) { + if (linkHandler instanceof ReadyChannelTabListLinkHandler) { + return ((ReadyChannelTabListLinkHandler) linkHandler).getChannelTabExtractor(this); + } else { + return new BandcampChannelTabExtractor(this, linkHandler); + } + } + @Override public PlaylistExtractor getPlaylistExtractor(final ListLinkHandler linkHandler) { return new BandcampPlaylistExtractor(this, linkHandler); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampAlbumInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampAlbumInfoItemExtractor.java new file mode 100644 index 000000000..3f41ea047 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampAlbumInfoItemExtractor.java @@ -0,0 +1,55 @@ +package org.schabi.newpipe.extractor.services.bandcamp.extractors; + +import com.grack.nanojson.JsonObject; +import org.schabi.newpipe.extractor.ListExtractor; +import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.playlist.PlaylistInfoItemExtractor; + +public class BandcampAlbumInfoItemExtractor implements PlaylistInfoItemExtractor { + private final JsonObject albumInfoItem; + private final String uploaderUrl; + + public BandcampAlbumInfoItemExtractor(final JsonObject albumInfoItem, + final String uploaderUrl) { + this.albumInfoItem = albumInfoItem; + this.uploaderUrl = uploaderUrl; + } + + @Override + public String getName() throws ParsingException { + return albumInfoItem.getString("title"); + } + + @Override + public String getUrl() throws ParsingException { + return BandcampExtractorHelper.getStreamUrlFromIds( + albumInfoItem.getLong("band_id"), + albumInfoItem.getLong("item_id"), + albumInfoItem.getString("item_type")); + } + + @Override + public String getThumbnailUrl() throws ParsingException { + return BandcampExtractorHelper.getImageUrl(albumInfoItem.getLong("art_id"), true); + } + + @Override + public String getUploaderName() throws ParsingException { + return albumInfoItem.getString("band_name"); + } + + @Override + public String getUploaderUrl() { + return uploaderUrl; + } + + @Override + public boolean isUploaderVerified() { + return false; + } + + @Override + public long getStreamCount() { + return ListExtractor.ITEM_COUNT_UNKNOWN; + } +} 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 80e7ba27e..dc2f98407 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,19 +8,22 @@ import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; import org.jsoup.Jsoup; -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.downloader.Downloader; 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.channel.tabs.ChannelTabs; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; -import org.schabi.newpipe.extractor.services.bandcamp.extractors.streaminfoitem.BandcampDiscographStreamInfoItemExtractor; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; +import org.schabi.newpipe.extractor.linkhandler.ReadyChannelTabListLinkHandler; +import org.schabi.newpipe.extractor.services.bandcamp.linkHandler.BandcampChannelTabLinkHandlerFactory; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Objects; import java.util.stream.Stream; @@ -52,8 +55,8 @@ public class BandcampChannelExtractor extends ChannelExtractor { */ try { final String html = getDownloader() - .get(replaceHttpWithHttps(channelInfo.getString("bandcamp_url"))) - .responseBody(); + .get(replaceHttpWithHttps(channelInfo.getString("bandcamp_url"))) + .responseBody(); return Stream.of(Jsoup.parse(html).getElementById("customHeader")) .filter(Objects::nonNull) @@ -107,29 +110,47 @@ public class BandcampChannelExtractor extends ChannelExtractor { @Nonnull @Override - public InfoItemsPage getInitialPage() throws ParsingException { - - final StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId()); - + public List getTabs() throws ParsingException { final JsonArray discography = channelInfo.getArray("discography"); + final TabExtractorBuilder builder = new TabExtractorBuilder(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); + final List tabs = new ArrayList<>(); - if (!discograph.getString("item_type").equals("track")) { + boolean foundTrackItem = false; + boolean foundAlbumItem = false; + + for (final Object discographyItem : discography) { + if (foundTrackItem && foundAlbumItem) { + break; + } + + if (!(discographyItem instanceof JsonObject)) { continue; } - collector.commit(new BandcampDiscographStreamInfoItemExtractor(discograph, getUrl())); + final JsonObject discographyJsonItem = (JsonObject) discographyItem; + final String itemType = discographyJsonItem.getString("item_type"); + + if (!foundTrackItem && "track".equals(itemType)) { + foundTrackItem = true; + tabs.add(new ReadyChannelTabListLinkHandler(getUrl() + + BandcampChannelTabLinkHandlerFactory.getUrlSuffix(ChannelTabs.TRACKS), + getId(), + ChannelTabs.TRACKS, + builder)); + } + + if (!foundAlbumItem && "album".equals(itemType)) { + foundAlbumItem = true; + tabs.add(new ReadyChannelTabListLinkHandler(getUrl() + + BandcampChannelTabLinkHandlerFactory.getUrlSuffix(ChannelTabs.ALBUMS), + getId(), + ChannelTabs.ALBUMS, + builder)); + } } - return new InfoItemsPage<>(collector, null); - } - - @Override - public InfoItemsPage getPage(final Page page) { - return null; + return Collections.unmodifiableList(tabs); } @Override @@ -143,4 +164,20 @@ public class BandcampChannelExtractor extends ChannelExtractor { public String getName() { return channelInfo.getString("name"); } + + private static final class TabExtractorBuilder + implements ReadyChannelTabListLinkHandler.ChannelTabExtractorBuilder { + private final JsonArray discography; + + TabExtractorBuilder(final JsonArray discography) { + this.discography = discography; + } + + @Nonnull + @Override + public ChannelTabExtractor build(@Nonnull final StreamingService service, + @Nonnull 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 new file mode 100644 index 000000000..b4110e9e9 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampChannelTabExtractor.java @@ -0,0 +1,95 @@ +package org.schabi.newpipe.extractor.services.bandcamp.extractors; + +import com.grack.nanojson.JsonArray; +import com.grack.nanojson.JsonObject; +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.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.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); + + 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) throws ParsingException { + if (discography == null) { + discography = BandcampExtractorHelper.getArtistDetails(getId()) + .getArray("discography"); + } + } + + @Nonnull + @Override + public InfoItemsPage getInitialPage() throws IOException, ExtractionException { + final MultiInfoItemsCollector collector = new MultiInfoItemsCollector(getServiceId()); + + for (final Object discograph : discography) { + // A discograph is as an item appears in a discography + if (!(discograph instanceof JsonObject)) { + continue; + } + + final JsonObject discographJsonObject = (JsonObject) discograph; + final String itemType = discographJsonObject.getString("item_type", ""); + + if (!itemType.equals(filter)) { + continue; + } + + switch (itemType) { + case "track": + collector.commit(new BandcampDiscographStreamInfoItemExtractor( + discographJsonObject, getUrl())); + break; + case "album": + collector.commit(new BandcampAlbumInfoItemExtractor( + discographJsonObject, getUrl())); + break; + } + } + + return new InfoItemsPage<>(collector, null); + } + + @Override + public InfoItemsPage getPage(final Page page) { + return null; + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampChannelLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampChannelLinkHandlerFactory.java index 3f51ed174..618bfc313 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampChannelLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampChannelLinkHandlerFactory.java @@ -10,6 +10,7 @@ import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper; import org.schabi.newpipe.extractor.utils.JsonUtils; +import org.schabi.newpipe.extractor.utils.Utils; import java.io.IOException; import java.util.List; @@ -17,11 +18,20 @@ import java.util.List; /** * Artist do have IDs that are useful */ -public class BandcampChannelLinkHandlerFactory extends ListLinkHandlerFactory { +public final class BandcampChannelLinkHandlerFactory extends ListLinkHandlerFactory { + private static final BandcampChannelLinkHandlerFactory INSTANCE + = new BandcampChannelLinkHandlerFactory(); + + private BandcampChannelLinkHandlerFactory() { + } + + public static BandcampChannelLinkHandlerFactory getInstance() { + return INSTANCE; + } @Override - public String getId(final String url) throws ParsingException { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { try { final String response = NewPipe.getDownloader().get(url).responseBody(); @@ -41,16 +51,13 @@ public class BandcampChannelLinkHandlerFactory extends ListLinkHandlerFactory { */ @Override public String getUrl(final String id, final List contentFilter, final String sortFilter) - throws ParsingException { - try { - return BandcampExtractorHelper.getArtistDetails(id) - .getString("bandcamp_url") - .replace("http://", "https://"); - } catch (final NullPointerException e) { + throws ParsingException, UnsupportedOperationException { + final JsonObject artistDetails = BandcampExtractorHelper.getArtistDetails(id); + if (artistDetails.getBoolean("error")) { throw new ParsingException( - "JSON does not contain URL (invalid id?) or is otherwise invalid", e); + "JSON does not contain a channel URL (invalid id?) or is otherwise invalid"); } - + return Utils.replaceHttpWithHttps(artistDetails.getString("bandcamp_url")); } /** @@ -61,22 +68,21 @@ public class BandcampChannelLinkHandlerFactory extends ListLinkHandlerFactory { final String lowercaseUrl = url.toLowerCase(); - // https: | | artist.bandcamp.com | releases - // 0 1 2 3 + // https: | | artist.bandcamp.com | releases - music - album - track ( | name) + // 0 1 2 3 (4) final String[] splitUrl = lowercaseUrl.split("/"); // URL is too short - if (splitUrl.length < 3) { + if (splitUrl.length != 3 && splitUrl.length != 4) { return false; } - // Must have "releases" or "music" as segment after url or none at all - if (splitUrl.length > 3 && !( - splitUrl[3].equals("releases") || splitUrl[3].equals("music") - )) { - + // Must have "releases", "music", "album" or "track" as segment after URL or none at all + if (splitUrl.length == 4 && !(splitUrl[3].equals("releases") + || splitUrl[3].equals("music") + || splitUrl[3].equals("album") + || splitUrl[3].equals("track"))) { return false; - } else { if (splitUrl[2].equals("daily.bandcamp.com")) { // Refuse links to daily.bandcamp.com as that is not an artist diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampChannelTabLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampChannelTabLinkHandlerFactory.java new file mode 100644 index 000000000..96cd8f994 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampChannelTabLinkHandlerFactory.java @@ -0,0 +1,72 @@ + +package org.schabi.newpipe.extractor.services.bandcamp.linkHandler; + +import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs; +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 BandcampChannelTabLinkHandlerFactory extends ListLinkHandlerFactory { + + private static final BandcampChannelTabLinkHandlerFactory INSTANCE + = new BandcampChannelTabLinkHandlerFactory(); + + private BandcampChannelTabLinkHandlerFactory() { + } + + public static BandcampChannelTabLinkHandlerFactory getInstance() { + return INSTANCE; + } + + /** + * Get a tab's URL suffix. + * + *

+ * These URLs don't actually exist on the Bandcamp website, as both albums and tracks are + * listed on the main page, but redirect to the main page, which is perfect for us as we need a + * unique URL for each tab. + *

+ * + * @param tab the tab value, which must not be null + * @return a URL suffix + * @throws UnsupportedTabException if the tab is not supported + */ + @Nonnull + public static String getUrlSuffix(@Nonnull final String tab) throws UnsupportedTabException { + switch (tab) { + case ChannelTabs.TRACKS: + return "/track"; + case ChannelTabs.ALBUMS: + return "/album"; + } + throw new UnsupportedTabException(tab); + } + + @Override + public String getId(final String url) throws ParsingException, UnsupportedOperationException { + return BandcampChannelLinkHandlerFactory.getInstance().getId(url); + } + + @Override + public String getUrl(final String id, final List contentFilter, final String sortFilter) + throws ParsingException, UnsupportedOperationException { + return BandcampChannelLinkHandlerFactory.getInstance().getUrl(id) + + getUrlSuffix(contentFilter.get(0)); + } + + @Override + public boolean onAcceptUrl(final String url) throws ParsingException { + return BandcampChannelLinkHandlerFactory.getInstance().onAcceptUrl(url); + } + + @Override + public String[] getAvailableContentFilter() { + return new String[]{ + ChannelTabs.TRACKS, + ChannelTabs.ALBUMS, + }; + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampCommentsLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampCommentsLinkHandlerFactory.java index 45ac46bf5..086efd8e1 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampCommentsLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampCommentsLinkHandlerFactory.java @@ -10,10 +10,20 @@ import java.util.List; * Like in {@link BandcampStreamLinkHandlerFactory}, tracks have no meaningful IDs except for * their URLs */ -public class BandcampCommentsLinkHandlerFactory extends ListLinkHandlerFactory { +public final class BandcampCommentsLinkHandlerFactory extends ListLinkHandlerFactory { + + private static final BandcampCommentsLinkHandlerFactory INSTANCE + = new BandcampCommentsLinkHandlerFactory(); + + private BandcampCommentsLinkHandlerFactory() { + } + + public static BandcampCommentsLinkHandlerFactory getInstance() { + return INSTANCE; + } @Override - public String getId(final String url) throws ParsingException { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { return url; } @@ -35,7 +45,8 @@ public class BandcampCommentsLinkHandlerFactory extends ListLinkHandlerFactory { @Override public String getUrl(final String id, final List contentFilter, - final String sortFilter) throws ParsingException { + final String sortFilter) + throws ParsingException, UnsupportedOperationException { return id; } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampFeaturedLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampFeaturedLinkHandlerFactory.java index fd6933738..99d1a6b98 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampFeaturedLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampFeaturedLinkHandlerFactory.java @@ -2,6 +2,7 @@ package org.schabi.newpipe.extractor.services.bandcamp.linkHandler; +import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper; import org.schabi.newpipe.extractor.utils.Utils; @@ -13,12 +14,23 @@ import static org.schabi.newpipe.extractor.services.bandcamp.extractors.Bandcamp import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampRadioExtractor.KIOSK_RADIO; import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampRadioExtractor.RADIO_API_URL; -public class BandcampFeaturedLinkHandlerFactory extends ListLinkHandlerFactory { +public final class BandcampFeaturedLinkHandlerFactory extends ListLinkHandlerFactory { + + private static final BandcampFeaturedLinkHandlerFactory INSTANCE = + new BandcampFeaturedLinkHandlerFactory(); + + private BandcampFeaturedLinkHandlerFactory() { + } + + public static BandcampFeaturedLinkHandlerFactory getInstance() { + return INSTANCE; + } @Override public String getUrl(final String id, final List contentFilter, - final String sortFilter) { + final String sortFilter) + throws ParsingException, UnsupportedOperationException { if (id.equals(KIOSK_FEATURED)) { return FEATURED_API_URL; // doesn't have a website } else if (id.equals(KIOSK_RADIO)) { @@ -29,7 +41,7 @@ public class BandcampFeaturedLinkHandlerFactory extends ListLinkHandlerFactory { } @Override - public String getId(final String url) { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { final String fixedUrl = Utils.replaceHttpWithHttps(url); if (BandcampExtractorHelper.isRadioUrl(fixedUrl) || fixedUrl.equals(RADIO_API_URL)) { return KIOSK_RADIO; diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampPlaylistLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampPlaylistLinkHandlerFactory.java index a88453339..68fac3e6f 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampPlaylistLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampPlaylistLinkHandlerFactory.java @@ -11,16 +11,28 @@ import java.util.List; /** * Just as with streams, the album ids are essentially useless for us. */ -public class BandcampPlaylistLinkHandlerFactory extends ListLinkHandlerFactory { +public final class BandcampPlaylistLinkHandlerFactory extends ListLinkHandlerFactory { + + private static final BandcampPlaylistLinkHandlerFactory INSTANCE + = new BandcampPlaylistLinkHandlerFactory(); + + private BandcampPlaylistLinkHandlerFactory() { + } + + public static BandcampPlaylistLinkHandlerFactory getInstance() { + return INSTANCE; + } + @Override - public String getId(final String url) throws ParsingException { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { return getUrl(url); } @Override public String getUrl(final String url, final List contentFilter, - final String sortFilter) throws ParsingException { + final String sortFilter) + throws ParsingException, UnsupportedOperationException { return url; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampSearchQueryHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampSearchQueryHandlerFactory.java index f1eeab4a6..73eb80ea3 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampSearchQueryHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampSearchQueryHandlerFactory.java @@ -11,11 +11,23 @@ import org.schabi.newpipe.extractor.utils.Utils; import java.io.UnsupportedEncodingException; import java.util.List; -public class BandcampSearchQueryHandlerFactory extends SearchQueryHandlerFactory { +public final class BandcampSearchQueryHandlerFactory extends SearchQueryHandlerFactory { + + private static final BandcampSearchQueryHandlerFactory INSTANCE + = new BandcampSearchQueryHandlerFactory(); + + private BandcampSearchQueryHandlerFactory() { + } + + public static BandcampSearchQueryHandlerFactory getInstance() { + return INSTANCE; + } + @Override public String getUrl(final String query, final List contentFilter, - final String sortFilter) throws ParsingException { + final String sortFilter) + throws ParsingException, UnsupportedOperationException { try { return BASE_URL + "/search?q=" + Utils.encodeUrlUtf8(query) + "&page=1"; } catch (final UnsupportedEncodingException e) { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampStreamLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampStreamLinkHandlerFactory.java index 0ef30cbec..c686f3147 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampStreamLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/linkHandler/BandcampStreamLinkHandlerFactory.java @@ -14,14 +14,24 @@ import static org.schabi.newpipe.extractor.services.bandcamp.extractors.Bandcamp * *

Radio (bandcamp weekly) shows do have ids.

*/ -public class BandcampStreamLinkHandlerFactory extends LinkHandlerFactory { +public final class BandcampStreamLinkHandlerFactory extends LinkHandlerFactory { + + private static final BandcampStreamLinkHandlerFactory INSTANCE + = new BandcampStreamLinkHandlerFactory(); + + private BandcampStreamLinkHandlerFactory() { + } + + public static BandcampStreamLinkHandlerFactory getInstance() { + return INSTANCE; + } /** * @see BandcampStreamLinkHandlerFactory */ @Override - public String getId(final String url) throws ParsingException { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { if (BandcampExtractorHelper.isRadioUrl(url)) { return url.split("bandcamp.com/\\?show=")[1]; } else { @@ -34,7 +44,8 @@ public class BandcampStreamLinkHandlerFactory extends LinkHandlerFactory { * @see BandcampStreamLinkHandlerFactory */ @Override - public String getUrl(final String input) { + public String getUrl(final String input) + throws ParsingException, UnsupportedOperationException { if (input.matches("\\d+")) { return BASE_URL + "/?show=" + input; } else {