diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeService.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeService.java index 0d8845fa4..fcdff3af6 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeService.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeService.java @@ -39,6 +39,7 @@ import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeTrendingE import org.schabi.newpipe.extractor.services.youtube.extractors.kiosk.YoutubeLiveExtractor; import org.schabi.newpipe.extractor.services.youtube.extractors.kiosk.YoutubeTrendingGamingVideosExtractor; import org.schabi.newpipe.extractor.services.youtube.extractors.kiosk.YoutubeTrendingMoviesAndShowsTrailersExtractor; +import org.schabi.newpipe.extractor.services.youtube.extractors.kiosk.YoutubeTrendingMusicExtractor; import org.schabi.newpipe.extractor.services.youtube.extractors.kiosk.YoutubeTrendingPodcastsEpisodesExtractor; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeChannelLinkHandlerFactory; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeChannelTabLinkHandlerFactory; @@ -50,6 +51,7 @@ import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeStreamLi import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeTrendingGamingVideosLinkHandlerFactory; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeTrendingLinkHandlerFactory; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeTrendingMoviesAndShowsTrailersLinkHandlerFactory; +import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeTrendingMusicLinkHandlerFactory; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeTrendingPodcastsEpisodesLinkHandlerFactory; import org.schabi.newpipe.extractor.stream.StreamExtractor; import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; @@ -171,6 +173,8 @@ public class YoutubeService extends StreamingService { YoutubeTrendingGamingVideosLinkHandlerFactory.INSTANCE; final ListLinkHandlerFactory trendingMoviesAndShowsLHF = YoutubeTrendingMoviesAndShowsTrailersLinkHandlerFactory.INSTANCE; + final ListLinkHandlerFactory trendingMusicLHF = + YoutubeTrendingMusicLinkHandlerFactory.INSTANCE; try { list.addKioskEntry( @@ -206,6 +210,14 @@ public class YoutubeService extends StreamingService { trendingMoviesAndShowsLHF, YoutubeTrendingMoviesAndShowsTrailersLinkHandlerFactory.KIOSK_ID ); + list.addKioskEntry( + (streamingService, url, id) -> new YoutubeTrendingMusicExtractor( + YoutubeService.this, + trendingMusicLHF.fromUrl(url), + id), + trendingMusicLHF, + YoutubeTrendingMusicLinkHandlerFactory.KIOSK_ID + ); list.addKioskEntry( (streamingService, url, id) -> new YoutubeTrendingExtractor( YoutubeService.this, diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/kiosk/YoutubeTrendingMusicExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/kiosk/YoutubeTrendingMusicExtractor.java new file mode 100644 index 000000000..b545ec1e6 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/kiosk/YoutubeTrendingMusicExtractor.java @@ -0,0 +1,39 @@ +package org.schabi.newpipe.extractor.services.youtube.extractors.kiosk; + +import org.schabi.newpipe.extractor.StreamingService; +import org.schabi.newpipe.extractor.downloader.Downloader; +import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException; +import org.schabi.newpipe.extractor.exceptions.ExtractionException; +import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; + +import javax.annotation.Nonnull; +import java.io.IOException; + +public class YoutubeTrendingMusicExtractor extends YoutubeChartsBaseKioskExtractor { + + public YoutubeTrendingMusicExtractor(final StreamingService streamingService, + final ListLinkHandler linkHandler, + final String kioskId) { + super(streamingService, linkHandler, kioskId, "TRENDING_VIDEOS"); + } + + @Override + public void onFetchPage(@Nonnull final Downloader downloader) + throws IOException, ExtractionException { + if (!YT_CHARTS_SUPPORTED_COUNTRY_CODES.contains( + getExtractorContentCountry().getCountryCode())) { + throw new ContentNotSupportedException( + "YouTube Charts doesn't support this country for trending music videos charts"); + } + super.onFetchPage(downloader); + } + + @Nonnull + @Override + public String getName() throws ParsingException { + // This is the official YouTube Charts name, even if autogenerated tracks and unofficial + // contents are returned + return "Trending Music Videos"; + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubeTrendingMusicLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubeTrendingMusicLinkHandlerFactory.java new file mode 100644 index 000000000..4fe6df761 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubeTrendingMusicLinkHandlerFactory.java @@ -0,0 +1,52 @@ +package org.schabi.newpipe.extractor.services.youtube.linkHandler; + +import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; +import org.schabi.newpipe.extractor.utils.Utils; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; +import java.util.Locale; + +public final class YoutubeTrendingMusicLinkHandlerFactory + extends ListLinkHandlerFactory { + + public static final String KIOSK_ID = "trending_music"; + + public static final YoutubeTrendingMusicLinkHandlerFactory INSTANCE = + new YoutubeTrendingMusicLinkHandlerFactory(); + + private static final String PATH = "/charts/TrendingVideos"; + + private YoutubeTrendingMusicLinkHandlerFactory() { + } + + @Override + public String getUrl(final String id, + final List contentFilter, + final String sortFilter) + throws ParsingException, UnsupportedOperationException { + return "https://charts.youtube.com" + PATH + "/RightNow"; + } + + @Override + public String getId(final String url) throws ParsingException, UnsupportedOperationException { + return KIOSK_ID; + } + + @Override + public boolean onAcceptUrl(final String url) throws ParsingException { + final URL urlObj; + try { + urlObj = Utils.stringToURL(url); + } catch (final MalformedURLException e) { + return false; + } + + return Utils.isHTTP(urlObj) + && "charts.youtube.com".equals(urlObj.getHost().toLowerCase(Locale.ROOT)) + // Accept URLs not containing the /RightNow part + && urlObj.getPath().startsWith(PATH); + } +}