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 {