Skip to content

Commit 981aee4

Browse files
committed
Add support to extract total comment count.
1 parent 45636b0 commit 981aee4

4 files changed

Lines changed: 59 additions & 4 deletions

File tree

extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsExtractor.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ public boolean isCommentsDisabled() throws ExtractionException {
2222
return false;
2323
}
2424

25+
/**
26+
* @return total number of comments.
27+
*/
28+
public int getCommentsCount() throws ExtractionException {
29+
return -1;
30+
}
31+
2532
@Nonnull
2633
@Override
2734
public String getName() throws ParsingException {

extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfo.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ public static CommentsInfo getInfo(final CommentsExtractor commentsExtractor)
4848
ExtractorHelper.getItemsPageOrLogError(commentsInfo, commentsExtractor);
4949
commentsInfo.setCommentsDisabled(commentsExtractor.isCommentsDisabled());
5050
commentsInfo.setRelatedItems(initialCommentsPage.getItems());
51+
try {
52+
commentsInfo.setCommentsCount(commentsExtractor.getCommentsCount());
53+
} catch (Exception e) {
54+
commentsInfo.addError(e);
55+
}
5156
commentsInfo.setNextPage(initialCommentsPage.getNextPage());
5257

5358
return commentsInfo;
@@ -76,6 +81,7 @@ public static InfoItemsPage<CommentsInfoItem> getMoreItems(
7681

7782
private transient CommentsExtractor commentsExtractor;
7883
private boolean commentsDisabled = false;
84+
private int commentsCount;
7985

8086
public CommentsExtractor getCommentsExtractor() {
8187
return commentsExtractor;
@@ -86,6 +92,7 @@ public void setCommentsExtractor(final CommentsExtractor commentsExtractor) {
8692
}
8793

8894
/**
95+
* @return <code>true</code> if the comments are disabled otherwise <code>false</code> (default)
8996
* @apiNote Warning: This method is experimental and may get removed in a future release.
9097
* @return {@code true} if the comments are disabled otherwise {@code false} (default)
9198
* @see CommentsExtractor#isCommentsDisabled()
@@ -95,10 +102,29 @@ public boolean isCommentsDisabled() {
95102
}
96103

97104
/**
105+
* @param commentsDisabled <code>true</code> if the comments are disabled otherwise <code>false</code>
98106
* @apiNote Warning: This method is experimental and may get removed in a future release.
99107
* @param commentsDisabled {@code true} if the comments are disabled otherwise {@code false}
100108
*/
101109
public void setCommentsDisabled(final boolean commentsDisabled) {
102110
this.commentsDisabled = commentsDisabled;
103111
}
112+
113+
/**
114+
* Returns the total number of comments.
115+
*
116+
* @return totalComments
117+
*/
118+
public int getCommentsCount() {
119+
return commentsCount;
120+
}
121+
122+
/**
123+
* Sets the total number of comments.
124+
*
125+
* @param commentsCount
126+
*/
127+
public void setCommentsCount(int commentsCount) {
128+
this.commentsCount = commentsCount;
129+
}
104130
}

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

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.schabi.newpipe.extractor.services.youtube.extractors;
22

33
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonPostResponse;
4+
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject;
45
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.prepareDesktopJsonBuilder;
56
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
67

@@ -28,6 +29,7 @@
2829
import com.grack.nanojson.JsonArray;
2930
import com.grack.nanojson.JsonObject;
3031
import com.grack.nanojson.JsonWriter;
32+
import org.schabi.newpipe.extractor.utils.Utils;
3133

3234
public class YoutubeCommentsExtractor extends CommentsExtractor {
3335

@@ -44,6 +46,7 @@ public class YoutubeCommentsExtractor extends CommentsExtractor {
4446
*/
4547
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
4648
private Optional<Boolean> optCommentsDisabled = Optional.empty();
49+
private JsonObject ajaxJson;
4750

4851
public YoutubeCommentsExtractor(
4952
final StreamingService service,
@@ -187,16 +190,15 @@ public InfoItemsPage<CommentsInfoItem> getPage(final Page page)
187190
.done())
188191
.getBytes(StandardCharsets.UTF_8);
189192

190-
final JsonObject ajaxJson = getJsonPostResponse("next", body, localization);
193+
this.ajaxJson = getJsonPostResponse("next", body, localization);
191194

192195
final CommentsInfoItemsCollector collector = new CommentsInfoItemsCollector(
193196
getServiceId());
194-
collectCommentsFrom(collector, ajaxJson);
197+
collectCommentsFrom(collector);
195198
return new InfoItemsPage<>(collector, getNextPage(ajaxJson));
196199
}
197200

198-
private void collectCommentsFrom(final CommentsInfoItemsCollector collector,
199-
@Nonnull final JsonObject ajaxJson) throws ParsingException {
201+
private void collectCommentsFrom(final CommentsInfoItemsCollector collector) throws ParsingException {
200202

201203
final JsonArray onResponseReceivedEndpoints =
202204
ajaxJson.getArray("onResponseReceivedEndpoints");
@@ -274,4 +276,17 @@ public boolean isCommentsDisabled() throws ExtractionException {
274276

275277
return optCommentsDisabled.get();
276278
}
279+
280+
@Override
281+
public int getCommentsCount() throws ExtractionException {
282+
final JsonObject commentsHeaderRenderer = ajaxJson
283+
.getArray("onResponseReceivedEndpoints").getObject(0)
284+
.getObject("reloadContinuationItemsCommand")
285+
.getArray("continuationItems").getObject(0)
286+
.getObject("commentsHeaderRenderer");
287+
288+
final String text = getTextFromObject(commentsHeaderRenderer.getObject("countText"));
289+
290+
return Integer.parseInt(Utils.removeNonDigitCharacters(text));
291+
}
277292
}

extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeCommentsExtractorTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ private boolean getCommentsFromCommentsInfoHelper(String url) throws IOException
8989
@Test
9090
public void testGetCommentsAllData() throws IOException, ExtractionException {
9191
InfoItemsPage<CommentsInfoItem> comments = extractor.getInitialPage();
92+
assertTrue(extractor.getCommentsCount() > 5); // at least 5 comments
9293

9394
DefaultTests.defaultTestListOfItems(YouTube, comments.getItems(), comments.getErrors());
9495
for (CommentsInfoItem c : comments.getItems()) {
@@ -344,6 +345,12 @@ public void testGetCommentsReplyCount() throws IOException, ExtractionException
344345
assertNotEquals(UNKNOWN_REPLY_COUNT, firstComment.getReplyCount(), "Could not get the reply count of the first comment");
345346
assertGreater(300, firstComment.getReplyCount());
346347
}
348+
349+
@Test
350+
public void testCommentsCount() throws IOException, ExtractionException {
351+
extractor.getInitialPage(); // Needs to be called first
352+
assertTrue(extractor.getCommentsCount() > 18800);
353+
}
347354
}
348355

349356
public static class FormattingTest {

0 commit comments

Comments
 (0)