4747import static org .schabi .newpipe .extractor .utils .Utils .isNullOrEmpty ;
4848
4949public class YoutubeTrendingExtractor extends KioskExtractor <StreamInfoItem > {
50+ private static final String KIOSK_RECOMMENDED_PODCASTS = "Recommended Podcasts" ;
51+ private static final String RECOMMENDED_LIVES_BROWSE_ID = "UC4R8DWoMoI7CAwX8_LjQHig" ;
52+ private static final String RECOMMENDED_PODCASTS_BROWSE_ID = "FEpodcasts_destination" ;
53+ private static final String RECOMMENDED_PODCASTS_PARAMS = "qgcCCAM=" ;
54+ private static final long RECOMMENDED_PODCASTS_MAX_ITEMS = 40 ;
55+
5056 private JsonObject initialData ;
5157
5258 public YoutubeTrendingExtractor (final StreamingService service ,
@@ -58,13 +64,21 @@ public YoutubeTrendingExtractor(final StreamingService service,
5864 @ Override
5965 public void onFetchPage (@ Nonnull final Downloader downloader )
6066 throws IOException , ExtractionException {
61- // @formatter:off
62- final byte [] body = JsonWriter .string (prepareDesktopJsonBuilder (getExtractorLocalization (),
63- getExtractorContentCountry ())
64- .value ("browseId" , "UC4R8DWoMoI7CAwX8_LjQHig" )
65- .done ())
66- .getBytes (UTF_8 );
67- // @formatter:on
67+ final byte [] body ;
68+ if (KIOSK_RECOMMENDED_PODCASTS .equals (getId ())) {
69+ body = JsonWriter .string (prepareDesktopJsonBuilder (getExtractorLocalization (),
70+ getExtractorContentCountry ())
71+ .value ("browseId" , RECOMMENDED_PODCASTS_BROWSE_ID )
72+ .value ("params" , RECOMMENDED_PODCASTS_PARAMS )
73+ .done ())
74+ .getBytes (UTF_8 );
75+ } else {
76+ body = JsonWriter .string (prepareDesktopJsonBuilder (getExtractorLocalization (),
77+ getExtractorContentCountry ())
78+ .value ("browseId" , RECOMMENDED_LIVES_BROWSE_ID )
79+ .done ())
80+ .getBytes (UTF_8 );
81+ }
6882
6983 initialData = getJsonPostResponse ("browse" , body , getExtractorLocalization ());
7084 }
@@ -86,6 +100,8 @@ public String getName() throws ParsingException {
86100 } else if (header .has ("carouselHeaderRenderer" )) {
87101 name = header .getObject ("carouselHeaderRenderer" ).getArray ("contents" ).getObject (0 )
88102 .getObject ("topicChannelDetailsRenderer" ).getObject ("title" ).getString ("simpleText" );
103+ } else if (header .has ("pageHeaderRenderer" )) {
104+ name = header .getObject ("pageHeaderRenderer" ).getString ("pageTitle" );
89105 }
90106
91107 if (isNullOrEmpty (name )) {
@@ -99,6 +115,9 @@ public String getName() throws ParsingException {
99115 public InfoItemsPage <StreamInfoItem > getInitialPage () throws ParsingException {
100116 final StreamInfoItemsCollector collector = new StreamInfoItemsCollector (getServiceId ());
101117 final TimeAgoParser timeAgoParser = getTimeAgoParser ();
118+ final long maximumItems = KIOSK_RECOMMENDED_PODCASTS .equals (getId ())
119+ ? RECOMMENDED_PODCASTS_MAX_ITEMS
120+ : Long .MAX_VALUE ;
102121 final JsonObject tabContent = getTrendingTabRenderer ().getObject ("content" );
103122
104123 if (tabContent .has ("richGridRenderer" )) {
@@ -110,8 +129,10 @@ public InfoItemsPage<StreamInfoItem> getInitialPage() throws ParsingException {
110129 // Filter Trending shorts and Recently trending sections
111130 .filter (content -> content .has ("richItemRenderer" ))
112131 .map (content -> content .getObject ("richItemRenderer" )
113- .getObject ("content" )
114- .getObject ("videoRenderer" ))
132+ .getObject ("content" ))
133+ .filter (content -> content .has ("videoRenderer" ))
134+ .map (content -> content .getObject ("videoRenderer" ))
135+ .limit (maximumItems )
115136 .forEachOrdered (videoRenderer -> collector .commit (
116137 new YoutubeStreamInfoItemExtractor (videoRenderer , timeAgoParser )));
117138 } else if (tabContent .has ("sectionListRenderer" )) {
@@ -136,6 +157,7 @@ public InfoItemsPage<StreamInfoItem> getInitialPage() throws ParsingException {
136157 .filter (JsonObject .class ::isInstance )
137158 .map (JsonObject .class ::cast )
138159 .map (item -> item .getObject ("videoRenderer" ))
160+ .limit (maximumItems )
139161 .forEachOrdered (videoRenderer -> collector .commit (
140162 new YoutubeStreamInfoItemExtractor (videoRenderer , timeAgoParser )));
141163 }
@@ -159,6 +181,7 @@ public InfoItemsPage<StreamInfoItem> getInitialPage() throws ParsingException {
159181 .filter (JsonObject .class ::isInstance )
160182 .map (JsonObject .class ::cast )
161183 .map (item -> item .getObject ("gridVideoRenderer" ))
184+ .limit (maximumItems )
162185 .forEachOrdered (videoRenderer -> collector .commit (
163186 new YoutubeStreamInfoItemExtractor (videoRenderer , timeAgoParser )));
164187 }
@@ -182,11 +205,12 @@ public InfoItemsPage<StreamInfoItem> getInitialPage() throws ParsingException {
182205 .map (content -> content .getObject ("richItemRenderer" )
183206 .getObject ("content" )
184207 .getObject ("videoRenderer" ))
208+ .limit (maximumItems )
185209 .forEachOrdered (videoRenderer -> collector .commit (
186210 new YoutubeStreamInfoItemExtractor (videoRenderer , timeAgoParser )));
187211 }
188212 if (collector .getItems ().isEmpty ()) {
189- throw new ParsingException ("Could not get trending page" );
213+ throw new ParsingException ("Could not get kiosk page: " + getId () );
190214 }
191215
192216 if (ServiceList .YouTube .getFilterTypes ().contains ("recommendations" )) {
0 commit comments