33import com .grack .nanojson .JsonArray ;
44import com .grack .nanojson .JsonObject ;
55
6+ import com .grack .nanojson .JsonWriter ;
7+ import org .schabi .newpipe .extractor .Page ;
68import org .schabi .newpipe .extractor .comments .CommentsInfoItemExtractor ;
79import org .schabi .newpipe .extractor .exceptions .ParsingException ;
810import org .schabi .newpipe .extractor .localization .DateWrapper ;
1820public class YoutubeCommentsInfoItemExtractor implements CommentsInfoItemExtractor {
1921
2022 private final JsonObject json ;
23+ private JsonObject commentRenderer ;
2124 private final String url ;
2225 private final TimeAgoParser timeAgoParser ;
2326
@@ -29,6 +32,16 @@ public YoutubeCommentsInfoItemExtractor(final JsonObject json,
2932 this .timeAgoParser = timeAgoParser ;
3033 }
3134
35+ private JsonObject getCommentRenderer () throws ParsingException {
36+ if (commentRenderer == null ) {
37+ if (!json .has ("comment" ))
38+ commentRenderer = json ;
39+ else
40+ commentRenderer = JsonUtils .getObject (json , "comment.commentRenderer" );
41+ }
42+ return commentRenderer ;
43+ }
44+
3245 @ Override
3346 public String getUrl () throws ParsingException {
3447 return url ;
@@ -37,7 +50,7 @@ public String getUrl() throws ParsingException {
3750 @ Override
3851 public String getThumbnailUrl () throws ParsingException {
3952 try {
40- final JsonArray arr = JsonUtils .getArray (json , "authorThumbnail.thumbnails" );
53+ final JsonArray arr = JsonUtils .getArray (getCommentRenderer () , "authorThumbnail.thumbnails" );
4154 return JsonUtils .getString (arr .getObject (2 ), "url" );
4255 } catch (final Exception e ) {
4356 throw new ParsingException ("Could not get thumbnail url" , e );
@@ -47,7 +60,7 @@ public String getThumbnailUrl() throws ParsingException {
4760 @ Override
4861 public String getName () throws ParsingException {
4962 try {
50- return getTextFromObject (JsonUtils .getObject (json , "authorText" ));
63+ return getTextFromObject (JsonUtils .getObject (getCommentRenderer () , "authorText" ));
5164 } catch (final Exception e ) {
5265 return EMPTY_STRING ;
5366 }
@@ -56,7 +69,7 @@ public String getName() throws ParsingException {
5669 @ Override
5770 public String getTextualUploadDate () throws ParsingException {
5871 try {
59- return getTextFromObject (JsonUtils .getObject (json , "publishedTimeText" ));
72+ return getTextFromObject (JsonUtils .getObject (getCommentRenderer () , "publishedTimeText" ));
6073 } catch (final Exception e ) {
6174 throw new ParsingException ("Could not get publishedTimeText" , e );
6275 }
@@ -94,7 +107,7 @@ public int getLikeCount() throws ParsingException {
94107 // Try first to get the exact like count by using the accessibility data
95108 final String likeCount ;
96109 try {
97- likeCount = Utils .removeNonDigitCharacters (JsonUtils .getString (json ,
110+ likeCount = Utils .removeNonDigitCharacters (JsonUtils .getString (getCommentRenderer () ,
98111 "actionButtons.commentActionButtonsRenderer.likeButton.toggleButtonRenderer.accessibilityData.accessibilityData.label" ));
99112 } catch (final Exception e ) {
100113 // Use the approximate like count returned into the voteCount object
@@ -145,11 +158,11 @@ public String getTextualLikeCount() throws ParsingException {
145158 */
146159 try {
147160 // If a comment has no likes voteCount is not set
148- if (!json .has ("voteCount" )) {
161+ if (!getCommentRenderer () .has ("voteCount" )) {
149162 return EMPTY_STRING ;
150163 }
151164
152- final JsonObject voteCountObj = JsonUtils .getObject (json , "voteCount" );
165+ final JsonObject voteCountObj = JsonUtils .getObject (getCommentRenderer () , "voteCount" );
153166 if (voteCountObj .isEmpty ()) {
154167 return EMPTY_STRING ;
155168 }
@@ -162,7 +175,7 @@ public String getTextualLikeCount() throws ParsingException {
162175 @ Override
163176 public String getCommentText () throws ParsingException {
164177 try {
165- final JsonObject contentText = JsonUtils .getObject (json , "contentText" );
178+ final JsonObject contentText = JsonUtils .getObject (getCommentRenderer () , "contentText" );
166179 if (contentText .isEmpty ()) {
167180 // completely empty comments as described in
168181 // https://github.com/TeamNewPipe/NewPipeExtractor/issues/380#issuecomment-668808584
@@ -180,7 +193,7 @@ public String getCommentText() throws ParsingException {
180193 @ Override
181194 public String getCommentId () throws ParsingException {
182195 try {
183- return JsonUtils .getString (json , "commentId" );
196+ return JsonUtils .getString (getCommentRenderer () , "commentId" );
184197 } catch (final Exception e ) {
185198 throw new ParsingException ("Could not get comment id" , e );
186199 }
@@ -189,7 +202,7 @@ public String getCommentId() throws ParsingException {
189202 @ Override
190203 public String getUploaderAvatarUrl () throws ParsingException {
191204 try {
192- JsonArray arr = JsonUtils .getArray (json , "authorThumbnail.thumbnails" );
205+ JsonArray arr = JsonUtils .getArray (getCommentRenderer () , "authorThumbnail.thumbnails" );
193206 return JsonUtils .getString (arr .getObject (2 ), "url" );
194207 } catch (final Exception e ) {
195208 throw new ParsingException ("Could not get author thumbnail" , e );
@@ -198,24 +211,24 @@ public String getUploaderAvatarUrl() throws ParsingException {
198211
199212 @ Override
200213 public boolean isHeartedByUploader () throws ParsingException {
201- final JsonObject commentActionButtonsRenderer = json .getObject ("actionButtons" )
214+ final JsonObject commentActionButtonsRenderer = getCommentRenderer () .getObject ("actionButtons" )
202215 .getObject ("commentActionButtonsRenderer" );
203216 return commentActionButtonsRenderer .has ("creatorHeart" );
204217 }
205218
206219 @ Override
207- public boolean isPinned () {
208- return json .has ("pinnedCommentBadge" );
220+ public boolean isPinned () throws ParsingException {
221+ return getCommentRenderer () .has ("pinnedCommentBadge" );
209222 }
210223
211- public boolean isUploaderVerified () {
212- return json .has ("authorCommentBadge" );
224+ public boolean isUploaderVerified () throws ParsingException {
225+ return getCommentRenderer () .has ("authorCommentBadge" );
213226 }
214227
215228 @ Override
216229 public String getUploaderName () throws ParsingException {
217230 try {
218- return getTextFromObject (JsonUtils .getObject (json , "authorText" ));
231+ return getTextFromObject (JsonUtils .getObject (getCommentRenderer () , "authorText" ));
219232 } catch (final Exception e ) {
220233 return EMPTY_STRING ;
221234 }
@@ -224,10 +237,20 @@ public String getUploaderName() throws ParsingException {
224237 @ Override
225238 public String getUploaderUrl () throws ParsingException {
226239 try {
227- return "https://www.youtube.com/channel/" + JsonUtils .getString (json ,
240+ return "https://www.youtube.com/channel/" + JsonUtils .getString (getCommentRenderer () ,
228241 "authorEndpoint.browseEndpoint.browseId" );
229242 } catch (final Exception e ) {
230243 return EMPTY_STRING ;
231244 }
232245 }
246+
247+ @ Override
248+ public Page getReplies () throws ParsingException {
249+ try {
250+ final String id = JsonUtils .getString (JsonUtils .getArray (json , "replies.commentRepliesRenderer.contents" ).getObject (0 ), "continuationItemRenderer.continuationEndpoint.continuationCommand.token" );
251+ return new Page (url , id );
252+ } catch (final Exception e ) {
253+ return null ; // Would return null for Comment Replies, since YouTube does not support nested replies.
254+ }
255+ }
233256}
0 commit comments