From d38d64708def2dbcbad5687e2fe4410ec9932294 Mon Sep 17 00:00:00 2001 From: AudricV <74829229+AudricV@users.noreply.github.com> Date: Sat, 26 Jul 2025 23:02:00 +0200 Subject: [PATCH] [YouTube] Add running lives extractor from Live system channel --- .../services/youtube/YoutubeService.java | 19 +++++-- .../kiosk/YoutubeLiveExtractor.java | 14 +++++ .../YoutubeLiveLinkHandlerFactory.java | 53 +++++++++++++++++++ 3 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/kiosk/YoutubeLiveExtractor.java create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubeLiveLinkHandlerFactory.java 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 a1785f0e0..e0b605fd1 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 @@ -36,9 +36,11 @@ import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExt import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeSubscriptionExtractor; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeSuggestionExtractor; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeTrendingExtractor; +import org.schabi.newpipe.extractor.services.youtube.extractors.kiosk.YoutubeLiveExtractor; 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.YoutubeCommentsLinkHandlerFactory; +import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeLiveLinkHandlerFactory; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubePlaylistLinkHandlerFactory; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeStreamLinkHandlerFactory; @@ -154,17 +156,26 @@ public class YoutubeService extends StreamingService { @Override public KioskList getKioskList() throws ExtractionException { final KioskList list = new KioskList(this); - final ListLinkHandlerFactory h = YoutubeTrendingLinkHandlerFactory.getInstance(); + final ListLinkHandlerFactory trendingLHF = YoutubeTrendingLinkHandlerFactory.getInstance(); + final ListLinkHandlerFactory runningLivesLHF = + YoutubeLiveLinkHandlerFactory.INSTANCE; - // add kiosks here e.g.: try { + list.addKioskEntry( + (streamingService, url, id) -> new YoutubeLiveExtractor( + YoutubeService.this, + runningLivesLHF.fromUrl(url), + id), + runningLivesLHF, + YoutubeLiveLinkHandlerFactory.KIOSK_ID + ); list.addKioskEntry( (streamingService, url, id) -> new YoutubeTrendingExtractor( YoutubeService.this, - h.fromUrl(url), + trendingLHF.fromUrl(url), id ), - h, + trendingLHF, YoutubeTrendingExtractor.KIOSK_ID ); list.setDefaultKiosk(YoutubeTrendingExtractor.KIOSK_ID); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/kiosk/YoutubeLiveExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/kiosk/YoutubeLiveExtractor.java new file mode 100644 index 000000000..17db88e8a --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/kiosk/YoutubeLiveExtractor.java @@ -0,0 +1,14 @@ +package org.schabi.newpipe.extractor.services.youtube.extractors.kiosk; + +import org.schabi.newpipe.extractor.StreamingService; +import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; + +public class YoutubeLiveExtractor extends YoutubeDesktopBaseKioskExtractor { + + public YoutubeLiveExtractor(final StreamingService streamingService, + final ListLinkHandler linkHandler, + final String kioskId) { + super(streamingService, linkHandler, kioskId, "UC4R8DWoMoI7CAwX8_LjQHig", + "EgdsaXZldGFikgEDCKEK"); + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubeLiveLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubeLiveLinkHandlerFactory.java new file mode 100644 index 000000000..831c918c9 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubeLiveLinkHandlerFactory.java @@ -0,0 +1,53 @@ +package org.schabi.newpipe.extractor.services.youtube.linkHandler; + +import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isInvidiousURL; +import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isYoutubeURL; + +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; + +public final class YoutubeLiveLinkHandlerFactory extends ListLinkHandlerFactory { + + public static final String KIOSK_ID = "live"; + + public static final YoutubeLiveLinkHandlerFactory INSTANCE = + new YoutubeLiveLinkHandlerFactory(); + + private static final String LIVE_CHANNEL_PATH = "/channel/UC4R8DWoMoI7CAwX8_LjQHig/livetab"; + private static final String LIVE_CHANNEL_TAB_PARAMS = "ss=CKEK"; + + private YoutubeLiveLinkHandlerFactory() { + } + + @Override + public String getUrl(final String id, + final List contentFilters, + final String sortFilter) + throws ParsingException, UnsupportedOperationException { + return "https://www.youtube.com" + LIVE_CHANNEL_PATH + "?" + LIVE_CHANNEL_TAB_PARAMS; + } + + @Override + public String getId(final String url) throws ParsingException, UnsupportedOperationException { + return KIOSK_ID; + } + + @Override + public boolean onAcceptUrl(final String url) { + final URL urlObj; + try { + urlObj = Utils.stringToURL(url); + } catch (final MalformedURLException e) { + return false; + } + + return Utils.isHTTP(urlObj) && (isYoutubeURL(urlObj) || isInvidiousURL(urlObj)) + && LIVE_CHANNEL_PATH.equals(urlObj.getPath()) + && LIVE_CHANNEL_TAB_PARAMS.equals(urlObj.getQuery()); + } +}