diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelper.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelper.java index b926da6a8..a029d85da 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelper.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelper.java @@ -8,6 +8,7 @@ import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; +import org.schabi.newpipe.extractor.MultiInfoItemsCollector; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.channel.ChannelInfoItemsCollector; import org.schabi.newpipe.extractor.downloader.Downloader; @@ -16,6 +17,7 @@ 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.services.soundcloud.extractors.SoundcloudChannelInfoItemExtractor; +import org.schabi.newpipe.extractor.services.soundcloud.extractors.SoundcloudPlaylistInfoItemExtractor; import org.schabi.newpipe.extractor.services.soundcloud.extractors.SoundcloudStreamInfoItemExtractor; import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; import org.schabi.newpipe.extractor.utils.JsonUtils; @@ -300,6 +302,54 @@ public final class SoundcloudParsingHelper { return getStreamsFromApi(collector, apiUrl, false); } + public static String getInfoItemsFromApi(final MultiInfoItemsCollector collector, + final String apiUrl) throws ReCaptchaException, + ParsingException, IOException { + final Response response = NewPipe.getDownloader().get(apiUrl, SoundCloud.getLocalization()); + if (response.responseCode() >= 400) { + throw new IOException("Could not get streams from API, HTTP " + + response.responseCode()); + } + + final JsonObject responseObject; + try { + responseObject = JsonParser.object().from(response.responseBody()); + } catch (final JsonParserException e) { + throw new ParsingException("Could not parse json response", e); + } + + responseObject.getArray("collection") + .stream() + .filter(JsonObject.class::isInstance) + .map(JsonObject.class::cast) + .forEach(searchResult -> { + final String kind = searchResult.getString("kind", ""); + switch (kind) { + case "user": + collector.commit(new SoundcloudChannelInfoItemExtractor(searchResult)); + break; + case "track": + collector.commit(new SoundcloudStreamInfoItemExtractor(searchResult)); + break; + case "playlist": + collector.commit(new SoundcloudPlaylistInfoItemExtractor(searchResult)); + break; + } + }); + + String nextPageUrl; + try { + nextPageUrl = responseObject.getString("next_href"); + if (!nextPageUrl.contains("client_id=")) { + nextPageUrl += "&client_id=" + SoundcloudParsingHelper.clientId(); + } + } catch (final Exception ignored) { + nextPageUrl = ""; + } + + return nextPageUrl; + } + @Nonnull public static String getUploaderUrl(final JsonObject object) { final String url = object.getObject("user").getString("permalink_url", ""); @@ -312,6 +362,7 @@ public final class SoundcloudParsingHelper { return replaceHttpWithHttps(url); } + @Nonnull public static String getUploaderName(final JsonObject object) { return object.getObject("user").getString("username", ""); } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudService.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudService.java index cc4977e42..e5b38af51 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudService.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudService.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.localization.ContentCountry; import org.schabi.newpipe.extractor.playlist.PlaylistExtractor; import org.schabi.newpipe.extractor.search.SearchExtractor; import org.schabi.newpipe.extractor.services.soundcloud.extractors.SoundcloudChannelExtractor; +import org.schabi.newpipe.extractor.services.soundcloud.extractors.SoundcloudChannelTabExtractor; import org.schabi.newpipe.extractor.services.soundcloud.extractors.SoundcloudChartsExtractor; import org.schabi.newpipe.extractor.services.soundcloud.extractors.SoundcloudCommentsExtractor; import org.schabi.newpipe.extractor.services.soundcloud.extractors.SoundcloudPlaylistExtractor; @@ -27,6 +29,7 @@ import org.schabi.newpipe.extractor.services.soundcloud.extractors.SoundcloudStr import org.schabi.newpipe.extractor.services.soundcloud.extractors.SoundcloudSubscriptionExtractor; import org.schabi.newpipe.extractor.services.soundcloud.extractors.SoundcloudSuggestionExtractor; import org.schabi.newpipe.extractor.services.soundcloud.linkHandler.SoundcloudChannelLinkHandlerFactory; +import org.schabi.newpipe.extractor.services.soundcloud.linkHandler.SoundcloudChannelTabLinkHandlerFactory; import org.schabi.newpipe.extractor.services.soundcloud.linkHandler.SoundcloudChartsLinkHandlerFactory; import org.schabi.newpipe.extractor.services.soundcloud.linkHandler.SoundcloudCommentsLinkHandlerFactory; import org.schabi.newpipe.extractor.services.soundcloud.linkHandler.SoundcloudPlaylistLinkHandlerFactory; @@ -50,7 +53,7 @@ public class SoundcloudService extends StreamingService { @Override public SearchQueryHandlerFactory getSearchQHFactory() { - return new SoundcloudSearchQueryHandlerFactory(); + return SoundcloudSearchQueryHandlerFactory.getInstance(); } @Override @@ -63,6 +66,11 @@ public class SoundcloudService extends StreamingService { return SoundcloudChannelLinkHandlerFactory.getInstance(); } + @Override + public ListLinkHandlerFactory getChannelTabLHFactory() { + return SoundcloudChannelTabLinkHandlerFactory.getInstance(); + } + @Override public ListLinkHandlerFactory getPlaylistLHFactory() { return SoundcloudPlaylistLinkHandlerFactory.getInstance(); @@ -86,6 +94,11 @@ public class SoundcloudService extends StreamingService { return new SoundcloudChannelExtractor(this, linkHandler); } + @Override + public ChannelTabExtractor getChannelTabExtractor(final ListLinkHandler linkHandler) { + return new SoundcloudChannelTabExtractor(this, linkHandler); + } + @Override public PlaylistExtractor getPlaylistExtractor(final ListLinkHandler linkHandler) { return new SoundcloudPlaylistExtractor(this, linkHandler); @@ -103,14 +116,15 @@ public class SoundcloudService extends StreamingService { @Override public KioskList getKioskList() throws ExtractionException { - final KioskList.KioskExtractorFactory chartsFactory = (streamingService, url, id) -> - new SoundcloudChartsExtractor(SoundcloudService.this, - new SoundcloudChartsLinkHandlerFactory().fromUrl(url), id); - final KioskList list = new KioskList(this); + final SoundcloudChartsLinkHandlerFactory h = + SoundcloudChartsLinkHandlerFactory.getInstance(); + final KioskList.KioskExtractorFactory chartsFactory = (streamingService, url, id) -> + new SoundcloudChartsExtractor(SoundcloudService.this, + h.fromUrl(url), id); + // add kiosks here e.g.: - final SoundcloudChartsLinkHandlerFactory h = new SoundcloudChartsLinkHandlerFactory(); try { list.addKioskEntry(chartsFactory, h, "Top 50"); list.addKioskEntry(chartsFactory, h, "New & hot"); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/extractors/SoundcloudChannelExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/extractors/SoundcloudChannelExtractor.java index ccb91715e..143c8bf90 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/extractors/SoundcloudChannelExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/extractors/SoundcloudChannelExtractor.java @@ -1,24 +1,23 @@ package org.schabi.newpipe.extractor.services.soundcloud.extractors; import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudParsingHelper.SOUNDCLOUD_API_V2_URL; -import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; 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.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.services.soundcloud.SoundcloudParsingHelper; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; +import org.schabi.newpipe.extractor.services.soundcloud.linkHandler.SoundcloudChannelTabLinkHandlerFactory; import java.io.IOException; +import java.util.List; import javax.annotation.Nonnull; @@ -108,34 +107,22 @@ public class SoundcloudChannelExtractor extends ChannelExtractor { @Nonnull @Override - public InfoItemsPage getInitialPage() throws ExtractionException { - try { - final StreamInfoItemsCollector streamInfoItemsCollector = - new StreamInfoItemsCollector(getServiceId()); + public List getTabs() throws ParsingException { + final String url = getUrl(); + final String urlTracks = url + + SoundcloudChannelTabLinkHandlerFactory.getUrlSuffix(ChannelTabs.TRACKS); + final String urlPlaylists = url + + SoundcloudChannelTabLinkHandlerFactory.getUrlSuffix(ChannelTabs.PLAYLISTS); + final String urlAlbums = url + + SoundcloudChannelTabLinkHandlerFactory.getUrlSuffix(ChannelTabs.ALBUMS); + final String id = getId(); - final String apiUrl = USERS_ENDPOINT + getId() + "/tracks" + "?client_id=" - + SoundcloudParsingHelper.clientId() + "&limit=20" + "&linked_partitioning=1"; - - final String nextPageUrl = SoundcloudParsingHelper.getStreamsFromApiMinItems(15, - streamInfoItemsCollector, apiUrl); - - return new InfoItemsPage<>(streamInfoItemsCollector, new Page(nextPageUrl)); - } catch (final Exception e) { - throw new ExtractionException("Could not get next page", e); - } - } - - @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 StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId()); - final String nextPageUrl = SoundcloudParsingHelper.getStreamsFromApiMinItems(15, collector, - page.getUrl()); - - return new InfoItemsPage<>(collector, new Page(nextPageUrl)); + return List.of( + new ListLinkHandler(urlTracks, urlTracks, id, + List.of(ChannelTabs.TRACKS), ""), + new ListLinkHandler(urlPlaylists, urlPlaylists, id, + List.of(ChannelTabs.PLAYLISTS), ""), + new ListLinkHandler(urlAlbums, urlAlbums, id, + List.of(ChannelTabs.ALBUMS), "")); } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/extractors/SoundcloudChannelTabExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/extractors/SoundcloudChannelTabExtractor.java new file mode 100644 index 000000000..a85daa0d9 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/extractors/SoundcloudChannelTabExtractor.java @@ -0,0 +1,76 @@ +package org.schabi.newpipe.extractor.services.soundcloud.extractors; + +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.soundcloud.SoundcloudParsingHelper; + +import javax.annotation.Nonnull; +import java.io.IOException; + +import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudParsingHelper.SOUNDCLOUD_API_V2_URL; +import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; + +public class SoundcloudChannelTabExtractor extends ChannelTabExtractor { + + private static final String USERS_ENDPOINT = SOUNDCLOUD_API_V2_URL + "users/"; + + private final String userId; + + public SoundcloudChannelTabExtractor(final StreamingService service, + final ListLinkHandler linkHandler) { + super(service, linkHandler); + userId = getLinkHandler().getId(); + } + + @Nonnull + private String getEndpoint() throws ParsingException { + switch (getName()) { + case ChannelTabs.TRACKS: + return "/tracks"; + case ChannelTabs.PLAYLISTS: + return "/playlists_without_albums"; + case ChannelTabs.ALBUMS: + return "/albums"; + } + throw new ParsingException("Unsupported tab: " + getName()); + } + + @Override + public void onFetchPage(@Nonnull final Downloader downloader) { + } + + @Nonnull + @Override + public String getId() { + return userId; + } + + @Nonnull + @Override + public InfoItemsPage getInitialPage() throws IOException, ExtractionException { + return getPage(new Page(USERS_ENDPOINT + userId + getEndpoint() + "?client_id=" + + SoundcloudParsingHelper.clientId() + "&limit=20" + "&linked_partitioning=1")); + } + + @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 MultiInfoItemsCollector collector = new MultiInfoItemsCollector(getServiceId()); + final String nextPageUrl = SoundcloudParsingHelper.getInfoItemsFromApi( + collector, page.getUrl()); + + return new InfoItemsPage<>(collector, new Page(nextPageUrl)); + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudChannelLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudChannelLinkHandlerFactory.java index 3b262faa9..07bc4e3f7 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudChannelLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudChannelLinkHandlerFactory.java @@ -23,7 +23,7 @@ public final class SoundcloudChannelLinkHandlerFactory extends ListLinkHandlerFa @Override - public String getId(final String url) throws ParsingException { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { Utils.checkUrl(URL_PATTERN, url); try { @@ -36,7 +36,8 @@ public final class SoundcloudChannelLinkHandlerFactory extends ListLinkHandlerFa @Override public String getUrl(final String id, final List contentFilter, - final String sortFilter) throws ParsingException { + final String sortFilter) + throws ParsingException, UnsupportedOperationException { try { return SoundcloudParsingHelper.resolveUrlWithEmbedPlayer( "https://api.soundcloud.com/users/" + id); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudChannelTabLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudChannelTabLinkHandlerFactory.java new file mode 100644 index 000000000..663e2a206 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudChannelTabLinkHandlerFactory.java @@ -0,0 +1,61 @@ +package org.schabi.newpipe.extractor.services.soundcloud.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 SoundcloudChannelTabLinkHandlerFactory extends ListLinkHandlerFactory { + private static final SoundcloudChannelTabLinkHandlerFactory INSTANCE + = new SoundcloudChannelTabLinkHandlerFactory(); + + private SoundcloudChannelTabLinkHandlerFactory() { + } + + public static SoundcloudChannelTabLinkHandlerFactory getInstance() { + return INSTANCE; + } + + @Nonnull + public static String getUrlSuffix(final String tab) throws UnsupportedOperationException { + switch (tab) { + case ChannelTabs.TRACKS: + return "/tracks"; + case ChannelTabs.PLAYLISTS: + return "/sets"; + case ChannelTabs.ALBUMS: + return "/albums"; + } + throw new UnsupportedTabException(tab); + } + + @Override + public String getId(final String url) throws ParsingException { + return SoundcloudChannelLinkHandlerFactory.getInstance().getId(url); + } + + @Override + public String getUrl(final String id, + final List contentFilter, + final String sortFilter) throws ParsingException { + return SoundcloudChannelLinkHandlerFactory.getInstance().getUrl(id) + + getUrlSuffix(contentFilter.get(0)); + } + + @Override + public boolean onAcceptUrl(final String url) throws ParsingException { + return SoundcloudChannelLinkHandlerFactory.getInstance().onAcceptUrl(url); + } + + @Override + public String[] getAvailableContentFilter() { + return new String[] { + ChannelTabs.TRACKS, + ChannelTabs.PLAYLISTS, + ChannelTabs.ALBUMS, + }; + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudChartsLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudChartsLinkHandlerFactory.java index 695efee06..fc171a210 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudChartsLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudChartsLinkHandlerFactory.java @@ -1,18 +1,30 @@ package org.schabi.newpipe.extractor.services.soundcloud.linkHandler; +import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; import org.schabi.newpipe.extractor.utils.Parser; import java.util.List; -public class SoundcloudChartsLinkHandlerFactory extends ListLinkHandlerFactory { +public final class SoundcloudChartsLinkHandlerFactory extends ListLinkHandlerFactory { + + private static final SoundcloudChartsLinkHandlerFactory INSTANCE = + new SoundcloudChartsLinkHandlerFactory(); + private static final String TOP_URL_PATTERN = "^https?://(www\\.|m\\.)?soundcloud.com/charts(/top)?/?([#?].*)?$"; private static final String URL_PATTERN = "^https?://(www\\.|m\\.)?soundcloud.com/charts(/top|/new)?/?([#?].*)?$"; + private SoundcloudChartsLinkHandlerFactory() { + } + + public static SoundcloudChartsLinkHandlerFactory getInstance() { + return INSTANCE; + } + @Override - public String getId(final String url) { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { if (Parser.isMatch(TOP_URL_PATTERN, url.toLowerCase())) { return "Top 50"; } else { @@ -23,7 +35,8 @@ public class SoundcloudChartsLinkHandlerFactory extends ListLinkHandlerFactory { @Override public String getUrl(final String id, final List contentFilter, - final String sortFilter) { + final String sortFilter) + throws ParsingException, UnsupportedOperationException { if (id.equals("Top 50")) { return "https://soundcloud.com/charts/top"; } else { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudCommentsLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudCommentsLinkHandlerFactory.java index 23c6a2939..c5b2c8b64 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudCommentsLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudCommentsLinkHandlerFactory.java @@ -24,7 +24,8 @@ public final class SoundcloudCommentsLinkHandlerFactory extends ListLinkHandlerF @Override public String getUrl(final String id, final List contentFilter, - final String sortFilter) throws ParsingException { + final String sortFilter) + throws ParsingException, UnsupportedOperationException { try { return "https://api-v2.soundcloud.com/tracks/" + id + "/comments" + "?client_id=" + clientId() + "&threaded=0" + "&filter_replies=1"; @@ -37,7 +38,7 @@ public final class SoundcloudCommentsLinkHandlerFactory extends ListLinkHandlerF } @Override - public String getId(final String url) throws ParsingException { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { // Delegation to avoid duplicate code, as we need the same id return SoundcloudStreamLinkHandlerFactory.getInstance().getId(url); } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudPlaylistLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudPlaylistLinkHandlerFactory.java index 96d9a24ce..794e581ee 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudPlaylistLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudPlaylistLinkHandlerFactory.java @@ -22,7 +22,7 @@ public final class SoundcloudPlaylistLinkHandlerFactory extends ListLinkHandlerF } @Override - public String getId(final String url) throws ParsingException { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { Utils.checkUrl(URL_PATTERN, url); try { @@ -37,7 +37,7 @@ public final class SoundcloudPlaylistLinkHandlerFactory extends ListLinkHandlerF public String getUrl(final String id, final List contentFilter, final String sortFilter) - throws ParsingException { + throws ParsingException, UnsupportedOperationException { try { return SoundcloudParsingHelper.resolveUrlWithEmbedPlayer( "https://api.soundcloud.com/playlists/" + id); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudSearchQueryHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudSearchQueryHandlerFactory.java index 5d07e1c98..b034c0d35 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudSearchQueryHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudSearchQueryHandlerFactory.java @@ -13,7 +13,10 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.List; -public class SoundcloudSearchQueryHandlerFactory extends SearchQueryHandlerFactory { +public final class SoundcloudSearchQueryHandlerFactory extends SearchQueryHandlerFactory { + + private static final SoundcloudSearchQueryHandlerFactory INSTANCE = + new SoundcloudSearchQueryHandlerFactory(); public static final String TRACKS = "tracks"; public static final String USERS = "users"; @@ -22,11 +25,18 @@ public class SoundcloudSearchQueryHandlerFactory extends SearchQueryHandlerFacto public static final int ITEMS_PER_PAGE = 10; + private SoundcloudSearchQueryHandlerFactory() { + } + + public static SoundcloudSearchQueryHandlerFactory getInstance() { + return INSTANCE; + } + @Override public String getUrl(final String id, final List contentFilter, final String sortFilter) - throws ParsingException { + throws ParsingException, UnsupportedOperationException { try { String url = SOUNDCLOUD_API_V2_URL + "search"; diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudStreamLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudStreamLinkHandlerFactory.java index 9af4be09b..64b34ef7a 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudStreamLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/linkHandler/SoundcloudStreamLinkHandlerFactory.java @@ -21,7 +21,7 @@ public final class SoundcloudStreamLinkHandlerFactory extends LinkHandlerFactory } @Override - public String getUrl(final String id) throws ParsingException { + public String getUrl(final String id) throws ParsingException, UnsupportedOperationException { try { return SoundcloudParsingHelper.resolveUrlWithEmbedPlayer( "https://api.soundcloud.com/tracks/" + id); @@ -31,7 +31,7 @@ public final class SoundcloudStreamLinkHandlerFactory extends LinkHandlerFactory } @Override - public String getId(final String url) throws ParsingException { + public String getId(final String url) throws ParsingException, UnsupportedOperationException { if (Parser.isMatch(API_URL_PATTERN, url)) { return Parser.matchGroup1(API_URL_PATTERN, url); }