88import java .util .List ;
99import java .util .Map ;
1010
11+ import javax .annotation .Nonnull ;
12+
1113import org .schabi .newpipe .extractor .DownloadRequest ;
1214import org .schabi .newpipe .extractor .DownloadResponse ;
1315import org .schabi .newpipe .extractor .Downloader ;
2628import com .grack .nanojson .JsonArray ;
2729import com .grack .nanojson .JsonObject ;
2830import com .grack .nanojson .JsonParser ;
29- import com . grack . nanojson . JsonParserException ;
31+
3032
3133public class YoutubeCommentsExtractor extends CommentsExtractor {
3234
33- private static final String USER_AGENT = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64 ; rv:61 .0) Gecko/20100101 Firefox/61 .0" ;
35+ private static final String USER_AGENT = "Mozilla/5.0 (Android 8.1.0; Mobile ; rv:62 .0) Gecko/62.0 Firefox/62 .0" ;
3436
35- private List <String > cookies ;
36- private String sessionToken ;
3737 private String ytClientVersion ;
3838 private String ytClientName ;
3939 private String title ;
@@ -45,17 +45,14 @@ public YoutubeCommentsExtractor(StreamingService service, ListLinkHandler uiHand
4545
4646 @ Override
4747 public InfoItemsPage <CommentsInfoItem > getInitialPage () throws IOException , ExtractionException {
48- // initial page does not load any comments but is required to get session token
49- // and cookies
48+ // initial page does not load any comments but is required to get comments token
5049 super .fetchPage ();
5150 return initPage ;
5251 }
5352
54- // isn't this method redundant. you can just call getnextpage on getInitialPage
5553 @ Override
5654 public String getNextPageUrl () throws IOException , ExtractionException {
57- // initial page does not load any comments but is required to get session token
58- // and cookies
55+ // initial page does not load any comments but is required to get comments token
5956 super .fetchPage ();
6057 return initPage .getNextPageUrl ();
6158 }
@@ -64,7 +61,7 @@ private String getNextPageUrl(JsonObject ajaxJson) throws IOException, ParsingEx
6461
6562 JsonArray arr ;
6663 try {
67- arr = (JsonArray ) JsonUtils .getValue (ajaxJson , "response.continuationContents.itemSectionContinuation .continuations" );
64+ arr = (JsonArray ) JsonUtils .getValue (ajaxJson , "response.continuationContents.commentSectionContinuation .continuations" );
6865 } catch (Exception e ) {
6966 return "" ;
7067 }
@@ -85,9 +82,8 @@ private String getNextPageUrl(String continuation) throws ParsingException {
8582 params .put ("action_get_comments" , "1" );
8683 params .put ("pbj" , "1" );
8784 params .put ("ctoken" , continuation );
88- params .put ("continuation" , continuation );
8985 try {
90- return "https://www .youtube.com/comment_service_ajax ?" + getDataString (params );
86+ return "https://m .youtube.com/watch_comment ?" + getDataString (params );
9187 } catch (UnsupportedEncodingException e ) {
9288 throw new ParsingException ("Could not get next page url" , e );
9389 }
@@ -101,8 +97,8 @@ public InfoItemsPage<CommentsInfoItem> getPage(String pageUrl) throws IOExceptio
10197 String ajaxResponse = makeAjaxRequest (pageUrl );
10298 JsonObject ajaxJson ;
10399 try {
104- ajaxJson = JsonParser .object ().from (ajaxResponse );
105- } catch (JsonParserException e ) {
100+ ajaxJson = JsonParser .array ().from (ajaxResponse ). getObject ( 1 );
101+ } catch (Exception e ) {
106102 throw new ParsingException ("Could not parse json data for comments" , e );
107103 }
108104 CommentsInfoItemsCollector collector = new CommentsInfoItemsCollector (getServiceId ());
@@ -114,7 +110,7 @@ private void collectCommentsFrom(CommentsInfoItemsCollector collector, JsonObjec
114110
115111 JsonArray contents ;
116112 try {
117- contents = (JsonArray ) JsonUtils .getValue (ajaxJson , "response.continuationContents.itemSectionContinuation.contents " );
113+ contents = (JsonArray ) JsonUtils .getValue (ajaxJson , "response.continuationContents.commentSectionContinuation.items " );
118114 }catch (Exception e ) {
119115 //no comments
120116 return ;
@@ -138,7 +134,7 @@ private void collectCommentsFrom(CommentsInfoItemsCollector collector, JsonObjec
138134 private void fetchTitle (JsonArray contents ) {
139135 if (null == title ) {
140136 try {
141- title = ( String ) JsonUtils .getValue (contents .getObject (0 ), "commentThreadRenderer.commentTargetTitle.simpleText" );
137+ title = getYoutubeText (( JsonObject ) JsonUtils .getValue (contents .getObject (0 ), "commentThreadRenderer.commentTargetTitle" ) );
142138 } catch (Exception e ) {
143139 title = "Youtube Comments" ;
144140 }
@@ -152,11 +148,9 @@ public void onFetchPage(Downloader downloader) throws IOException, ExtractionExc
152148 DownloadRequest request = new DownloadRequest (null , requestHeaders );
153149 DownloadResponse response = downloader .get (getUrl (), request );
154150 String responseBody = response .getResponseBody ();
155- cookies = response .getResponseCookies ();
156- sessionToken = findValue (responseBody , "XSRF_TOKEN\" :\" " , "\" " );
157151 ytClientVersion = findValue (responseBody , "INNERTUBE_CONTEXT_CLIENT_VERSION\" :\" " , "\" " );
158152 ytClientName = findValue (responseBody , "INNERTUBE_CONTEXT_CLIENT_NAME\" :" , "," );
159- String commentsTokenInside = findValue (responseBody , "itemSectionRenderer " , "comment-item-section " );
153+ String commentsTokenInside = findValue (responseBody , "commentSectionRenderer " , "} " );
160154 String commentsToken = findValue (commentsTokenInside , "continuation\" :\" " , "\" " );
161155 initPage = getPage (getNextPageUrl (commentsToken ));
162156 }
@@ -168,20 +162,14 @@ public String getName() throws ParsingException {
168162
169163 private String makeAjaxRequest (String siteUrl ) throws IOException , ReCaptchaException {
170164
171- Map <String , String > postDataMap = new HashMap <>();
172- postDataMap .put ("session_token" , sessionToken );
173- String postData = getDataString (postDataMap );
174-
175165 Map <String , List <String >> requestHeaders = new HashMap <>();
176- requestHeaders .put ("Content-Type" , Arrays .asList ("application/x-www-form-urlencoded" ));
177166 requestHeaders .put ("Accept" , Arrays .asList ("*/*" ));
178167 requestHeaders .put ("User-Agent" , Arrays .asList (USER_AGENT ));
179168 requestHeaders .put ("X-YouTube-Client-Version" , Arrays .asList (ytClientVersion ));
180169 requestHeaders .put ("X-YouTube-Client-Name" , Arrays .asList (ytClientName ));
181- DownloadRequest request = new DownloadRequest (postData , requestHeaders );
182- request .setRequestCookies (cookies );
170+ DownloadRequest request = new DownloadRequest (null , requestHeaders );
183171
184- return NewPipe .getDownloader ().post (siteUrl , request ).getResponseBody ();
172+ return NewPipe .getDownloader ().get (siteUrl , request ).getResponseBody ();
185173 }
186174
187175 private String getDataString (Map <String , String > params ) throws UnsupportedEncodingException {
@@ -205,4 +193,21 @@ private String findValue(String doc, String start, String end) {
205193 return doc .substring (beginIndex , endIndex );
206194 }
207195
196+ public static String getYoutubeText (@ Nonnull JsonObject object ) throws ParsingException {
197+ try {
198+ return (String ) JsonUtils .getValue (object , "simpleText" );
199+ } catch (Exception e1 ) {
200+ try {
201+ JsonArray arr = (JsonArray ) JsonUtils .getValue (object , "runs" );
202+ String result = "" ;
203+ for (int i =0 ; i <arr .size ();i ++) {
204+ result = result + (String ) JsonUtils .getValue (arr .getObject (i ), "text" );
205+ }
206+ return result ;
207+ } catch (Exception e2 ) {
208+ throw new ParsingException ("Could not get text" , e2 );
209+ }
210+ }
211+ }
212+
208213}
0 commit comments