diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItem.java b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItem.java index 1b679f2cf..0ddbd6a9c 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItem.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItem.java @@ -30,6 +30,7 @@ public class CommentsInfoItem extends InfoItem { private int replyCount; @Nullable private Page replies; + private boolean creatorReply; public static final int NO_LIKE_COUNT = -1; public static final int NO_STREAM_POSITION = -1; @@ -172,4 +173,13 @@ public class CommentsInfoItem extends InfoItem { public Page getReplies() { return this.replies; } + + public void setCreatorReply(final boolean creatorReply) { + this.creatorReply = creatorReply; + } + + public boolean hasCreatorReply() { + return creatorReply; + } + } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemExtractor.java index dfff3bda4..c482f7195 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemExtractor.java @@ -134,4 +134,12 @@ public interface CommentsInfoItemExtractor extends InfoItemExtractor { default Page getReplies() throws ParsingException { return null; } + + /** + * Whether the comment was replied to by the creator. + */ + @Nullable + default boolean hasCreatorReply() throws ParsingException { + return false; + } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemsCollector.java b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemsCollector.java index fca5bdf59..d9b31e130 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemsCollector.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemsCollector.java @@ -101,6 +101,13 @@ public final class CommentsInfoItemsCollector addError(e); } + try { + resultItem.setCreatorReply(extractor.hasCreatorReply()); + } catch (final Exception e) { + addError(e); + } + + return resultItem; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsInfoItemExtractor.java index fb6463a54..7410b57d6 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsInfoItemExtractor.java @@ -277,4 +277,16 @@ public class YoutubeCommentsInfoItemExtractor implements CommentsInfoItemExtract return null; } } + + @Override + public boolean hasCreatorReply() throws ParsingException { + try { + final JsonObject commentRepliesRenderer = JsonUtils.getObject(json, + "replies.commentRepliesRenderer"); + return commentRepliesRenderer.has("viewRepliesCreatorThumbnail"); + } catch (final Exception e) { + return false; + } + } + } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeCommentsExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeCommentsExtractorTest.java index 611c6b457..8df29c9b4 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeCommentsExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeCommentsExtractorTest.java @@ -352,6 +352,49 @@ public class YoutubeCommentsExtractorTest { } } + public static class CreatorReply { + private final static String url = "https://www.youtube.com/watch?v=bem4adjGKjE"; + private static YoutubeCommentsExtractor extractor; + + @BeforeAll + public static void setUp() throws Exception { + YoutubeTestsUtils.ensureStateless(); + NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "creatorReply")); + extractor = (YoutubeCommentsExtractor) YouTube + .getCommentsExtractor(url); + extractor.fetchPage(); + } + + @Test + void testGetCommentsAllData() throws IOException, ExtractionException { + final InfoItemsPage comments = extractor.getInitialPage(); + + DefaultTests.defaultTestListOfItems(YouTube, comments.getItems(), comments.getErrors()); + + boolean creatorReply = false; + + for (final CommentsInfoItem c : comments.getItems()) { + assertFalse(Utils.isBlank(c.getUploaderUrl())); + assertFalse(Utils.isBlank(c.getUploaderName())); + YoutubeTestsUtils.testImages(c.getUploaderAvatars()); + assertFalse(Utils.isBlank(c.getCommentId())); + assertFalse(Utils.isBlank(c.getName())); + assertFalse(Utils.isBlank(c.getTextualUploadDate())); + assertNotNull(c.getUploadDate()); + YoutubeTestsUtils.testImages(c.getThumbnails()); + assertFalse(Utils.isBlank(c.getUrl())); + assertTrue(c.getLikeCount() >= 0); + assertFalse(Utils.isBlank(c.getCommentText().getContent())); + if (c.hasCreatorReply()) { + creatorReply = true; + } + } + assertTrue(creatorReply, "No comments was replied to by creator"); + + } + } + + public static class FormattingTest { private final static String url = "https://www.youtube.com/watch?v=zYpyS2HaZHM";