Bandcamp service with support for streams and searches
This commit is contained in:
parent
d83787a5ca
commit
a579337c9a
|
@ -6,6 +6,7 @@ dependencies {
|
||||||
implementation 'org.mozilla:rhino:1.7.7.1'
|
implementation 'org.mozilla:rhino:1.7.7.1'
|
||||||
implementation 'com.github.spotbugs:spotbugs-annotations:3.1.0'
|
implementation 'com.github.spotbugs:spotbugs-annotations:3.1.0'
|
||||||
implementation 'org.nibor.autolink:autolink:0.8.0'
|
implementation 'org.nibor.autolink:autolink:0.8.0'
|
||||||
|
implementation 'org.json:json:20190722'
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
}
|
}
|
|
@ -4,6 +4,7 @@ import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.extractor.services.bandcamp.BandcampService;
|
||||||
import org.schabi.newpipe.extractor.services.media_ccc.MediaCCCService;
|
import org.schabi.newpipe.extractor.services.media_ccc.MediaCCCService;
|
||||||
import org.schabi.newpipe.extractor.services.peertube.PeertubeService;
|
import org.schabi.newpipe.extractor.services.peertube.PeertubeService;
|
||||||
import org.schabi.newpipe.extractor.services.soundcloud.SoundcloudService;
|
import org.schabi.newpipe.extractor.services.soundcloud.SoundcloudService;
|
||||||
|
@ -39,6 +40,7 @@ public final class ServiceList {
|
||||||
public static final SoundcloudService SoundCloud;
|
public static final SoundcloudService SoundCloud;
|
||||||
public static final MediaCCCService MediaCCC;
|
public static final MediaCCCService MediaCCC;
|
||||||
public static final PeertubeService PeerTube;
|
public static final PeertubeService PeerTube;
|
||||||
|
public static final BandcampService bandcamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When creating a new service, put this service in the end of this list,
|
* When creating a new service, put this service in the end of this list,
|
||||||
|
@ -49,7 +51,8 @@ public final class ServiceList {
|
||||||
YouTube = new YoutubeService(0),
|
YouTube = new YoutubeService(0),
|
||||||
SoundCloud = new SoundcloudService(1),
|
SoundCloud = new SoundcloudService(1),
|
||||||
MediaCCC = new MediaCCCService(2),
|
MediaCCC = new MediaCCCService(2),
|
||||||
PeerTube = new PeertubeService(3)
|
PeerTube = new PeertubeService(3),
|
||||||
|
bandcamp = new BandcampService(4)
|
||||||
));
|
));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
// Created by Fynn Godau 2019, licensed GNU GPL version 3 or later
|
||||||
|
|
||||||
|
package org.schabi.newpipe.extractor.services.bandcamp;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
|
import org.schabi.newpipe.extractor.channel.ChannelExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.comments.CommentsExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
|
import org.schabi.newpipe.extractor.kiosk.KioskList;
|
||||||
|
import org.schabi.newpipe.extractor.linkhandler.*;
|
||||||
|
import org.schabi.newpipe.extractor.playlist.PlaylistExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.search.SearchExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampSearchExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampStreamExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.services.bandcamp.linkHandler.BandcampChannelLinkHandlerFactory;
|
||||||
|
import org.schabi.newpipe.extractor.services.bandcamp.linkHandler.BandcampSearchQueryHandlerFactory;
|
||||||
|
import org.schabi.newpipe.extractor.services.bandcamp.linkHandler.BandcampStreamLinkHandlerFactory;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.AUDIO;
|
||||||
|
|
||||||
|
public class BandcampService extends StreamingService {
|
||||||
|
|
||||||
|
public BandcampService(int id) {
|
||||||
|
super(id, "bandcamp", Collections.singletonList(AUDIO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getBaseUrl() {
|
||||||
|
return "https://bandcamp.com";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LinkHandlerFactory getStreamLHFactory() {
|
||||||
|
return new BandcampStreamLinkHandlerFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListLinkHandlerFactory getChannelLHFactory() {
|
||||||
|
//return new BandcampChannelLinkHandlerFactory(); TODO
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListLinkHandlerFactory getPlaylistLHFactory() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchQueryHandlerFactory getSearchQHFactory() {
|
||||||
|
return new BandcampSearchQueryHandlerFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListLinkHandlerFactory getCommentsLHFactory() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchExtractor getSearchExtractor(SearchQueryHandler queryHandler) {
|
||||||
|
return new BandcampSearchExtractor(this, queryHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SuggestionExtractor getSuggestionExtractor() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SubscriptionExtractor getSubscriptionExtractor() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KioskList getKioskList() throws ExtractionException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelExtractor getChannelExtractor(ListLinkHandler linkHandler) throws ExtractionException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlaylistExtractor getPlaylistExtractor(ListLinkHandler linkHandler) throws ExtractionException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamExtractor getStreamExtractor(LinkHandler linkHandler) throws ExtractionException {
|
||||||
|
return new BandcampStreamExtractor(this, linkHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommentsExtractor getCommentsExtractor(ListLinkHandler linkHandler) throws ExtractionException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
// Created by Fynn Godau 2019, licensed GNU GPL version 3 or later
|
||||||
|
|
||||||
|
package org.schabi.newpipe.extractor.services.bandcamp.extractors;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class BandcampExtractorHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get JSON behind <code>var $variable = </code> out of web page
|
||||||
|
* <br/<br/>
|
||||||
|
* Originally a part of bandcampDirect.
|
||||||
|
*
|
||||||
|
* @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 getJSONFromJavaScriptVariables(String html, String variable) throws JSONException, ParsingException {
|
||||||
|
|
||||||
|
String[] part = html.split("var " + variable + " = ");
|
||||||
|
|
||||||
|
String firstHalfGone = part[1];
|
||||||
|
|
||||||
|
firstHalfGone = firstHalfGone.replaceAll("\" \\+ \"", "");
|
||||||
|
|
||||||
|
int position = -1;
|
||||||
|
int level = 0;
|
||||||
|
for (char character : firstHalfGone.toCharArray()) {
|
||||||
|
position++;
|
||||||
|
|
||||||
|
switch (character) {
|
||||||
|
case '{':
|
||||||
|
level++;
|
||||||
|
continue;
|
||||||
|
case '}':
|
||||||
|
level--;
|
||||||
|
if (level == 0) {
|
||||||
|
return new JSONObject(firstHalfGone.substring(0, position + 1)
|
||||||
|
.replaceAll(" {4}//.+", "") // Remove comments in JSON
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ParsingException("Unexpected HTML: JSON never ends");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concatenate all non-null and non-empty strings together while separating them using
|
||||||
|
* the comma parameter
|
||||||
|
*/
|
||||||
|
public static String smartConcatenate(String[] strings, String comma) {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
|
||||||
|
// Remove empty strings
|
||||||
|
ArrayList<String> list = new ArrayList<>(Arrays.asList(strings));
|
||||||
|
for (int i = list.size() - 1; i >= 0; i--) {
|
||||||
|
if (list.get(i) == null || list.get(i).isEmpty()) {
|
||||||
|
list.remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append remaining strings to result
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
String string = list.get(i);
|
||||||
|
result.append(string);
|
||||||
|
|
||||||
|
if (i != list.size() - 1) {
|
||||||
|
// This is not the last iteration yet
|
||||||
|
result.append(comma);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.valueOf(result);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
// Created by Fynn Godau 2019, licensed GNU GPL version 3 or later
|
||||||
|
|
||||||
|
package org.schabi.newpipe.extractor.services.bandcamp.extractors;
|
||||||
|
|
||||||
|
import org.jsoup.Jsoup;
|
||||||
|
import org.jsoup.nodes.Document;
|
||||||
|
import org.jsoup.nodes.Element;
|
||||||
|
import org.jsoup.select.Elements;
|
||||||
|
import org.schabi.newpipe.extractor.InfoItem;
|
||||||
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
|
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
|
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
|
||||||
|
import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector;
|
||||||
|
import org.schabi.newpipe.extractor.search.SearchExtractor;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class BandcampSearchExtractor extends SearchExtractor {
|
||||||
|
|
||||||
|
public BandcampSearchExtractor(StreamingService service, SearchQueryHandler linkHandler) {
|
||||||
|
super(service, linkHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSearchSuggestion() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InfoItemsPage<InfoItem> getPage(String pageUrl) throws IOException, ExtractionException {
|
||||||
|
// okay apparently this is where we DOWNLOAD the page and then COMMIT its ENTRIES to an INFOITEMPAGE
|
||||||
|
String html = getDownloader().get(pageUrl).responseBody();
|
||||||
|
|
||||||
|
InfoItemsSearchCollector collector = getInfoItemSearchCollector();
|
||||||
|
|
||||||
|
|
||||||
|
Document d = Jsoup.parse(html);
|
||||||
|
|
||||||
|
Elements searchResultsElements = d.getElementsByClass("searchresult");
|
||||||
|
|
||||||
|
for (Element searchResult :
|
||||||
|
searchResultsElements) {
|
||||||
|
|
||||||
|
Element resultInfo = searchResult.getElementsByClass("result-info").first();
|
||||||
|
|
||||||
|
String type = resultInfo
|
||||||
|
.getElementsByClass("itemtype").first().text();
|
||||||
|
|
||||||
|
String image = null;
|
||||||
|
Element img = searchResult.getElementsByClass("art").first()
|
||||||
|
.getElementsByTag("img").first();
|
||||||
|
if (img != null) {
|
||||||
|
image = img.attr("src");
|
||||||
|
}
|
||||||
|
|
||||||
|
String heading = resultInfo.getElementsByClass("heading").text();
|
||||||
|
|
||||||
|
String subhead = resultInfo.getElementsByClass("subhead").text();
|
||||||
|
|
||||||
|
String url = resultInfo.getElementsByClass("itemurl").text();
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
case "FAN":
|
||||||
|
//collector.commit Channel (?) with heading, url, image
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "ARTIST":
|
||||||
|
String id = resultInfo.getElementsByClass("itemurl").first()
|
||||||
|
.getElementsByTag("a").first()
|
||||||
|
.attr("href") // the link contains the id
|
||||||
|
.split("search_item_id=")
|
||||||
|
[1] // the number is behind its name
|
||||||
|
.split("&") // there is another attribute behind the name
|
||||||
|
[0]; // get the number
|
||||||
|
|
||||||
|
//searchResults.add(new Artist(heading, Long.parseLong(id), image, subhead));
|
||||||
|
//collector.commit Channel with heading, id, image, subhead
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "ALBUM":
|
||||||
|
String artist = subhead.split(" by")[0];
|
||||||
|
//searchResults.add(new Album(heading, artist, url, image));
|
||||||
|
//collector.commit Playlist with heading, artist, url, image
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "TRACK":
|
||||||
|
String album = subhead.split("from ")[0].split(" by")[0];
|
||||||
|
|
||||||
|
String[] splitBy = subhead.split(" by");
|
||||||
|
String artist1 = null;
|
||||||
|
if (splitBy.length > 1) {
|
||||||
|
artist1 = subhead.split(" by")[1];
|
||||||
|
}
|
||||||
|
collector.commit(new BandcampStreamInfoItemExtractor(heading, url, image, artist1, album));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return new InfoItemsPage<>(getInfoItemSearchCollector(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public InfoItemsPage<InfoItem> getInitialPage() throws IOException, ExtractionException {
|
||||||
|
return getPage(getUrl());//new InfoItemsPage<>(getInfoItemSearchCollector(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getNextPageUrl() throws IOException, ExtractionException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,224 @@
|
||||||
|
// Created by Fynn Godau 2019, licensed GNU GPL version 3 or later
|
||||||
|
|
||||||
|
package org.schabi.newpipe.extractor.services.bandcamp.extractors;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.jsoup.Jsoup;
|
||||||
|
import org.jsoup.nodes.Document;
|
||||||
|
import org.schabi.newpipe.extractor.MediaFormat;
|
||||||
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
|
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.linkhandler.LinkHandler;
|
||||||
|
import org.schabi.newpipe.extractor.localization.DateWrapper;
|
||||||
|
import org.schabi.newpipe.extractor.stream.*;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class BandcampStreamExtractor extends StreamExtractor {
|
||||||
|
|
||||||
|
private JSONObject albumJson;
|
||||||
|
private JSONObject current;
|
||||||
|
private Document document;
|
||||||
|
|
||||||
|
public BandcampStreamExtractor(StreamingService service, LinkHandler linkHandler) {
|
||||||
|
super(service, linkHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
|
||||||
|
String html = downloader.get(getLinkHandler().getUrl()).responseBody();
|
||||||
|
document = Jsoup.parse(html);
|
||||||
|
albumJson = getAlbumInfoJson(html);
|
||||||
|
current = albumJson.getJSONObject("current");
|
||||||
|
|
||||||
|
if (albumJson.getJSONArray("trackinfo").length() > 1) {
|
||||||
|
// In this case, we are actually viewing an album page!
|
||||||
|
throw new ExtractionException("Page is actually an album, not a track");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the JSON that contains album's metadata from page
|
||||||
|
*
|
||||||
|
* @param html Website
|
||||||
|
* @return Album metadata JSON
|
||||||
|
* @throws ParsingException In case of a faulty website
|
||||||
|
*/
|
||||||
|
public static JSONObject getAlbumInfoJson(String html) throws ParsingException {
|
||||||
|
try {
|
||||||
|
return BandcampExtractorHelper.getJSONFromJavaScriptVariables(html, "TralbumData");
|
||||||
|
} catch (JSONException e) {
|
||||||
|
throw new ParsingException("Faulty JSON", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getName() throws ParsingException {
|
||||||
|
return current.getString("title");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getUploaderUrl() throws ParsingException {
|
||||||
|
String[] parts = getUrl().split("/");
|
||||||
|
// https: (/) (/) * .bandcamp.com (/) and leave out the rest
|
||||||
|
return "https://" + parts[2] + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getUrl() throws ParsingException {
|
||||||
|
return albumJson.getString("url").replace("http://", "https://");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getUploaderName() throws ParsingException {
|
||||||
|
return albumJson.getString("artist");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getTextualUploadDate() throws ParsingException {
|
||||||
|
return current.getString("release_date");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public DateWrapper getUploadDate() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getThumbnailUrl() throws ParsingException {
|
||||||
|
return document.getElementsByAttributeValue("property", "og:image").get(0).attr("content");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getUploaderAvatarUrl() {
|
||||||
|
return document.getElementsByClass("band-photo").first().attr("src");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return BandcampExtractorHelper.smartConcatenate(
|
||||||
|
new String[]{
|
||||||
|
getStringOrNull(current, "about"),
|
||||||
|
getStringOrNull(current, "lyrics"),
|
||||||
|
getStringOrNull(current, "credits")
|
||||||
|
}, "\n\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Avoid exceptions like "<code>JSONObject["about"] not a string.</code>" and instead just return null.
|
||||||
|
* This is for the case that the actual JSON has something like <code>"about": null</code>.
|
||||||
|
*/
|
||||||
|
private String getStringOrNull(JSONObject jsonObject, String value) {
|
||||||
|
try {
|
||||||
|
return jsonObject.getString(value);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAgeLimit() throws ParsingException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLength() throws ParsingException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTimeStamp() throws ParsingException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getViewCount() throws ParsingException {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLikeCount() throws ParsingException {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getDislikeCount() throws ParsingException {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getDashMpdUrl() throws ParsingException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getHlsUrl() throws ParsingException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AudioStream> getAudioStreams() throws IOException, ExtractionException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<VideoStream> getVideoStreams() throws IOException, ExtractionException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<VideoStream> getVideoOnlyStreams() throws IOException, ExtractionException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public List<SubtitlesStream> getSubtitlesDefault() throws IOException, ExtractionException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public List<SubtitlesStream> getSubtitles(MediaFormat format) throws IOException, ExtractionException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamType getStreamType() throws ParsingException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamInfoItem getNextStream() throws IOException, ExtractionException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamInfoItemsCollector getRelatedStreams() throws IOException, ExtractionException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
// Created by Fynn Godau 2019, licensed GNU GPL version 3 or later
|
||||||
|
|
||||||
|
package org.schabi.newpipe.extractor.services.bandcamp.extractors;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.localization.DateWrapper;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public class BandcampStreamInfoItemExtractor implements StreamInfoItemExtractor {
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
private String url;
|
||||||
|
private String cover;
|
||||||
|
private String artist;
|
||||||
|
private String albumName;
|
||||||
|
|
||||||
|
public BandcampStreamInfoItemExtractor(String title, String url, String cover, String artist, String albumName) {
|
||||||
|
this.title = title;
|
||||||
|
this.url = url;
|
||||||
|
this.cover = cover;
|
||||||
|
this.artist = artist;
|
||||||
|
this.albumName = albumName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamType getStreamType() throws ParsingException {
|
||||||
|
return StreamType.AUDIO_STREAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getDuration() throws ParsingException {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getViewCount() throws ParsingException {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUploaderName() throws ParsingException {
|
||||||
|
return artist;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUploaderUrl() throws ParsingException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getTextualUploadDate() throws ParsingException {
|
||||||
|
return null; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public DateWrapper getUploadDate() throws ParsingException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() throws ParsingException {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrl() throws ParsingException {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getThumbnailUrl() throws ParsingException {
|
||||||
|
return cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* There are no ads just like that, duh
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isAd() throws ParsingException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
// Created by Fynn Godau 2019, licensed GNU GPL version 3 or later
|
||||||
|
|
||||||
|
package org.schabi.newpipe.extractor.services.bandcamp.linkHandler;
|
||||||
|
|
||||||
|
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.linkhandler.LinkHandlerFactory;
|
||||||
|
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
|
||||||
|
import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper;
|
||||||
|
import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampStreamExtractor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Artist do have IDs that are useful
|
||||||
|
*/
|
||||||
|
public class BandcampChannelLinkHandlerFactory extends ListLinkHandlerFactory {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId(String url) throws ParsingException {
|
||||||
|
try {
|
||||||
|
String response = NewPipe.getDownloader().get(url).responseBody();
|
||||||
|
return BandcampStreamExtractor.getAlbumInfoJson(response)
|
||||||
|
.getString("band_id");
|
||||||
|
} catch (IOException | ReCaptchaException e) {
|
||||||
|
throw new ParsingException("Download failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrl(String id, List<String> contentFilter, String sortFilter) throws ParsingException {
|
||||||
|
return null; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches <code>* .bandcamp.com</code> as well as custom domains
|
||||||
|
* where the profile is at <code>* . * /releases</code>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onAcceptUrl(String url) throws ParsingException {
|
||||||
|
|
||||||
|
// Ends with "bandcamp.com" or "bandcamp.com/"?
|
||||||
|
boolean endsWithBandcampCom = url.endsWith("bandcamp.com")
|
||||||
|
|| url.endsWith("bandcamp.com/");
|
||||||
|
|
||||||
|
// Is a subdomain of bandcamp.com?
|
||||||
|
boolean isBandcampComSubdomain = url.matches("https?://.+\\.bandcamp\\.com");
|
||||||
|
|
||||||
|
// Is root of bandcamp.com subdomain?
|
||||||
|
boolean isBandcampComArtistPage = endsWithBandcampCom && isBandcampComSubdomain;
|
||||||
|
|
||||||
|
boolean isCustomDomainReleases = url.matches("https?://.+\\..+/releases/?(?!.)");
|
||||||
|
|
||||||
|
return isBandcampComArtistPage || isCustomDomainReleases;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Created by Fynn Godau 2019, licensed GNU GPL version 3 or later
|
||||||
|
|
||||||
|
package org.schabi.newpipe.extractor.services.bandcamp.linkHandler;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandlerFactory;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class BandcampSearchQueryHandlerFactory extends SearchQueryHandlerFactory {
|
||||||
|
|
||||||
|
private static final String SEARCH_URL = "https://bandcamp.com/search?q=";
|
||||||
|
|
||||||
|
public static final String CHARSET_UTF_8 = "UTF-8";
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrl(String query, List<String> contentFilter, String sortFilter) throws ParsingException {
|
||||||
|
try {
|
||||||
|
|
||||||
|
return SEARCH_URL +
|
||||||
|
URLEncoder.encode(query, CHARSET_UTF_8);
|
||||||
|
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new ParsingException("query \"" + query + "\" could not be encoded", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
// Created by Fynn Godau 2019, licensed GNU GPL version 3 or later
|
||||||
|
|
||||||
|
package org.schabi.newpipe.extractor.services.bandcamp.linkHandler;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks do have IDs, but they are not really useful. That's why id = url.
|
||||||
|
* Instead, URLs are cleaned up so that they always look the same.
|
||||||
|
*/
|
||||||
|
public class BandcampStreamLinkHandlerFactory extends LinkHandlerFactory {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see BandcampStreamLinkHandlerFactory
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getId(String url) throws ParsingException {
|
||||||
|
return getUrl(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up url
|
||||||
|
* @see BandcampStreamLinkHandlerFactory
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getUrl(String url) {
|
||||||
|
if (url.endsWith("/"))
|
||||||
|
url = url.substring(0, url.length() - 1);
|
||||||
|
url = url.replace("http://", "https://").toLowerCase();
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sometimes, the root page of an artist is also an album or track
|
||||||
|
* page. In that case, it is assumed that one actually wants to open
|
||||||
|
* the profile and not the track it has set as the default one.
|
||||||
|
* <br/><br/>Urls are expected to be in this format to account for
|
||||||
|
* custom domains:
|
||||||
|
* <br/><code>https:// * . * /track/ *</code>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onAcceptUrl(String url) {
|
||||||
|
return getUrl(url).matches("https?://.+\\..+/track/.+");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
// Created by Fynn Godau 2019, licensed GNU GPL version 3 or later
|
||||||
|
|
||||||
|
package org.schabi.newpipe.extractor.services.bandcamp;
|
||||||
|
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.schabi.newpipe.DownloaderTestImpl;
|
||||||
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.services.bandcamp.linkHandler.BandcampChannelLinkHandlerFactory;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for {@link BandcampChannelLinkHandlerFactory}
|
||||||
|
*/
|
||||||
|
public class BandcampChannelLinkHandlerFactoryTest {
|
||||||
|
private static BandcampChannelLinkHandlerFactory linkHandler;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUp() {
|
||||||
|
linkHandler = new BandcampChannelLinkHandlerFactory();
|
||||||
|
NewPipe.init(DownloaderTestImpl.getInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAcceptUrl() throws ParsingException {
|
||||||
|
// Tests expecting true
|
||||||
|
assertTrue(linkHandler.acceptUrl("http://interovgm.com/releases/"));
|
||||||
|
assertTrue(linkHandler.acceptUrl("https://interovgm.com/releases"));
|
||||||
|
assertTrue(linkHandler.acceptUrl("http://zachbenson.bandcamp.com"));
|
||||||
|
|
||||||
|
// Tests expecting false
|
||||||
|
assertFalse(linkHandler.acceptUrl("https://bandcamp.com"));
|
||||||
|
assertFalse(linkHandler.acceptUrl("https://zachbenson.bandcamp.com/track/kitchen"));
|
||||||
|
assertFalse(linkHandler.acceptUrl("https://zachbenson.bandcamp.com/"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
// Created by Fynn Godau 2019, licensed GNU GPL version 3 or later
|
||||||
|
|
||||||
|
package org.schabi.newpipe.extractor.services.bandcamp;
|
||||||
|
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.schabi.newpipe.DownloaderTestImpl;
|
||||||
|
import org.schabi.newpipe.extractor.InfoItem;
|
||||||
|
import org.schabi.newpipe.extractor.ListExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
|
import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampSearchExtractor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.schabi.newpipe.extractor.ServiceList.bandcamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for {@link BandcampSearchExtractor}
|
||||||
|
*/
|
||||||
|
public class BandcampSearchExtractorTest {
|
||||||
|
|
||||||
|
private static BandcampSearchExtractor extractor;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUp() {
|
||||||
|
NewPipe.init(DownloaderTestImpl.getInstance());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether searching bandcamp for "best friend's basement" returns
|
||||||
|
* the accordingly named song by Zach Benson
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testBestFriendsBasement() throws ExtractionException, IOException {
|
||||||
|
extractor = (BandcampSearchExtractor) bandcamp
|
||||||
|
.getSearchExtractor("best friend's basement");
|
||||||
|
|
||||||
|
ListExtractor.InfoItemsPage<InfoItem> page = extractor.getInitialPage();
|
||||||
|
InfoItem bestFriendsBasement = page.getItems().get(0);
|
||||||
|
|
||||||
|
// The track by Zach Benson should be the first result, no?
|
||||||
|
assertEquals("Best Friend's Basement", bestFriendsBasement.getName());
|
||||||
|
assertTrue(bestFriendsBasement.getThumbnailUrl().endsWith(".jpg"));
|
||||||
|
assertTrue(bestFriendsBasement.getThumbnailUrl().contains("f4.bcbits.com/img/"));
|
||||||
|
assertEquals(InfoItem.InfoType.STREAM, bestFriendsBasement.getInfoType());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
// Created by Fynn Godau 2019, licensed GNU GPL version 3 or later
|
||||||
|
|
||||||
|
package org.schabi.newpipe.extractor.services.bandcamp;
|
||||||
|
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.schabi.newpipe.DownloaderTestImpl;
|
||||||
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.services.bandcamp.linkHandler.BandcampSearchQueryHandlerFactory;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.schabi.newpipe.extractor.ServiceList.bandcamp;
|
||||||
|
|
||||||
|
public class BandcampSearchQueryHandlerFactoryTest {
|
||||||
|
|
||||||
|
static BandcampSearchQueryHandlerFactory searchQuery;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUp() {
|
||||||
|
NewPipe.init(DownloaderTestImpl.getInstance());
|
||||||
|
|
||||||
|
searchQuery = (BandcampSearchQueryHandlerFactory) bandcamp
|
||||||
|
.getSearchQHFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncoding() throws ParsingException {
|
||||||
|
// Note: this isn't exactly as bandcamp does it (it wouldn't encode '!'), but both works
|
||||||
|
assertEquals("https://bandcamp.com/search?q=hello%21%22%C2%A7%24%25%26%2F%28%29%3D", searchQuery.getUrl("hello!\"§$%&/()="));
|
||||||
|
// Note: bandcamp uses %20 instead of '+', but both works
|
||||||
|
assertEquals("https://bandcamp.com/search?q=search+query+with+spaces", searchQuery.getUrl("search query with spaces"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
// Created by Fynn Godau 2019, licensed GNU GPL version 3 or later
|
||||||
|
|
||||||
|
package org.schabi.newpipe.extractor.services.bandcamp;
|
||||||
|
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.schabi.newpipe.DownloaderTestImpl;
|
||||||
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampStreamExtractor;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.schabi.newpipe.extractor.ServiceList.bandcamp;
|
||||||
|
|
||||||
|
public class BandcampStreamExtractorTest {
|
||||||
|
|
||||||
|
private static BandcampStreamExtractor extractor;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUp() throws Exception {
|
||||||
|
NewPipe.init(DownloaderTestImpl.getInstance());
|
||||||
|
extractor = (BandcampStreamExtractor) bandcamp
|
||||||
|
.getStreamExtractor("https://zachbenson.bandcamp.com/track/kitchen");
|
||||||
|
extractor.fetchPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = ExtractionException.class)
|
||||||
|
public void testAlbum() throws ExtractionException {
|
||||||
|
bandcamp.getStreamExtractor("https://zachbenson.bandcamp.com/album/prom");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testServiceId() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testName() throws ParsingException {
|
||||||
|
assertEquals("kitchen", extractor.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUrl() throws ParsingException {
|
||||||
|
assertEquals("https://zachbenson.bandcamp.com/track/kitchen", extractor.getUrl());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testArtistUrl() throws ParsingException {
|
||||||
|
assertEquals("https://zachbenson.bandcamp.com/", extractor.getUploaderUrl());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDescription() {
|
||||||
|
assertEquals(831, extractor.getDescription().length());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testArtistProfilePicture() {
|
||||||
|
String url = extractor.getUploaderAvatarUrl();
|
||||||
|
assertTrue(url.contains("://f4.bcbits.com/img/") && url.endsWith(".jpg"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
// Created by Fynn Godau 2019, licensed GNU GPL version 3 or later
|
||||||
|
|
||||||
|
package org.schabi.newpipe.extractor.services.bandcamp;
|
||||||
|
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.schabi.newpipe.DownloaderTestImpl;
|
||||||
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.services.bandcamp.linkHandler.BandcampStreamLinkHandlerFactory;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for {@link BandcampStreamLinkHandlerFactory}
|
||||||
|
*/
|
||||||
|
public class BandcampStreamLinkHandlerFactoryTest {
|
||||||
|
|
||||||
|
private static BandcampStreamLinkHandlerFactory linkHandler;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUp() {
|
||||||
|
linkHandler = new BandcampStreamLinkHandlerFactory();
|
||||||
|
NewPipe.init(DownloaderTestImpl.getInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUrlCleanup() {
|
||||||
|
assertEquals("https://zachbenson.bandcamp.com/track/u-i-tonite", linkHandler.getUrl("http://ZachBenson.Bandcamp.COM/Track/U-I-Tonite/"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAcceptUrl() throws ParsingException {
|
||||||
|
// Tests expecting false
|
||||||
|
assertFalse(linkHandler.acceptUrl("http://interovgm.com/releases/"));
|
||||||
|
assertFalse(linkHandler.acceptUrl("https://interovgm.com/releases"));
|
||||||
|
assertFalse(linkHandler.acceptUrl("http://zachbenson.bandcamp.com"));
|
||||||
|
assertFalse(linkHandler.acceptUrl("https://bandcamp.com"));
|
||||||
|
assertFalse(linkHandler.acceptUrl("https://zachbenson.bandcamp.com/"));
|
||||||
|
|
||||||
|
// Tests expecting true
|
||||||
|
assertTrue(linkHandler.acceptUrl("https://zachbenson.bandcamp.com/track/kitchen"));
|
||||||
|
assertTrue(linkHandler.acceptUrl("http://ZachBenson.Bandcamp.COM/Track/U-I-Tonite/"));
|
||||||
|
assertTrue(linkHandler.acceptUrl("https://interovgm.com/track/title"));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue