[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: https://github.com/TeamNewPipe/NewPipe/issues/12040
Ref: https://github.com/TeamNewPipe/NewPipe/issues/12011
pull/1280/head
FineFindus 2025-02-13 18:14:55 +01:00
rodzic aa67363553
commit 601c1c8bd1
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 64873EE210FF8E6B
6 zmienionych plików z 62 dodań i 0 usunięć

Wyświetl plik

@ -470,4 +470,18 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
throw new ParsingException("Could not determine if this is short-form content", e);
}
}
@Nonnull
@Override
public boolean requiresMembership() throws ParsingException {
final JsonArray badges = videoInfo.getArray("badges");
for (final Object badge : badges) {
if (((JsonObject) badge).getObject("metadataBadgeRenderer")
.getString("style", "").equals("BADGE_STYLE_TYPE_MEMBERS_ONLY")) {
return true;
}
}
return false;
}
}

Wyświetl plik

@ -581,6 +581,16 @@ public abstract class StreamExtractor extends Extractor {
return false;
}
/**
* Whether the stream is only available to channel members.
*
* @return whether the stream is only available to channel members.
* @throws ParsingException if there is an error in the extraction
*/
public boolean requiresMembership() throws ParsingException {
return false;
}
public enum Privacy {
PUBLIC,
UNLISTED,

Wyświetl plik

@ -330,6 +330,11 @@ public class StreamInfo extends Info {
} catch (final Exception e) {
streamInfo.addError(e);
}
try {
streamInfo.setRequiresMembership(extractor.requiresMembership());
} catch (final Exception e) {
streamInfo.addError(e);
}
streamInfo.setRelatedItems(ExtractorHelper.getRelatedItemsOrLogError(streamInfo,
extractor));
@ -381,6 +386,7 @@ public class StreamInfo extends Info {
private List<StreamSegment> streamSegments = List.of();
private List<MetaInfo> metaInfo = List.of();
private boolean shortFormContent = false;
private boolean membersOnly = false;
/**
* Preview frames, e.g. for the storyboard / seekbar thumbnail preview
@ -727,4 +733,12 @@ public class StreamInfo extends Info {
public void setShortFormContent(final boolean isShortFormContent) {
this.shortFormContent = isShortFormContent;
}
public boolean requiresMembership() {
return membersOnly;
}
public void setRequiresMembership(final boolean requiresMembership) {
this.membersOnly = requiresMembership;
}
}

Wyświetl plik

@ -47,6 +47,7 @@ public class StreamInfoItem extends InfoItem {
private List<Image> uploaderAvatars = List.of();
private boolean uploaderVerified = false;
private boolean shortFormContent = false;
private boolean requiresMembership = false;
public StreamInfoItem(final int serviceId,
final String url,
@ -143,6 +144,14 @@ public class StreamInfoItem extends InfoItem {
this.shortFormContent = shortFormContent;
}
public boolean requiresMembership() {
return requiresMembership;
}
public void setRequiresMembership(final boolean requiresMembership) {
this.requiresMembership = requiresMembership;
}
@Override
public String toString() {
return "StreamInfoItem{"

Wyświetl plik

@ -146,4 +146,14 @@ public interface StreamInfoItemExtractor extends InfoItemExtractor {
default boolean isShortFormContent() throws ParsingException {
return false;
}
/**
* Whether the stream is only available to channel members.
*
* @return whether the stream is only available to channel members.
* @throws ParsingException if there is an error in the extraction
*/
default boolean requiresMembership() throws ParsingException {
return false;
}
}

Wyświetl plik

@ -103,6 +103,11 @@ public class StreamInfoItemsCollector
} catch (final Exception e) {
addError(e);
}
try {
resultItem.setRequiresMembership(extractor.requiresMembership());
} catch (final Exception e) {
addError(e);
}
return resultItem;
}