From 6f3f608ab651574999a169cd506428ded9eac491 Mon Sep 17 00:00:00 2001 From: FireMasterK <20838718+FireMasterK@users.noreply.github.com> Date: Fri, 11 Feb 2022 04:08:22 +0000 Subject: [PATCH] Add support for extracting channel subscriber count in StreamInfo. --- .../extractors/YoutubeStreamExtractor.java | 15 +++++++++++++++ .../newpipe/extractor/stream/StreamExtractor.java | 11 +++++++++++ .../newpipe/extractor/stream/StreamInfo.java | 14 ++++++++++++++ .../services/BaseStreamExtractorTest.java | 1 + .../services/DefaultStreamExtractorTest.java | 7 +++++++ .../stream/YoutubeStreamExtractorDefaultTest.java | 5 +++++ 6 files changed, 53 insertions(+) diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java index 6c7ac66b8..10a20393b 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java @@ -45,6 +45,7 @@ import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; import java.util.*; +import static org.schabi.newpipe.extractor.ListExtractor.ITEM_COUNT_UNKNOWN; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.*; import static org.schabi.newpipe.extractor.utils.Utils.EMPTY_STRING; import static org.schabi.newpipe.extractor.utils.Utils.UTF_8; @@ -437,6 +438,20 @@ public class YoutubeStreamExtractor extends StreamExtractor { return fixThumbnailUrl(url); } + @Override + public long getUploaderSubscriberCount() throws ParsingException { + final JsonObject videoOwnerRenderer = JsonUtils.getObject(videoSecondaryInfoRenderer, "owner.videoOwnerRenderer"); + if (videoOwnerRenderer.has("subscriberCountText")) { + try { + return Utils.mixedNumberWordToLong(getTextFromObject(videoOwnerRenderer.getObject("subscriberCountText"))); + } catch (final NumberFormatException e) { + throw new ParsingException("Could not get subscriber count", e); + } + } else { + return ITEM_COUNT_UNKNOWN; + } + } + @Nonnull @Override public String getDashMpdUrl() throws ParsingException { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamExtractor.java index b78f8664e..f7bac660e 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamExtractor.java @@ -202,6 +202,17 @@ public abstract class StreamExtractor extends Extractor { return false; } + /** + * The subscriber count of the uploader. + * If the subscriber count is not implemented, or is unavailable, return -1. + * + * @return the subscriber count of the uploader or -1 if not available + * @throws ParsingException + */ + public long getUploaderSubscriberCount() throws ParsingException { + return -1; + } + /** * The url to the image file/profile picture/avatar of the creator/uploader of the stream. * If the url is not available you can return an empty String. diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java index 455f0dc46..42ca495cc 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java @@ -235,6 +235,11 @@ public class StreamInfo extends Info { } catch (Exception e) { streamInfo.addError(e); } + try { + streamInfo.setUploaderSubscriberCount(extractor.getUploaderSubscriberCount()); + } catch (Exception e) { + streamInfo.addError(e); + } try { streamInfo.setSubChannelName(extractor.getSubChannelName()); @@ -367,6 +372,7 @@ public class StreamInfo extends Info { private String uploaderUrl = ""; private String uploaderAvatarUrl = ""; private boolean uploaderVerified = false; + private long uploaderSubscriberCount = -1; private String subChannelName = ""; private String subChannelUrl = ""; @@ -540,6 +546,14 @@ public class StreamInfo extends Info { this.uploaderVerified = uploaderVerified; } + public long getUploaderSubscriberCount() { + return uploaderSubscriberCount; + } + + public void setUploaderSubscriberCount(long uploaderSubscriberCount) { + this.uploaderSubscriberCount = uploaderSubscriberCount; + } + public String getSubChannelName() { return subChannelName; } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/BaseStreamExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/BaseStreamExtractorTest.java index f32a60907..da418660a 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/BaseStreamExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/BaseStreamExtractorTest.java @@ -5,6 +5,7 @@ public interface BaseStreamExtractorTest extends BaseExtractorTest { void testUploaderName() throws Exception; void testUploaderUrl() throws Exception; void testUploaderAvatarUrl() throws Exception; + void testSubscriberCount() throws Exception; void testSubChannelName() throws Exception; void testSubChannelUrl() throws Exception; void testSubChannelAvatarUrl() throws Exception; diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/DefaultStreamExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/DefaultStreamExtractorTest.java index 1563abac4..5f02d55a5 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/DefaultStreamExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/DefaultStreamExtractorTest.java @@ -45,6 +45,7 @@ public abstract class DefaultStreamExtractorTest extends DefaultExtractorTest expectedDescriptionContains() { return Arrays.asList("https://www.youtube.com/channel/UC7l23W7gFi4Uho6WSzckZRA", "https://www.handcraftpictures.com/"); @@ -182,6 +183,7 @@ public class YoutubeStreamExtractorDefaultTest { @Override public StreamType expectedStreamType() { return StreamType.VIDEO_STREAM; } @Override public String expectedUploaderName() { return "Unbox Therapy"; } @Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UCsTcErHg8oDvUnTzoqsYeNw"; } + @Override public long expectedUploaderSubscriberCountAtLeast() { return 18_000_000; } @Override public List expectedDescriptionContains() { return Arrays.asList("https://www.youtube.com/watch?v=X7FLCHVXpsA&list=PL7u4lWXQ3wfI_7PgX0C-VTiwLeu0S4v34", "https://www.youtube.com/watch?v=Lqv6G0pDNnw&list=PL7u4lWXQ3wfI_7PgX0C-VTiwLeu0S4v34", @@ -274,6 +276,7 @@ public class YoutubeStreamExtractorDefaultTest { @Override public StreamType expectedStreamType() { return StreamType.VIDEO_STREAM; } @Override public String expectedUploaderName() { return "tagesschau"; } @Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UC5NOEUbkLheQcaaRldYW5GA"; } + @Override public long expectedUploaderSubscriberCountAtLeast() { return 1_000_000; } @Override public boolean expectedUploaderVerified() { return true; } @Override public List expectedDescriptionContains() { return Arrays.asList("Themen der Sendung", "07:15", "Wetter", "Sendung nachträglich bearbeitet"); @@ -336,6 +339,7 @@ public class YoutubeStreamExtractorDefaultTest { @Override public StreamType expectedStreamType() { return StreamType.VIDEO_STREAM; } @Override public String expectedUploaderName() { return "maiLab"; } @Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UCyHDQ5C6z1NDmJ4g6SerW8g"; } + @Override public long expectedUploaderSubscriberCountAtLeast() { return 1_400_000; } @Override public List expectedDescriptionContains() {return Arrays.asList("Vitamin", "2:44", "Was ist Vitamin D?");} @Override public boolean expectedUploaderVerified() { return true; } @Override public long expectedLength() { return 1010; } @@ -405,6 +409,7 @@ public class YoutubeStreamExtractorDefaultTest { @Override public StreamType expectedStreamType() { return StreamType.VIDEO_STREAM; } @Override public String expectedUploaderName() { return "Dinge Erklärt – Kurzgesagt"; } @Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UCwRH985XgMYXQ6NxXDo8npw"; } + @Override public long expectedUploaderSubscriberCountAtLeast() { return 1_500_000; } @Override public List expectedDescriptionContains() { return Arrays.asList("Lasst uns abtauchen!", "Angebot von funk", "Dinge"); } @Override public long expectedLength() { return 631; } @Override public long expectedTimestamp() { return TIMESTAMP; }