1+ /*
2+ * Created by Christian Schabesberger on 28.09.16.
3+ *
4+ * Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
5+ * YoutubeSuggestionExtractor.java is part of NewPipe Extractor.
6+ *
7+ * NewPipe Extractor is free software: you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation, either version 3 of the License, or
10+ * (at your option) any later version.
11+ *
12+ * NewPipe Extractor is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ * GNU General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU General Public License
18+ * along with NewPipe Extractor. If not, see <https://www.gnu.org/licenses/>.
19+ */
20+
121package org .schabi .newpipe .extractor .services .youtube .extractors ;
222
3- import static org .schabi .newpipe .extractor .services .youtube .YoutubeParsingHelper .getCookieHeader ;
23+ import static org .schabi .newpipe .extractor .utils .Utils .isBlank ;
24+ import static org .schabi .newpipe .extractor .utils .Utils .isNullOrEmpty ;
425
526import com .grack .nanojson .JsonArray ;
627import com .grack .nanojson .JsonParser ;
728import com .grack .nanojson .JsonParserException ;
829
930import org .schabi .newpipe .extractor .NewPipe ;
1031import org .schabi .newpipe .extractor .StreamingService ;
11- import org .schabi .newpipe .extractor .downloader .Downloader ;
32+ import org .schabi .newpipe .extractor .downloader .Response ;
1233import org .schabi .newpipe .extractor .exceptions .ExtractionException ;
1334import org .schabi .newpipe .extractor .exceptions .ParsingException ;
1435import org .schabi .newpipe .extractor .suggestion .SuggestionExtractor ;
1536import org .schabi .newpipe .extractor .utils .Utils ;
1637
1738import java .io .IOException ;
18- import java .util .ArrayList ;
39+ import java .util .Collections ;
40+ import java .util .HashMap ;
1941import java .util .List ;
20-
21- /*
22- * Created by Christian Schabesberger on 28.09.16.
23- *
24- * Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
25- * YoutubeSuggestionExtractor.java is part of NewPipe.
26- *
27- * NewPipe is free software: you can redistribute it and/or modify
28- * it under the terms of the GNU General Public License as published by
29- * the Free Software Foundation, either version 3 of the License, or
30- * (at your option) any later version.
31- *
32- * NewPipe is distributed in the hope that it will be useful,
33- * but WITHOUT ANY WARRANTY; without even the implied warranty of
34- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35- * GNU General Public License for more details.
36- *
37- * You should have received a copy of the GNU General Public License
38- * along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
39- */
42+ import java .util .Map ;
43+ import java .util .stream .Collectors ;
4044
4145public class YoutubeSuggestionExtractor extends SuggestionExtractor {
4246
@@ -46,35 +50,45 @@ public YoutubeSuggestionExtractor(final StreamingService service) {
4650
4751 @ Override
4852 public List <String > suggestionList (final String query ) throws IOException , ExtractionException {
49- final Downloader dl = NewPipe .getDownloader ();
50- final List <String > suggestions = new ArrayList <>();
51-
52- final String url = "https://suggestqueries.google.com/complete/search"
53- + "?client=" + "youtube" //"firefox" for JSON, 'toolbar' for xml
54- + "&jsonp=" + "JP"
53+ final String url = "https://suggestqueries-clients6.youtube.com/complete/search"
54+ + "?client=" + "youtube"
5555 + "&ds=" + "yt"
5656 + "&gl=" + Utils .encodeUrlUtf8 (getExtractorContentCountry ().getCountryCode ())
57- + "&q=" + Utils .encodeUrlUtf8 (query );
57+ + "&q=" + Utils .encodeUrlUtf8 (query )
58+ + "&xhr=t" ;
5859
59- String response = dl . get ( url , getCookieHeader (), getExtractorLocalization ()). responseBody ();
60- // trim JSONP part "JP(...)"
61- response = response . substring ( 3 , response . length () - 1 );
62- try {
63- final JsonArray collection = JsonParser . array (). from ( response ). getArray ( 1 );
64- for ( final Object suggestion : collection ) {
65- if (!( suggestion instanceof JsonArray )) {
66- continue ;
67- }
68- final String suggestionStr = (( JsonArray ) suggestion ). getString ( 0 );
69- if ( suggestionStr == null ) {
70- continue ;
71- }
72- suggestions . add ( suggestionStr );
73- }
60+ final Map < String , List < String >> headers = new HashMap <> ();
61+ headers . put ( "Origin" , Collections . singletonList ( "https://www.youtube.com" ));
62+ headers . put ( "Referer" , Collections . singletonList ( "https://www.youtube.com" ) );
63+
64+ final Response response = NewPipe . getDownloader ()
65+ . get ( url , headers , getExtractorLocalization ());
66+
67+ final String contentTypeHeader = response . getHeader ( "Content-Type" ) ;
68+ if ( isNullOrEmpty ( contentTypeHeader ) || ! contentTypeHeader . contains ( "application/json" )) {
69+ throw new ExtractionException ( "Invalid response type (got \" " + contentTypeHeader
70+ + " \" , excepted a JSON response) (response code "
71+ + response . responseCode () + ")" ) ;
72+ }
73+
74+ final String responseBody = response . responseBody ();
7475
75- return suggestions ;
76+ if (responseBody .isEmpty ()) {
77+ throw new ExtractionException ("Empty response received" );
78+ }
79+
80+ try {
81+ final JsonArray suggestions = JsonParser .array ()
82+ .from (responseBody )
83+ .getArray (1 ); // 0: search query, 1: search suggestions, 2: tracking data?
84+ return suggestions .stream ()
85+ .filter (JsonArray .class ::isInstance )
86+ .map (JsonArray .class ::cast )
87+ .map (suggestion -> suggestion .getString (0 )) // 0 is the search suggestion
88+ .filter (suggestion -> !isBlank (suggestion )) // Filter blank suggestions
89+ .collect (Collectors .toUnmodifiableList ());
7690 } catch (final JsonParserException e ) {
77- throw new ParsingException ("Could not parse json response" , e );
91+ throw new ParsingException ("Could not parse JSON response" , e );
7892 }
7993 }
8094}
0 commit comments