add soundcloud SearchExtractor

This commit is contained in:
Christian Schabesberger 2018-06-01 19:08:49 +02:00
parent 5718d5b8b4
commit ef2ce6854c
4 changed files with 127 additions and 11 deletions

View file

@ -0,0 +1,113 @@
package org.schabi.newpipe.extractor.services.soundcloud;
import com.grack.nanojson.JsonArray;
import com.grack.nanojson.JsonObject;
import com.grack.nanojson.JsonParser;
import com.grack.nanojson.JsonParserException;
import org.schabi.newpipe.extractor.*;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector;
import org.schabi.newpipe.extractor.search.SearchEngine;
import org.schabi.newpipe.extractor.search.SearchExtractor;
import org.schabi.newpipe.extractor.search.SearchQueryUrlHandler;
import org.schabi.newpipe.extractor.utils.Parser;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchQueryUrlHandler.ITEMS_PER_PAGE;
public class SoundcloudSearchExtractor extends SearchExtractor {
private JsonArray searchCollection;
public SoundcloudSearchExtractor(StreamingService service,
SearchQueryUrlHandler urlIdHandler,
String contentCountry) {
super(service, urlIdHandler, contentCountry);
}
@Override
public String getSearchSuggestion() throws ParsingException {
return null;
}
@Nonnull
@Override
public InfoItemsPage<InfoItem> getInitialPage() throws IOException, ExtractionException {
return new InfoItemsPage<>(collectItems(searchCollection), getNextPageUrl());
}
@Override
public String getNextPageUrl() throws IOException, ExtractionException {
return getNextPageUrlFromCurrentUrl(getUrl());
}
@Override
public InfoItemsPage<InfoItem> getPage(String pageUrl) throws IOException, ExtractionException {
final Downloader dl = getDownloader();
try {
searchCollection = JsonParser.object().from(dl.download(pageUrl)).getArray("collection");
} catch (JsonParserException e) {
throw new ParsingException("Could not parse json response", e);
}
return new InfoItemsPage<>(collectItems(searchCollection), getNextPageUrlFromCurrentUrl(pageUrl));
}
@Override
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
final Downloader dl = getDownloader();
final String url = getUrl();
try {
searchCollection = JsonParser.object().from(dl.download(url)).getArray("collection");
} catch (JsonParserException e) {
throw new ParsingException("Could not parse json response", e);
}
if (searchCollection.size() == 0) {
throw new SearchEngine.NothingFoundException("Nothing found");
}
}
private InfoItemsCollector<InfoItem, InfoItemExtractor> collectItems(JsonArray searchCollection) {
final InfoItemsSearchCollector collector = getInfoItemSearchCollector();
for (Object result : searchCollection) {
if (!(result instanceof JsonObject)) continue;
//noinspection ConstantConditions
JsonObject searchResult = (JsonObject) result;
String kind = searchResult.getString("kind", "");
switch (kind) {
case "user":
collector.commit(new SoundcloudChannelInfoItemExtractor(searchResult));
break;
case "track":
collector.commit(new SoundcloudStreamInfoItemExtractor(searchResult));
break;
case "playlist":
collector.commit(new SoundcloudPlaylistInfoItemExtractor(searchResult));
break;
}
}
return collector;
}
private String getNextPageUrlFromCurrentUrl(String currentUrl)
throws MalformedURLException, UnsupportedEncodingException {
final int pageOffset = Integer.parseInt(
Parser.compatParseMap(
new URL(currentUrl)
.getQuery())
.get("offset"));
return currentUrl.replace("&offset=" +
Integer.toString(pageOffset),
"&offset=" + Integer.toString(pageOffset + ITEMS_PER_PAGE));
}
}

View file

