From 34b05a0dda9de7b9a74704b20cdf8c844d6d2499 Mon Sep 17 00:00:00 2001 From: FineFindus Date: Mon, 25 Sep 2023 10:40:45 +0200 Subject: [PATCH] feat(youtube/comments): support creator replies --- .../extractor/comments/CommentsInfoItem.java | 10 +++++ .../comments/CommentsInfoItemExtractor.java | 7 +++ .../comments/CommentsInfoItemsCollector.java | 7 +++ .../YoutubeCommentsInfoItemExtractor.java | 12 ++++++ .../youtube/YoutubeCommentsExtractorTest.java | 43 +++++++++++++++++++ 5 files changed, 79 insertions(+) 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 e1df4013d..f45c8f0d4 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 @@ -31,6 +31,7 @@ public class CommentsInfoItem extends InfoItem { @Nullable private Page replies; private boolean isChannelOwner; + private boolean creatorReply; public static final int NO_LIKE_COUNT = -1; public static final int NO_STREAM_POSITION = -1; @@ -182,4 +183,13 @@ public class CommentsInfoItem extends InfoItem { return isChannelOwner; } + + 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 3adf1f2c4..e78c61daf 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 @@ -141,4 +141,11 @@ public interface CommentsInfoItemExtractor extends InfoItemExtractor { default boolean isChannelOwner() throws ParsingException { return false; } + + /** + * Whether the comment was replied to by the creator. + */ + 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 397ffb5c7..ff912bb0f 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 @@ -108,6 +108,13 @@ public final class CommentsInfoItemsCollector } + 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 aa527358c..16740407d 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 @@ -283,4 +283,16 @@ public class YoutubeCommentsInfoItemExtractor implements CommentsInfoItemExtract return getCommentRenderer().getBoolean("authorIsChannelOwner"); } + + @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 7128ecc42..4ffeed09f 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 @@ -395,6 +395,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";