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

159 lines
6.2 KiB
Java
Raw Normal View History

// Created by Fynn Godau 2019, licensed GNU GPL version 3 or later
package org.schabi.newpipe.extractor.services.bandcamp.extractors;
import com.grack.nanojson.JsonObject;
import com.grack.nanojson.JsonParser;
import com.grack.nanojson.JsonParserException;
import com.grack.nanojson.JsonWriter;
2020-10-08 17:56:03 +02:00
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
import org.schabi.newpipe.extractor.localization.DateWrapper;
2020-06-04 19:04:25 +02:00
import org.schabi.newpipe.extractor.utils.Utils;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
public class BandcampExtractorHelper {
/**
2020-10-08 17:56:03 +02:00
* <p>Get an attribute of a web page as JSON
*
* <p>Originally a part of bandcampDirect.</p>
*
* @param html The HTML where the JSON we're looking for is stored inside a
* variable inside some JavaScript block
* @param variable Name of the variable
* @return The JsonObject stored in the variable with this name
*/
public static JsonObject getJsonData(final String html, final String variable)
throws JsonParserException, ArrayIndexOutOfBoundsException {
final Document document = Jsoup.parse(html);
final String json = document.getElementsByAttribute(variable).attr(variable);
2020-10-08 17:56:03 +02:00
return JsonParser.object().from(json);
}
/**
* Translate all these parameters together to the URL of the corresponding album or track
* using the mobile api
*/
public static String getStreamUrlFromIds(final long bandId, final long itemId, final String itemType)
throws ParsingException {
try {
final String jsonString = NewPipe.getDownloader().get(
"https://bandcamp.com/api/mobile/22/tralbum_details?band_id=" + bandId
+ "&tralbum_id=" + itemId + "&tralbum_type=" + itemType.substring(0, 1))
.responseBody();
return JsonParser.object().from(jsonString).getString("bandcamp_url").replace("http://", "https://");
} catch (final JsonParserException | ReCaptchaException | IOException e) {
throw new ParsingException("Ids could not be translated to URL", e);
}
}
/**
* Concatenate all non-null and non-empty strings together while separating them using
* the comma parameter
*/
public static String smartConcatenate(final String[] strings, final String comma) {
final StringBuilder result = new StringBuilder();
// Remove empty strings
final ArrayList<String> list = new ArrayList<>(Arrays.asList(strings));
for (int i = list.size() - 1; i >= 0; i--) {
if (Utils.isNullOrEmpty(list.get(i)) || list.get(i).equals("null")) {
list.remove(i);
}
}
// Append remaining strings to result
for (int i = 0; i < list.size(); i++) {
result.append(list.get(i));
if (i != list.size() - 1) {
// This is not the last iteration yet
result.append(comma);
}
}
return String.valueOf(result);
}
/**
* Fetch artist details from mobile endpoint.
* <a href=https://notabug.org/fynngodau/bandcampDirect/wiki/rewindBandcamp+%E2%80%93+Fetching+artist+details>
* More technical info.</a>
*/
public static JsonObject getArtistDetails(String id) throws ParsingException {
try {
return
JsonParser.object().from(
NewPipe.getDownloader().post(
"https://bandcamp.com/api/mobile/22/band_details",
null,
JsonWriter.string()
.object()
.value("band_id", id)
.end()
.done()
.getBytes()
).responseBody()
);
} catch (final IOException | ReCaptchaException | JsonParserException e) {
throw new ParsingException("Could not download band details", e);
}
}
/**
* @param id The image ID
* @param album Whether this is the cover of an album
* @return Url of image with this ID in size 10 which is 1200x1200 (we could also choose size 0
* but we don't want something as large as 3460x3460 here, do we?)
*/
public static String getImageUrl(final long id, final boolean album) {
return "https://f4.bcbits.com/img/" + (album ? 'a' : "") + id + "_10.jpg";
}
/**
* @return <code>true</code> if the given url looks like it comes from a bandcamp custom domain
* or if it comes from bandcamp.com itself
*/
public static boolean isSupportedDomain(final String url) throws ParsingException {
// Accept all bandcamp.com URLs
if (url.toLowerCase().matches("https?://.+\\.bandcamp\\.com(/.*)?")) return true;
try {
// Accept all other URLs if they contain a <meta> tag that says they are generated by bandcamp
return Jsoup.parse(
NewPipe.getDownloader().get(url).responseBody()
)
.getElementsByAttributeValue("name", "generator")
.attr("content").equals("Bandcamp");
} catch (IOException | ReCaptchaException e) {
throw new ParsingException("Could not determine whether URL is custom domain " +
"(not available? network error?)");
}
}
static DateWrapper parseDate(final String textDate) throws ParsingException {
try {
final Date date = new SimpleDateFormat("dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH).parse(textDate);
final Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
return new DateWrapper(calendar, false);
} catch (final ParseException e) {
throw new ParsingException("Could not extract date", e);
}
}
}