2020-04-10 10:51:05 +02:00
|
|
|
package org.schabi.newpipe.extractor.services.soundcloud.extractors;
|
2018-06-01 19:08:49 +02:00
|
|
|
|
2022-08-15 05:49:40 +02:00
|
|
|
import static org.schabi.newpipe.extractor.services.soundcloud.linkHandler.SoundcloudSearchQueryHandlerFactory.ITEMS_PER_PAGE;
|
|
|
|
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
|
|
|
|
2018-06-01 19:08:49 +02:00
|
|
|
import com.grack.nanojson.JsonArray;
|
|
|
|
import com.grack.nanojson.JsonObject;
|
|
|
|
import com.grack.nanojson.JsonParser;
|
|
|
|
import com.grack.nanojson.JsonParserException;
|
2022-03-18 11:12:45 +01:00
|
|
|
|
|
|
|
import org.schabi.newpipe.extractor.InfoItem;
|
|
|
|
import org.schabi.newpipe.extractor.InfoItemExtractor;
|
|
|
|
import org.schabi.newpipe.extractor.InfoItemsCollector;
|
|
|
|
import org.schabi.newpipe.extractor.MetaInfo;
|
2022-08-15 05:49:40 +02:00
|
|
|
import org.schabi.newpipe.extractor.MultiInfoItemsCollector;
|
2022-03-18 11:12:45 +01:00
|
|
|
import org.schabi.newpipe.extractor.Page;
|
|
|
|
import org.schabi.newpipe.extractor.StreamingService;
|
2019-04-28 22:03:16 +02:00
|
|
|
import org.schabi.newpipe.extractor.downloader.Downloader;
|
2018-06-01 19:08:49 +02:00
|
|
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
|
|
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
2019-04-28 22:03:16 +02:00
|
|
|
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
|
2018-06-01 19:08:49 +02:00
|
|
|
import org.schabi.newpipe.extractor.search.SearchExtractor;
|
|
|
|
import org.schabi.newpipe.extractor.utils.Parser;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.UnsupportedEncodingException;
|
|
|
|
import java.net.MalformedURLException;
|
|
|
|
import java.net.URL;
|
2020-12-20 19:54:12 +01:00
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.List;
|
2021-12-27 21:18:39 +01:00
|
|
|
import java.util.function.IntUnaryOperator;
|
2018-06-01 19:08:49 +02:00
|
|
|
|
2022-08-15 05:49:40 +02:00
|
|
|
import javax.annotation.Nonnull;
|
2018-06-01 19:08:49 +02:00
|
|
|
|
|
|
|
public class SoundcloudSearchExtractor extends SearchExtractor {
|
2021-12-27 21:42:43 +01:00
|
|
|
private JsonArray initialSearchCollection;
|
2018-06-01 19:08:49 +02:00
|
|
|
|
2021-05-15 17:51:43 +02:00
|
|
|
public SoundcloudSearchExtractor(final StreamingService service,
|
|
|
|
final SearchQueryHandler linkHandler) {
|
2019-04-28 22:03:16 +02:00
|
|
|
super(service, linkHandler);
|
2018-06-01 19:08:49 +02:00
|
|
|
}
|
|
|
|
|
2020-04-12 16:06:52 +02:00
|
|
|
@Nonnull
|
2018-06-01 19:08:49 +02:00
|
|
|
@Override
|
2018-09-15 21:47:53 +02:00
|
|
|
public String getSearchSuggestion() {
|
2020-04-12 16:06:52 +02:00
|
|
|
return "";
|
2018-06-01 19:08:49 +02:00
|
|
|
}
|
|
|
|
|
2020-04-11 19:18:08 +02:00
|
|
|
@Override
|
|
|
|
public boolean isCorrectedSearch() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-02-07 22:42:21 +01:00
|
|
|
@Nonnull
|
2020-12-20 19:54:12 +01:00
|
|
|
@Override
|
|
|
|
public List<MetaInfo> getMetaInfo() {
|
|
|
|
return Collections.emptyList();
|
|
|
|
}
|
|
|
|
|
2018-06-01 19:08:49 +02:00
|
|
|
@Nonnull
|
|
|
|
@Override
|
|
|
|
public InfoItemsPage<InfoItem> getInitialPage() throws IOException, ExtractionException {
|
2021-12-27 21:18:39 +01:00
|
|
|
return new InfoItemsPage<>(
|
2021-12-27 21:42:43 +01:00
|
|
|
collectItems(initialSearchCollection),
|
|
|
|
getNextPageFromCurrentUrl(getUrl(), currentOffset -> ITEMS_PER_PAGE));
|
2018-06-01 19:08:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-05-15 17:51:43 +02:00
|
|
|
public InfoItemsPage<InfoItem> getPage(final Page page) throws IOException,
|
|
|
|
ExtractionException {
|
2020-05-11 15:25:18 +02:00
|
|
|
if (page == null || isNullOrEmpty(page.getUrl())) {
|
|
|
|
throw new IllegalArgumentException("Page doesn't contain an URL");
|
|
|
|
}
|
|
|
|
|
2018-06-01 19:08:49 +02:00
|
|
|
final Downloader dl = getDownloader();
|
2021-12-27 21:42:43 +01:00
|
|
|
final JsonArray searchCollection;
|
2018-06-01 19:08:49 +02:00
|
|
|
try {
|
2021-05-15 17:51:43 +02:00
|
|
|
final String response = dl.get(page.getUrl(), getExtractorLocalization())
|
|
|
|
.responseBody();
|
2019-04-28 22:03:16 +02:00
|
|
|
searchCollection = JsonParser.object().from(response).getArray("collection");
|
2021-05-15 17:51:43 +02:00
|
|
|
} catch (final JsonParserException e) {
|
2018-06-01 19:08:49 +02:00
|
|
|
throw new ParsingException("Could not parse json response", e);
|
|
|
|
}
|
|
|
|
|
2022-03-18 11:12:45 +01:00
|
|
|
return new InfoItemsPage<>(collectItems(searchCollection),
|
|
|
|
getNextPageFromCurrentUrl(page.getUrl(),
|
|
|
|
currentOffset -> currentOffset + ITEMS_PER_PAGE));
|
2018-06-01 19:08:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-05-15 17:51:43 +02:00
|
|
|
public void onFetchPage(@Nonnull final Downloader downloader) throws IOException,
|
|
|
|
ExtractionException {
|
2018-06-01 19:08:49 +02:00
|
|
|
final Downloader dl = getDownloader();
|
|
|
|
final String url = getUrl();
|
|
|
|
try {
|
2019-04-28 22:03:16 +02:00
|
|
|
final String response = dl.get(url, getExtractorLocalization()).responseBody();
|
2021-12-27 21:42:43 +01:00
|
|
|
initialSearchCollection = JsonParser.object().from(response).getArray("collection");
|
2021-05-15 17:51:43 +02:00
|
|
|
} catch (final JsonParserException e) {
|
2018-06-01 19:08:49 +02:00
|
|
|
throw new ParsingException("Could not parse json response", e);
|
|
|
|
}
|
|
|
|
|
2021-12-27 21:42:43 +01:00
|
|
|
if (initialSearchCollection.isEmpty()) {
|
2018-07-02 13:47:39 +02:00
|
|
|
throw new SearchExtractor.NothingFoundException("Nothing found");
|
2018-06-01 19:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-15 17:51:43 +02:00
|
|
|
private InfoItemsCollector<InfoItem, InfoItemExtractor> collectItems(
|
|
|
|
final JsonArray searchCollection) {
|
2022-02-02 19:18:20 +01:00
|
|
|
final MultiInfoItemsCollector collector = new MultiInfoItemsCollector(getServiceId());
|
2018-06-01 19:08:49 +02:00
|
|
|
|
2021-05-15 17:51:43 +02:00
|
|
|
for (final Object result : searchCollection) {
|
2022-03-18 11:12:45 +01:00
|
|
|
if (!(result instanceof JsonObject)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-05-15 17:51:43 +02:00
|
|
|
final JsonObject searchResult = (JsonObject) result;
|
2022-08-15 05:49:40 +02:00
|
|
|
final String kind = searchResult.getString("kind", "");
|
2018-06-01 19:08:49 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-03-18 11:12:45 +01:00
|
|
|
private Page getNextPageFromCurrentUrl(final String currentUrl,
|
|
|
|
final IntUnaryOperator newPageOffsetCalculator)
|
2018-06-01 19:08:49 +02:00
|
|
|
throws MalformedURLException, UnsupportedEncodingException {
|
2021-12-27 21:42:43 +01:00
|
|
|
final int currentPageOffset = Integer.parseInt(
|
|
|
|
Parser.compatParseMap(new URL(currentUrl).getQuery()).get("offset"));
|
2018-06-01 19:08:49 +02:00
|
|
|
|
2021-12-27 21:18:39 +01:00
|
|
|
return new Page(
|
|
|
|
currentUrl.replace(
|
|
|
|
"&offset=" + currentPageOffset,
|
2021-12-27 21:42:43 +01:00
|
|
|
"&offset=" + newPageOffsetCalculator.applyAsInt(currentPageOffset)));
|
2018-06-01 19:08:49 +02:00
|
|
|
}
|
|
|
|
}
|