2
0
mirror of https://github.com/TeamNewPipe/NewPipeExtractor synced 2025-08-22 09:57:38 +00:00

[YouTube] Add trending music extractor

This kiosk is meant to return official music videos, but it also
returns unofficial content and autogenerated tracks, hence the
kiosk name.

Making requests with an unsupported YouTube Charts country leads to a
400 HTTP error, so for these countries a ContentNotSupportedException
is thrown by the extractor.
This commit is contained in:
AudricV 2025-07-26 23:30:24 +02:00
parent f4203e632d
commit 21c3aad320
No known key found for this signature in database
GPG Key ID: DA92EC7905614198
3 changed files with 103 additions and 0 deletions

View File

@ -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.YoutubeLiveExtractor;
import org.schabi.newpipe.extractor.services.youtube.extractors.kiosk.YoutubeTrendingGamingVideosExtractor; 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.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.extractors.kiosk.YoutubeTrendingPodcastsEpisodesExtractor;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeChannelLinkHandlerFactory; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeChannelLinkHandlerFactory;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeChannelTabLinkHandlerFactory; 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.YoutubeTrendingGamingVideosLinkHandlerFactory;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeTrendingLinkHandlerFactory; 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.YoutubeTrendingMoviesAndShowsTrailersLinkHandlerFactory;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeTrendingMusicLinkHandlerFactory;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeTrendingPodcastsEpisodesLinkHandlerFactory; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeTrendingPodcastsEpisodesLinkHandlerFactory;
import org.schabi.newpipe.extractor.stream.StreamExtractor; import org.schabi.newpipe.extractor.stream.StreamExtractor;
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
@ -171,6 +173,8 @@ public class YoutubeService extends StreamingService {
YoutubeTrendingGamingVideosLinkHandlerFactory.INSTANCE; YoutubeTrendingGamingVideosLinkHandlerFactory.INSTANCE;
final ListLinkHandlerFactory trendingMoviesAndShowsLHF = final ListLinkHandlerFactory trendingMoviesAndShowsLHF =
YoutubeTrendingMoviesAndShowsTrailersLinkHandlerFactory.INSTANCE; YoutubeTrendingMoviesAndShowsTrailersLinkHandlerFactory.INSTANCE;
final ListLinkHandlerFactory trendingMusicLHF =
YoutubeTrendingMusicLinkHandlerFactory.INSTANCE;
try { try {
list.addKioskEntry( list.addKioskEntry(
@ -206,6 +210,14 @@ public class YoutubeService extends StreamingService {
trendingMoviesAndShowsLHF, trendingMoviesAndShowsLHF,
YoutubeTrendingMoviesAndShowsTrailersLinkHandlerFactory.KIOSK_ID YoutubeTrendingMoviesAndShowsTrailersLinkHandlerFactory.KIOSK_ID
); );
list.addKioskEntry(
(streamingService, url, id) -> new YoutubeTrendingMusicExtractor(
YoutubeService.this,
trendingMusicLHF.fromUrl(url),
id),
trendingMusicLHF,
YoutubeTrendingMusicLinkHandlerFactory.KIOSK_ID
);
list.addKioskEntry( list.addKioskEntry(
(streamingService, url, id) -> new YoutubeTrendingExtractor( (streamingService, url, id) -> new YoutubeTrendingExtractor(
YoutubeService.this, YoutubeService.this,

View File

@ -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";
}
}

View File

@ -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<String> 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);
}
}