Skip to content

Commit f651be4

Browse files
committed
[Youtube] Mark members-only videos
YouTube inserts members-only videos (i.e., videos that require channel membership to watch) into the Videos tab. Because the extractor unable to distinguish between them and "normal" videos, they may appear in subscriptions feeds. This enables the extractor to check if videos require membership, allowing clients to filter them. Ref: TeamNewPipe/NewPipe#12040 Ref: TeamNewPipe/NewPipe#12011
1 parent d9c777d commit f651be4

6 files changed

Lines changed: 62 additions & 0 deletions

File tree

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,4 +470,18 @@ public boolean isShortFormContent() throws ParsingException {
470470
throw new ParsingException("Could not determine if this is short-form content", e);
471471
}
472472
}
473+
474+
@Nonnull
475+
@Override
476+
public boolean requiresMembership() throws ParsingException {
477+
final JsonArray badges = videoInfo.getArray("badges");
478+
for (final Object badge : badges) {
479+
if (((JsonObject) badge).getObject("metadataBadgeRenderer")
480+
.getString("style", "").equals("BADGE_STYLE_TYPE_MEMBERS_ONLY")) {
481+
return true;
482+
}
483+
}
484+
return false;
485+
}
486+
473487
}

extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamExtractor.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,16 @@ public boolean isShortFormContent() throws ParsingException {
581581
return false;
582582
}
583583

584+
/**
585+
* Whether the stream is only available to channel members.
586+
*
587+
* @return whether the stream is only available to channel members.
588+
* @throws ParsingException if there is an error in the extraction
589+
*/
590+
public boolean requiresMembership() throws ParsingException {
591+
return false;
592+
}
593+
584594
public enum Privacy {
585595
PUBLIC,
586596
UNLISTED,

extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,11 @@ private static void extractOptionalData(final StreamInfo streamInfo,
330330
} catch (final Exception e) {
331331
streamInfo.addError(e);
332332
}
333+
try {
334+
streamInfo.setRequiresMembership(extractor.requiresMembership());
335+
} catch (final Exception e) {
336+
streamInfo.addError(e);
337+
}
333338

334339
streamInfo.setRelatedItems(ExtractorHelper.getRelatedItemsOrLogError(streamInfo,
335340
extractor));
@@ -381,6 +386,7 @@ private static void extractOptionalData(final StreamInfo streamInfo,
381386
private List<StreamSegment> streamSegments = List.of();
382387
private List<MetaInfo> metaInfo = List.of();
383388
private boolean shortFormContent = false;
389+
private boolean membersOnly = false;
384390

385391
/**
386392
* Preview frames, e.g. for the storyboard / seekbar thumbnail preview
@@ -727,4 +733,12 @@ public boolean isShortFormContent() {
727733
public void setShortFormContent(final boolean isShortFormContent) {
728734
this.shortFormContent = isShortFormContent;
729735
}
736+
737+
public boolean requiresMembership() {
738+
return membersOnly;
739+
}
740+
741+
public void setRequiresMembership(final boolean requiresMembership) {
742+
this.membersOnly = requiresMembership;
743+
}
730744
}

extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public class StreamInfoItem extends InfoItem {
4747
private List<Image> uploaderAvatars = List.of();
4848
private boolean uploaderVerified = false;
4949
private boolean shortFormContent = false;
50+
private boolean requiresMembership = false;
5051

5152
public StreamInfoItem(final int serviceId,
5253
final String url,
@@ -143,6 +144,14 @@ public void setShortFormContent(final boolean shortFormContent) {
143144
this.shortFormContent = shortFormContent;
144145
}
145146

147+
public boolean requiresMembership() {
148+
return requiresMembership;
149+
}
150+
151+
public void setRequiresMembership(final boolean requiresMembership) {
152+
this.requiresMembership = requiresMembership;
153+
}
154+
146155
@Override
147156
public String toString() {
148157
return "StreamInfoItem{"

extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemExtractor.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,4 +147,14 @@ default String getShortDescription() throws ParsingException {
147147
default boolean isShortFormContent() throws ParsingException {
148148
return false;
149149
}
150+
151+
/**
152+
* Whether the stream is only available to channel members.
153+
*
154+
* @return whether the stream is only available to channel members.
155+
* @throws ParsingException if there is an error in the extraction
156+
*/
157+
default boolean requiresMembership() throws ParsingException {
158+
return false;
159+
}
150160
}

extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemsCollector.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ public StreamInfoItem extract(final StreamInfoItemExtractor extractor) throws Pa
103103
} catch (final Exception e) {
104104
addError(e);
105105
}
106+
try {
107+
resultItem.setRequiresMembership(extractor.requiresMembership());
108+
} catch (final Exception e) {
109+
addError(e);
110+
}
106111

107112
return resultItem;
108113
}

0 commit comments

Comments
 (0)