Skip to content

Commit ff11c2d

Browse files
authored
Merge pull request #628 from litetex/fix-broken-yt-liked-comments
Fix broken yt likes in comments
2 parents 1ff56a8 + 289b84e commit ff11c2d

25 files changed

Lines changed: 630 additions & 178 deletions

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public class CommentsInfoItem extends InfoItem {
1717
@Nullable
1818
private DateWrapper uploadDate;
1919
private int likeCount;
20+
private String textualLikeCount;
2021
private boolean heartedByUploader;
2122
private boolean pinned;
2223

@@ -89,6 +90,14 @@ public void setLikeCount(int likeCount) {
8990
this.likeCount = likeCount;
9091
}
9192

93+
public String getTextualLikeCount() {
94+
return textualLikeCount;
95+
}
96+
97+
public void setTextualLikeCount(String textualLikeCount) {
98+
this.textualLikeCount = textualLikeCount;
99+
}
100+
92101
public void setHeartedByUploader(boolean isHeartedByUploader) {
93102
this.heartedByUploader = isHeartedByUploader;
94103
}

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

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,59 +3,95 @@
33
import org.schabi.newpipe.extractor.InfoItemExtractor;
44
import org.schabi.newpipe.extractor.exceptions.ParsingException;
55
import org.schabi.newpipe.extractor.localization.DateWrapper;
6+
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeCommentsInfoItemExtractor;
67
import org.schabi.newpipe.extractor.stream.StreamExtractor;
8+
import org.schabi.newpipe.extractor.utils.Utils;
79

810
import javax.annotation.Nullable;
911

1012
public interface CommentsInfoItemExtractor extends InfoItemExtractor {
1113

1214
/**
13-
* Return the like count of the comment, or -1 if it's unavailable
15+
* Return the like count of the comment, or -1 if it's unavailable<br/>
16+
*
17+
* NOTE: Currently only implemented for YT {@link YoutubeCommentsInfoItemExtractor#getLikeCount()}
18+
* with limitations (only approximate like count is returned)
1419
*
1520
* @see StreamExtractor#getLikeCount()
1621
*/
17-
int getLikeCount() throws ParsingException;
22+
default int getLikeCount() throws ParsingException {
23+
return -1;
24+
}
25+
26+
/**
27+
* The unmodified like count given by the service<br/>
28+
*
29+
* It may be language dependent
30+
*/
31+
default String getTextualLikeCount() throws ParsingException {
32+
return Utils.EMPTY_STRING;
33+
}
1834

1935
/**
2036
* The text of the comment
2137
*/
22-
String getCommentText() throws ParsingException;
38+
default String getCommentText() throws ParsingException {
39+
return Utils.EMPTY_STRING;
40+
}
2341

2442
/**
2543
* The upload date given by the service, unmodified
2644
*
2745
* @see StreamExtractor#getTextualUploadDate()
2846
*/
29-
String getTextualUploadDate() throws ParsingException;
47+
default String getTextualUploadDate() throws ParsingException {
48+
return Utils.EMPTY_STRING;
49+
}
3050

3151
/**
3252
* The upload date wrapped with DateWrapper class
3353
*
3454
* @see StreamExtractor#getUploadDate()
3555
*/
3656
@Nullable
37-
DateWrapper getUploadDate() throws ParsingException;
57+
default DateWrapper getUploadDate() throws ParsingException {
58+
return null;
59+
}
3860

39-
String getCommentId() throws ParsingException;
61+
default String getCommentId() throws ParsingException {
62+
return Utils.EMPTY_STRING;
63+
}
4064

41-
String getUploaderUrl() throws ParsingException;
65+
default String getUploaderUrl() throws ParsingException {
66+
return Utils.EMPTY_STRING;
67+
}
4268

43-
String getUploaderName() throws ParsingException;
69+
default String getUploaderName() throws ParsingException {
70+
return Utils.EMPTY_STRING;
71+
}
4472

45-
String getUploaderAvatarUrl() throws ParsingException;
73+
default String getUploaderAvatarUrl() throws ParsingException {
74+
return Utils.EMPTY_STRING;
75+
}
4676

4777
/**
4878
* Whether the comment has been hearted by the uploader
4979
*/
50-
boolean isHeartedByUploader() throws ParsingException;
80+
default boolean isHeartedByUploader() throws ParsingException {
81+
return false;
82+
}
5183

5284
/**
5385
* Whether the comment is pinned
5486
*/
55-
boolean isPinned() throws ParsingException;
87+
default boolean isPinned() throws ParsingException {
88+
return false;
89+
}
5690

5791
/**
5892
* Whether the uploader is verified by the service
5993
*/
60-
boolean isUploaderVerified() throws ParsingException;
94+
default boolean isUploaderVerified() throws ParsingException {
95+
return false;
96+
}
6197
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import java.util.ArrayList;
88
import java.util.List;
9-
import java.util.Vector;
109

1110
public class CommentsInfoItemsCollector extends InfoItemsCollector<CommentsInfoItem, CommentsInfoItemExtractor> {
1211

@@ -65,6 +64,11 @@ public CommentsInfoItem extract(CommentsInfoItemExtractor extractor) throws Pars
6564
} catch (Exception e) {
6665
addError(e);
6766
}
67+
try {
68+
resultItem.setTextualLikeCount(extractor.getTextualLikeCount());
69+
} catch (Exception e) {
70+
addError(e);
71+
}
6872
try {
6973
resultItem.setThumbnailUrl(extractor.getThumbnailUrl());
7074
} catch (Exception e) {

extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampCommentsInfoItemExtractor.java

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
import org.jsoup.nodes.Element;
44
import org.schabi.newpipe.extractor.comments.CommentsInfoItemExtractor;
55
import org.schabi.newpipe.extractor.exceptions.ParsingException;
6-
import org.schabi.newpipe.extractor.localization.DateWrapper;
7-
8-
import javax.annotation.Nullable;
96

107
public class BandcampCommentsInfoItemExtractor implements CommentsInfoItemExtractor {
118

@@ -32,39 +29,11 @@ public String getThumbnailUrl() throws ParsingException {
3229
return writing.getElementsByClass("thumb").attr("src");
3330
}
3431

35-
@Override
36-
public int getLikeCount() {
37-
return -1;
38-
}
39-
4032
@Override
4133
public String getCommentText() {
4234
return writing.getElementsByClass("text").first().ownText();
4335
}
4436

45-
@Override
46-
public String getTextualUploadDate() {
47-
return "";
48-
}
49-
50-
@Nullable
51-
@Override
52-
public DateWrapper getUploadDate() {
53-
return null;
54-
}
55-
56-
@Override
57-
public String getCommentId() {
58-
return "";
59-
}
60-
61-
@Override
62-
public String getUploaderUrl() {
63-
//return writing.getElementsByClass("name").attr("href");
64-
// Fan links cannot be opened
65-
return "";
66-
}
67-
6837
@Override
6938
public String getUploaderName() throws ParsingException {
7039
return writing.getElementsByClass("name").first().text();
@@ -74,19 +43,4 @@ public String getUploaderName() throws ParsingException {
7443
public String getUploaderAvatarUrl() {
7544
return writing.getElementsByClass("thumb").attr("src");
7645
}
77-
78-
@Override
79-
public boolean isHeartedByUploader() {
80-
return false;
81-
}
82-
83-
@Override
84-
public boolean isPinned() {
85-
return false;
86-
}
87-
88-
@Override
89-
public boolean isUploaderVerified() throws ParsingException {
90-
return false;
91-
}
9246
}

extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeCommentsInfoItemExtractor.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,6 @@ public DateWrapper getUploadDate() throws ParsingException {
5757
return new DateWrapper(PeertubeParsingHelper.parseDateFrom(textualUploadDate));
5858
}
5959

60-
@Override
61-
public int getLikeCount() {
62-
return -1;
63-
}
64-
6560
@Override
6661
public String getCommentText() throws ParsingException {
6762
final String htmlText = JsonUtils.getString(item, "text");
@@ -89,21 +84,6 @@ public String getUploaderAvatarUrl() {
8984
return baseUrl + value;
9085
}
9186

92-
@Override
93-
public boolean isHeartedByUploader() throws ParsingException {
94-
return false;
95-
}
96-
97-
@Override
98-
public boolean isPinned() throws ParsingException {
99-
return false;
100-
}
101-
102-
@Override
103-
public boolean isUploaderVerified() throws ParsingException {
104-
return false;
105-
}
106-
10787
@Override
10888
public String getUploaderName() throws ParsingException {
10989
return JsonUtils.getString(item, "account.name") + "@" + JsonUtils.getString(item, "account.host");

extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/extractors/SoundcloudCommentsInfoItemExtractor.java

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,6 @@ public String getUploaderAvatarUrl() {
3838
return json.getObject("user").getString("avatar_url");
3939
}
4040

41-
@Override
42-
public boolean isHeartedByUploader() throws ParsingException {
43-
return false;
44-
}
45-
46-
@Override
47-
public boolean isPinned() throws ParsingException {
48-
return false;
49-
}
50-
5141
@Override
5242
public boolean isUploaderVerified() throws ParsingException {
5343
return json.getObject("user").getBoolean("verified");
@@ -69,11 +59,6 @@ public DateWrapper getUploadDate() throws ParsingException {
6959
return new DateWrapper(SoundcloudParsingHelper.parseDateFrom(getTextualUploadDate()));
7060
}
7161

72-
@Override
73-
public int getLikeCount() {
74-
return -1;
75-
}
76-
7762
@Override
7863
public String getName() throws ParsingException {
7964
return json.getObject("user").getString("permalink");

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

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.grack.nanojson.JsonArray;
44
import com.grack.nanojson.JsonObject;
5+
56
import org.schabi.newpipe.extractor.comments.CommentsInfoItemExtractor;
67
import org.schabi.newpipe.extractor.exceptions.ParsingException;
78
import org.schabi.newpipe.extractor.localization.DateWrapper;
@@ -70,12 +71,70 @@ public DateWrapper getUploadDate() throws ParsingException {
7071
}
7172
}
7273

74+
/**
75+
* @implNote The method is parsing internally a localized string.<br/>
76+
* <ul>
77+
* <li>
78+
* More than >1k likes will result in an inaccurate number
79+
* </li>
80+
* <li>
81+
* This will fail for other languages than English.
82+
* However as long as the Extractor only uses "en-GB"
83+
* (as seen in {@link org.schabi.newpipe.extractor.services.youtube.YoutubeService#SUPPORTED_LANGUAGES})
84+
* everything will work fine.
85+
* </li>
86+
* </ul>
87+
* <br/>
88+
* Consider using {@link #getTextualLikeCount()}
89+
*/
7390
@Override
7491
public int getLikeCount() throws ParsingException {
92+
// This may return a language dependent version, e.g. in German: 3,3 Mio
93+
final String textualLikeCount = getTextualLikeCount();
94+
try {
95+
if (Utils.isBlank(textualLikeCount)) {
96+
return 0;
97+
}
98+
99+
return (int) Utils.mixedNumberWordToLong(textualLikeCount);
100+
} catch (Exception e) {
101+
throw new ParsingException("Unexpected error while converting textual like count to like count", e);
102+
}
103+
}
104+
105+
@Override
106+
public String getTextualLikeCount() throws ParsingException {
107+
/*
108+
* Example results as of 2021-05-20:
109+
* Language = English
110+
* 3.3M
111+
* 48K
112+
* 1.4K
113+
* 270K
114+
* 19
115+
* 6
116+
*
117+
* Language = German
118+
* 3,3 Mio
119+
* 48.189
120+
* 1419
121+
* 270.984
122+
* 19
123+
* 6
124+
*/
75125
try {
76-
return json.getInt("likeCount");
126+
// If a comment has no likes voteCount is not set
127+
if (!json.has("voteCount")) {
128+
return EMPTY_STRING;
129+
}
130+
131+
final JsonObject voteCountObj = JsonUtils.getObject(json, "voteCount");
132+
if (voteCountObj.isEmpty()) {
133+
return EMPTY_STRING;
134+
}
135+
return getTextFromObject(voteCountObj);
77136
} catch (Exception e) {
78-
throw new ParsingException("Could not get like count", e);
137+
throw new ParsingException("Could not get vote count", e);
79138
}
80139
}
81140

extractor/src/test/java/org/schabi/newpipe/extractor/services/bandcamp/BandcampCommentsExtractorTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313

1414
import java.io.IOException;
1515

16-
import static org.junit.Assert.*;
16+
import static org.junit.Assert.assertEquals;
1717
import static org.junit.Assert.assertFalse;
18+
import static org.junit.Assert.assertTrue;
1819
import static org.schabi.newpipe.extractor.ServiceList.Bandcamp;
19-
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
2020

2121
public class BandcampCommentsExtractorTest {
2222

@@ -47,6 +47,7 @@ public void testGetCommentsAllData() throws IOException, ExtractionException {
4747
assertFalse(Utils.isBlank(c.getThumbnailUrl()));
4848
assertFalse(Utils.isBlank(c.getUrl()));
4949
assertEquals(-1, c.getLikeCount());
50+
assertTrue(Utils.isBlank(c.getTextualLikeCount()));
5051
}
5152
}
5253
}

extractor/src/test/java/org/schabi/newpipe/extractor/services/peertube/PeertubeCommentsExtractorTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ public void testGetCommentsAllData() throws IOException, ExtractionException {
7575
assertFalse(Utils.isBlank(c.getTextualUploadDate()));
7676
assertFalse(Utils.isBlank(c.getThumbnailUrl()));
7777
assertFalse(Utils.isBlank(c.getUrl()));
78-
assertFalse(c.getLikeCount() != -1);
78+
assertEquals(-1, c.getLikeCount());
79+
assertTrue(Utils.isBlank(c.getTextualLikeCount()));
7980
}
8081
}
8182

0 commit comments

Comments
 (0)