55import static org .schabi .newpipe .extractor .ServiceList .SoundCloud ;
66import static org .schabi .newpipe .extractor .utils .Utils .isNullOrEmpty ;
77import static org .schabi .newpipe .extractor .utils .Utils .replaceHttpWithHttps ;
8- import static org .schabi .newpipe .extractor .downloader .Response .validateResponseCode ;
98
109import com .grack .nanojson .JsonArray ;
1110import com .grack .nanojson .JsonObject ;
1918import org .schabi .newpipe .extractor .NewPipe ;
2019import org .schabi .newpipe .extractor .channel .ChannelInfoItemsCollector ;
2120import org .schabi .newpipe .extractor .downloader .Downloader ;
22- import org .schabi .newpipe .extractor .downloader .Response ;
2321import org .schabi .newpipe .extractor .exceptions .ExtractionException ;
2422import org .schabi .newpipe .extractor .exceptions .HttpResponseException ;
2523import org .schabi .newpipe .extractor .exceptions .ParsingException ;
@@ -106,8 +104,9 @@ public static synchronized String clientId() throws ExtractionException, IOExcep
106104
107105 final Downloader dl = NewPipe .getDownloader ();
108106
109- final Response downloadResponse = dl .get ("https://soundcloud.com" ).validateResponseCode ();
110- final String responseBody = downloadResponse .responseBody ();
107+ final String responseBody = dl .get ("https://soundcloud.com" )
108+ .ensureSuccessResponseCode ()
109+ .responseBody ();
111110 final String clientIdPattern = ",client_id:\" (.*?)\" " ;
112111
113112 final Document doc = Jsoup .parse (responseBody );
@@ -123,7 +122,7 @@ public static synchronized String clientId() throws ExtractionException, IOExcep
123122 if (!isNullOrEmpty (srcUrl )) {
124123 try {
125124 clientId = Parser .matchGroup1 (clientIdPattern , dl .get (srcUrl , headers )
126- .validateResponseCode ()
125+ .ensureSuccessResponseCode ()
127126 .responseBody ());
128127 return clientId ;
129128 } catch (final RegexException ignored ) {
@@ -155,7 +154,7 @@ public static DateWrapper parseDate(final String uploadDate) throws ParsingExcep
155154 /**
156155 * Call the endpoint "/resolve" of the API.
157156 * <p>
158- * See https://web.archive.org/web/20170804051146/https://developers.soundcloud.com/docs/api/reference#resolve
157+ * See <a href=" https://web.archive.org/web/20170804051146/https://developers.soundcloud.com/docs/api/reference#resolve">docs</a>
159158 */
160159 // CHECKSTYLE:ON
161160 public static JsonObject resolveFor (@ Nonnull final Downloader downloader , final String url )
@@ -166,7 +165,8 @@ public static JsonObject resolveFor(@Nonnull final Downloader downloader, final
166165
167166 try {
168167 final String response = downloader .get (apiUrl , SoundCloud .getLocalization ())
169- .responseBody ();
168+ .ensureSuccessResponseCode ()
169+ .responseBody ();
170170 return JsonParser .object ().from (response );
171171 } catch (final JsonParserException e ) {
172172 throw new ParsingException ("Could not parse json response" , e );
@@ -184,7 +184,7 @@ public static String resolveUrlWithEmbedPlayer(final String apiUrl) throws IOExc
184184
185185 final var response = NewPipe .getDownloader ().get ("https://w.soundcloud.com/player/?url="
186186 + Utils .encodeUrlUtf8 (apiUrl ), SoundCloud .getLocalization ());
187- validateResponseCode ( response );
187+ response . ensureSuccessResponseCode ( );
188188 final var responseBody = response .responseBody ();
189189 return Jsoup .parse (responseBody ).select ("link[rel=\" canonical\" ]" ).first ()
190190 .attr ("abs:href" );
@@ -195,7 +195,6 @@ public static String resolveUrlWithEmbedPlayer(final String apiUrl) throws IOExc
195195 *
196196 * @return the resolved id
197197 */
198- // TODO: what makes this method different from the others? Don' they all return the same?
199198 public static String resolveIdWithWidgetApi (final String urlString ) throws IOException ,
200199 ParsingException {
201200 String fixedUrl = urlString ;
@@ -204,7 +203,14 @@ public static String resolveIdWithWidgetApi(final String urlString) throws IOExc
204203
205204 if (ON_URL_PATTERN .matcher (fixedUrl ).find ()) {
206205 try {
207- fixedUrl = NewPipe .getDownloader ().head (fixedUrl ).latestUrl ();
206+ fixedUrl = NewPipe .getDownloader ()
207+ .head (fixedUrl )
208+ .throwIfServerError ()
209+ .latestUrl ();
210+ // Soundcloud returns HTTP 403 but it still redirects,
211+ // so can get the redirected url via latestUrl regardless.
212+ // This why only throw for 5xx and not 4xx.
213+
208214 // remove tracking params which are in the query string
209215 fixedUrl = fixedUrl .split ("\\ ?" )[0 ];
210216 } catch (final ExtractionException e ) {
@@ -232,10 +238,11 @@ public static String resolveIdWithWidgetApi(final String urlString) throws IOExc
232238 + Utils .encodeUrlUtf8 (url .toString ())
233239 + "&format=json&client_id=" + SoundcloudParsingHelper .clientId ();
234240
235- final var response = NewPipe .getDownloader ().get (widgetUrl ,
236- SoundCloud .getLocalization ());
241+ final var responseBody = NewPipe .getDownloader ()
242+ .get (widgetUrl , SoundCloud .getLocalization ())
243+ .ensureSuccessResponseCode ()
244+ .responseBody ();
237245
238- final var responseBody = response .validateResponseCode ().responseBody ();
239246 final JsonObject o = JsonParser .object ().from (responseBody );
240247 return String .valueOf (JsonUtils .getValue (o , "id" ));
241248 } catch (final JsonParserException e ) {
@@ -249,16 +256,16 @@ public static String resolveIdWithWidgetApi(final String urlString) throws IOExc
249256 /**
250257 * Fetch the users from the given API and commit each of them to the collector.
251258 * <p>
252- * This differ from {@link #getUsersFromApi(ChannelInfoItemsCollector, String)} in the sense
259+ * This differs from {@link #getUsersFromApi(ChannelInfoItemsCollector, String)} in the sense
253260 * that they will always get MIN_ITEMS or more.
254261 *
255- * @param minItems the method will return only when it have extracted that many items
262+ * @param minItems the method will return only when it has extracted this many items
256263 * (equal or more)
257264 */
258265 public static String getUsersFromApiMinItems (final int minItems ,
259266 final ChannelInfoItemsCollector collector ,
260267 final String apiUrl ) throws IOException ,
261- ReCaptchaException , ParsingException {
268+ ReCaptchaException , ParsingException , HttpResponseException {
262269 String nextPageUrl = SoundcloudParsingHelper .getUsersFromApi (collector , apiUrl );
263270
264271 while (!nextPageUrl .isEmpty () && collector .getItems ().size () < minItems ) {
@@ -271,14 +278,16 @@ public static String getUsersFromApiMinItems(final int minItems,
271278 /**
272279 * Fetch the user items from the given API and commit each of them to the collector.
273280 *
274- * @return the next streams url, empty if don't have
281+ * @return the next stream's url, empty if don't have
275282 */
276283 @ Nonnull
277284 public static String getUsersFromApi (final ChannelInfoItemsCollector collector ,
278- final String apiUrl ) throws IOException ,
279- ReCaptchaException , ParsingException {
280- final String response = NewPipe .getDownloader ().get (apiUrl , SoundCloud .getLocalization ())
281- .responseBody ();
285+ final String apiUrl )
286+ throws IOException , ReCaptchaException , ParsingException , HttpResponseException {
287+ final String response = NewPipe .getDownloader ()
288+ .get (apiUrl , SoundCloud .getLocalization ())
289+ .ensureSuccessResponseCode ()
290+ .responseBody ();
282291 final JsonObject responseObject ;
283292
284293 try {
@@ -301,16 +310,16 @@ public static String getUsersFromApi(final ChannelInfoItemsCollector collector,
301310 /**
302311 * Fetch the streams from the given API and commit each of them to the collector.
303312 * <p>
304- * This differ from {@link #getStreamsFromApi(StreamInfoItemsCollector, String)} in the sense
313+ * This differs from {@link #getStreamsFromApi(StreamInfoItemsCollector, String)} in the sense
305314 * that they will always get MIN_ITEMS or more items.
306315 *
307- * @param minItems the method will return only when it have extracted that many items
316+ * @param minItems the method will return only when it has extracted this many items
308317 * (equal or more)
309318 */
310319 public static String getStreamsFromApiMinItems (final int minItems ,
311320 final StreamInfoItemsCollector collector ,
312- final String apiUrl ) throws IOException ,
313- ReCaptchaException , ParsingException {
321+ final String apiUrl )
322+ throws IOException , ReCaptchaException , ParsingException , HttpResponseException {
314323 String nextPageUrl = SoundcloudParsingHelper .getStreamsFromApi (collector , apiUrl );
315324
316325 while (!nextPageUrl .isEmpty () && collector .getItems ().size () < minItems ) {
@@ -328,18 +337,16 @@ public static String getStreamsFromApiMinItems(final int minItems,
328337 @ Nonnull
329338 public static String getStreamsFromApi (final StreamInfoItemsCollector collector ,
330339 final String apiUrl ,
331- final boolean charts ) throws IOException ,
332- ReCaptchaException , ParsingException {
333- final Response response = NewPipe .getDownloader ().get (apiUrl , SoundCloud
334- .getLocalization ());
335- if (response .responseCode () >= 400 ) {
336- throw new IOException ("Could not get streams from API, HTTP " + response
337- .responseCode ());
338- }
340+ final boolean charts )
341+ throws IOException , ReCaptchaException , ParsingException , HttpResponseException {
342+ final String responseBody = NewPipe .getDownloader ()
343+ .get (apiUrl , SoundCloud .getLocalization ())
344+ .ensureResponseCodeIsNotError ()
345+ .responseBody ();
339346
340347 final JsonObject responseObject ;
341348 try {
342- responseObject = JsonParser .object ().from (response . responseBody () );
349+ responseObject = JsonParser .object ().from (responseBody );
343350 } catch (final JsonParserException e ) {
344351 throw new ParsingException ("Could not parse json response" , e );
345352 }
@@ -370,23 +377,22 @@ private static String getNextPageUrl(@Nonnull final JsonObject response) {
370377 }
371378
372379 public static String getStreamsFromApi (final StreamInfoItemsCollector collector ,
373- final String apiUrl ) throws ReCaptchaException ,
374- ParsingException , IOException {
380+ final String apiUrl )
381+ throws ReCaptchaException , ParsingException , IOException , HttpResponseException {
375382 return getStreamsFromApi (collector , apiUrl , false );
376383 }
377384
378385 public static String getInfoItemsFromApi (final MultiInfoItemsCollector collector ,
379- final String apiUrl ) throws ReCaptchaException ,
380- ParsingException , IOException {
381- final Response response = NewPipe .getDownloader ().get (apiUrl , SoundCloud .getLocalization ());
382- if (response .responseCode () >= 400 ) {
383- throw new IOException ("Could not get streams from API, HTTP "
384- + response .responseCode ());
385- }
386+ final String apiUrl )
387+ throws ReCaptchaException , ParsingException , IOException , HttpResponseException {
388+ final String responseBody = NewPipe .getDownloader ()
389+ .get (apiUrl , SoundCloud .getLocalization ())
390+ .ensureResponseCodeIsNotError ()
391+ .responseBody ();
386392
387393 final JsonObject responseObject ;
388394 try {
389- responseObject = JsonParser .object ().from (response . responseBody () );
395+ responseObject = JsonParser .object ().from (responseBody );
390396 } catch (final JsonParserException e ) {
391397 throw new ParsingException ("Could not parse json response" , e );
392398 }
0 commit comments