Skip to content

Commit 1852031

Browse files
committed
[YouTube] Support pageHeaderRenderer and interactiveTabbedHeaderRenderer channel headers
The addition of this support required to turn the isCarouselHeader boolean into an enum containing all supported channel headers named HeaderType. Also assert that the page has been fetched where needed to avoid NullPointerExceptions when the channel page has been not fetched and remove the getChannelHeaderJson method in YoutubeChannelExtractor, method for which its code has been moved to its sole usage after the new headers support changes.
1 parent 7936987 commit 1852031

2 files changed

Lines changed: 209 additions & 59 deletions

File tree

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelHelper.java

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -219,24 +219,68 @@ private static void checkIfChannelResponseIsValid(@Nonnull final JsonObject json
219219
*/
220220
public static final class ChannelHeader {
221221

222+
/**
223+
* Types of supported YouTube channel headers.
224+
*/
225+
public enum HeaderType {
226+
227+
/**
228+
* A {@code c4TabbedHeaderRenderer} channel header type.
229+
*
230+
* <p>
231+
* This header is returned on the majority of channels and contains the channel's name,
232+
* its banner and its avatar and its subscriber count in most cases.
233+
* </p>
234+
*/
235+
C4_TABBED,
236+
237+
/**
238+
* An {@code interactiveTabbedHeaderRenderer} channel header type.
239+
*
240+
* <p>
241+
* This header is returned for gaming topic channels, and only contains the channel's
242+
* name, its banner and a poster as its "avatar".
243+
* </p>
244+
*/
245+
INTERACTIVE_TABBED,
246+
247+
/**
248+
* A {@code carouselHeaderRenderer} channel header type.
249+
*
250+
* <p>
251+
* This header returns only the channel's name, its avatar and its subscriber count.
252+
* </p>
253+
*/
254+
CAROUSEL,
255+
256+
/**
257+
* A {@code pageHeaderRenderer} channel header type.
258+
*
259+
* <p>
260+
* This header returns only the channel's name and its avatar.
261+
* </p>
262+
*/
263+
PAGE
264+
}
265+
222266
/**
223267
* The channel header JSON response.
224268
*/
225269
@Nonnull
226270
public final JsonObject json;
227271

228272
/**
229-
* Whether the header is a {@code carouselHeaderRenderer}.
273+
* The type of the channel header.
230274
*
231275
* <p>
232-
* See the class documentation for more details.
276+
* See the documentation of the {@link HeaderType} class for more details.
233277
* </p>
234278
*/
235-
public final boolean isCarouselHeader;
279+
public final HeaderType headerType;
236280

237-
private ChannelHeader(@Nonnull final JsonObject json, final boolean isCarouselHeader) {
281+
private ChannelHeader(@Nonnull final JsonObject json, final HeaderType headerType) {
238282
this.json = json;
239-
this.isCarouselHeader = isCarouselHeader;
283+
this.headerType = headerType;
240284
}
241285
}
242286

@@ -254,7 +298,7 @@ public static Optional<ChannelHeader> getChannelHeader(
254298

255299
if (header.has("c4TabbedHeaderRenderer")) {
256300
return Optional.of(header.getObject("c4TabbedHeaderRenderer"))
257-
.map(json -> new ChannelHeader(json, false));
301+
.map(json -> new ChannelHeader(json, ChannelHeader.HeaderType.C4_TABBED));
258302
} else if (header.has("carouselHeaderRenderer")) {
259303
return header.getObject("carouselHeaderRenderer")
260304
.getArray("contents")
@@ -264,7 +308,14 @@ public static Optional<ChannelHeader> getChannelHeader(
264308
.filter(item -> item.has("topicChannelDetailsRenderer"))
265309
.findFirst()
266310
.map(item -> item.getObject("topicChannelDetailsRenderer"))
267-
.map(json -> new ChannelHeader(json, true));
311+
.map(json -> new ChannelHeader(json, ChannelHeader.HeaderType.CAROUSEL));
312+
} else if (header.has("pageHeaderRenderer")) {
313+
return Optional.of(header.getObject("pageHeaderRenderer"))
314+
.map(json -> new ChannelHeader(json, ChannelHeader.HeaderType.PAGE));
315+
} else if (header.has("interactiveTabbedHeaderRenderer")) {
316+
return Optional.of(header.getObject("interactiveTabbedHeaderRenderer"))
317+
.map(json -> new ChannelHeader(json,
318+
ChannelHeader.HeaderType.INTERACTIVE_TABBED));
268319
} else {
269320
return Optional.empty();
270321
}

0 commit comments

Comments
 (0)