@ -8,7 +8,7 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import java.net.URLEncoder;
public class SoundcloudQueryUrlHandler extends SearchQueryUrlHandler { public class SoundcloudSearchQueryUrlHandler extends SearchQueryUrlHandler {
public static final String CHARSET_UTF_8 = "UTF-8"; public static final String CHARSET_UTF_8 = "UTF-8";
public static final String TRACKS = "tracks"; public static final String TRACKS = "tracks";
@ -16,6 +16,8 @@ public class SoundcloudQueryUrlHandler extends SearchQueryUrlHandler {
public static final String PLAYLIST = "playlist"; public static final String PLAYLIST = "playlist";
public static final String ANY = "any"; public static final String ANY = "any";
public static final int ITEMS_PER_PAGE = 10;
@Override @Override
public String getUrl() throws ParsingException { public String getUrl() throws ParsingException {
try { try {
@ -40,7 +42,8 @@ public class SoundcloudQueryUrlHandler extends SearchQueryUrlHandler {
return url + "?q=" + URLEncoder.encode(id, CHARSET_UTF_8) return url + "?q=" + URLEncoder.encode(id, CHARSET_UTF_8)
+ "&client_id=" + SoundcloudParsingHelper.clientId() + "&client_id=" + SoundcloudParsingHelper.clientId()
+ "&limit=10"; + "&limit=" + ITEMS_PER_PAGE
+ "&offset=0";
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
throw new ParsingException("Could not encode query", e); throw new ParsingException("Could not encode query", e);

View file

@ -31,12 +31,12 @@ public class SoundcloudService extends StreamingService {
@Override @Override
public SearchExtractor getSearchExtractor(SearchQueryUrlHandler queryHandler, String contentCountry) { public SearchExtractor getSearchExtractor(SearchQueryUrlHandler queryHandler, String contentCountry) {
return null; return new SoundcloudSearchExtractor(this, queryHandler, contentCountry);
} }
@Override @Override
public SearchQueryUrlHandler getSearchQueryHandler() { public SearchQueryUrlHandler getSearchQueryHandler() {
return null; return new SoundcloudSearchQueryUrlHandler();
} }
@Override @Override
@ -56,17 +56,17 @@ public class SoundcloudService extends StreamingService {
@Override @Override
public StreamExtractor getStreamExtractor(UrlIdHandler urlIdHandler) throws ExtractionException { public StreamExtractor getStreamExtractor(UrlIdHandler urlIdHandler) {
return new SoundcloudStreamExtractor(this, urlIdHandler); return new SoundcloudStreamExtractor(this, urlIdHandler);
} }
@Override @Override
public ChannelExtractor getChannelExtractor(ListUrlIdHandler urlIdHandler) throws ExtractionException { public ChannelExtractor getChannelExtractor(ListUrlIdHandler urlIdHandler) {
return new SoundcloudChannelExtractor(this, urlIdHandler); return new SoundcloudChannelExtractor(this, urlIdHandler);
} }
@Override @Override
public PlaylistExtractor getPlaylistExtractor(ListUrlIdHandler urlIdHandler) throws ExtractionException { public PlaylistExtractor getPlaylistExtractor(ListUrlIdHandler urlIdHandler) {
return new SoundcloudPlaylistExtractor(this, urlIdHandler); return new SoundcloudPlaylistExtractor(this, urlIdHandler);
} }

View file

@ -80,14 +80,14 @@ public class YoutubeSearchExtractor extends SearchExtractor {
private String getNextPageUrlFromCurrentUrl(String currentUrl) private String getNextPageUrlFromCurrentUrl(String currentUrl)
throws MalformedURLException, UnsupportedEncodingException { throws MalformedURLException, UnsupportedEncodingException {
int nextPageNr = Integer.parseInt( final int pageNr = Integer.parseInt(
Parser.compatParseMap( Parser.compatParseMap(
new URL(currentUrl) new URL(currentUrl)
.getQuery()) .getQuery())
.get("page")) + 1; .get("page"));
return currentUrl.replace("&page=" + Integer.toString( nextPageNr-1), return currentUrl.replace("&page=" + Integer.toString( pageNr),
"&page=" + Integer.toString(nextPageNr)); "&page=" + Integer.toString(pageNr + 1));
} }
private InfoItemsSearchCollector collectItems(Document doc) throws NothingFoundException { private InfoItemsSearchCollector collectItems(Document doc) throws NothingFoundException {