4141
4242import java .io .IOException ;
4343import java .nio .charset .StandardCharsets ;
44+ import java .util .stream .Stream ;
4445
4546import javax .annotation .Nonnull ;
4647
4748public class YoutubeTrendingExtractor extends KioskExtractor <StreamInfoItem > {
4849 private JsonObject initialData ;
4950
51+ private static final String VIDEOS_TAB_PARAMS = "4gIOGgxtb3N0X3BvcHVsYXI%3D" ;
52+
5053 public YoutubeTrendingExtractor (final StreamingService service ,
5154 final ListLinkHandler linkHandler ,
5255 final String kioskId ) {
@@ -60,6 +63,7 @@ public void onFetchPage(@Nonnull final Downloader downloader)
6063 final byte [] body = JsonWriter .string (prepareDesktopJsonBuilder (getExtractorLocalization (),
6164 getExtractorContentCountry ())
6265 .value ("browseId" , "FEtrending" )
66+ .value ("params" , VIDEOS_TAB_PARAMS )
6367 .done ())
6468 .getBytes (StandardCharsets .UTF_8 );
6569 // @formatter:on
@@ -81,6 +85,8 @@ public String getName() throws ParsingException {
8185 name = getTextAtKey (header .getObject ("feedTabbedHeaderRenderer" ), "title" );
8286 } else if (header .has ("c4TabbedHeaderRenderer" )) {
8387 name = getTextAtKey (header .getObject ("c4TabbedHeaderRenderer" ), "title" );
88+ } else if (header .has ("pageHeaderRenderer" )) {
89+ name = getTextAtKey (header .getObject ("pageHeaderRenderer" ), "pageTitle" );
8490 }
8591
8692 if (isNullOrEmpty (name )) {
@@ -94,7 +100,10 @@ public String getName() throws ParsingException {
94100 public InfoItemsPage <StreamInfoItem > getInitialPage () throws ParsingException {
95101 final StreamInfoItemsCollector collector = new StreamInfoItemsCollector (getServiceId ());
96102 final TimeAgoParser timeAgoParser = getTimeAgoParser ();
97- final JsonObject tabContent = getTrendingTabContent ();
103+ final JsonObject tab = getTrendingTab ();
104+ final JsonObject tabContent = tab .getObject ("content" );
105+ final boolean isVideoTab = tab .getObject ("endpoint" ).getObject ("browseEndpoint" )
106+ .getString ("params" , "" ).equals (VIDEOS_TAB_PARAMS );
98107
99108 if (tabContent .has ("richGridRenderer" )) {
100109 tabContent .getObject ("richGridRenderer" )
@@ -110,7 +119,7 @@ public InfoItemsPage<StreamInfoItem> getInitialPage() throws ParsingException {
110119 .forEachOrdered (videoRenderer -> collector .commit (
111120 new YoutubeStreamInfoItemExtractor (videoRenderer , timeAgoParser )));
112121 } else if (tabContent .has ("sectionListRenderer" )) {
113- tabContent .getObject ("sectionListRenderer" )
122+ final Stream < JsonObject > shelves = tabContent .getObject ("sectionListRenderer" )
114123 .getArray ("contents" )
115124 .stream ()
116125 .filter (JsonObject .class ::isInstance )
@@ -120,11 +129,19 @@ public InfoItemsPage<StreamInfoItem> getInitialPage() throws ParsingException {
120129 .stream ())
121130 .filter (JsonObject .class ::isInstance )
122131 .map (JsonObject .class ::cast )
123- .map (content -> content .getObject ("shelfRenderer" ))
124- // Filter Trending shorts and Recently trending sections which have a title,
125- // contrary to normal trends
126- .filter (shelfRenderer -> !shelfRenderer .has ("title" ))
127- .flatMap (shelfRenderer -> shelfRenderer .getObject ("content" )
132+ .map (content -> content .getObject ("shelfRenderer" ));
133+
134+ final Stream <JsonObject > items ;
135+ if (isVideoTab ) {
136+ // The first shelf of the Videos tab contains the normal trends
137+ items = shelves .findFirst ().stream ();
138+ } else {
139+ // Filter Trending shorts and Recently trending sections which have a title,
140+ // contrary to normal trends
141+ items = shelves .filter (shelfRenderer -> !shelfRenderer .has ("title" ));
142+ }
143+
144+ items .flatMap (shelfRenderer -> shelfRenderer .getObject ("content" )
128145 .getObject ("expandedShelfContentsRenderer" )
129146 .getArray ("items" )
130147 .stream ())
@@ -138,7 +155,7 @@ public InfoItemsPage<StreamInfoItem> getInitialPage() throws ParsingException {
138155 return new InfoItemsPage <>(collector , null );
139156 }
140157
141- private JsonObject getTrendingTabContent () throws ParsingException {
158+ private JsonObject getTrendingTab () throws ParsingException {
142159 return initialData .getObject ("contents" )
143160 .getObject ("twoColumnBrowseResultsRenderer" )
144161 .getArray ("tabs" )
@@ -150,7 +167,7 @@ private JsonObject getTrendingTabContent() throws ParsingException {
150167 .filter (tabRenderer -> tabRenderer .has ("content" ))
151168 // There should be at most one tab selected
152169 .findFirst ()
153- .orElseThrow (() -> new ParsingException ( "Could not get \" Now \" trending tab" ))
154- . getObject ( "content" );
170+ .orElseThrow (() ->
171+ new ParsingException ( "Could not get \" Now \" or \" Videos \" trending tab" ) );
155172 }
156173}
0 commit comments