[PeerTube] Support searching for playlists

This commit is contained in:
TobiGr 2022-12-04 19:15:44 +01:00
parent 95cc6aefbb
commit dea6d8ce4c
6 changed files with 101 additions and 8 deletions

View File

@ -2,10 +2,13 @@ package org.schabi.newpipe.extractor.services.peertube;
import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonArray;
import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonObject;
import org.schabi.newpipe.extractor.InfoItemExtractor;
import org.schabi.newpipe.extractor.InfoItemsCollector; import org.schabi.newpipe.extractor.InfoItemsCollector;
import org.schabi.newpipe.extractor.Page; import org.schabi.newpipe.extractor.Page;
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubePlaylistInfoItemExtractor;
import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubeSepiaStreamInfoItemExtractor; import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubeSepiaStreamInfoItemExtractor;
import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubeStreamInfoItemExtractor; import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubeStreamInfoItemExtractor;
import org.schabi.newpipe.extractor.utils.JsonUtils; import org.schabi.newpipe.extractor.utils.JsonUtils;
@ -101,12 +104,18 @@ public final class PeertubeParsingHelper {
if (item.has("video")) { if (item.has("video")) {
item = item.getObject("video"); item = item.getObject("video");
} }
final boolean isPlaylistInfoItem = item.has("videosLength");
final PeertubeStreamInfoItemExtractor extractor; final InfoItemExtractor extractor;
if (sepia) { if (sepia) {
extractor = new PeertubeSepiaStreamInfoItemExtractor(item, baseUrl); extractor = new PeertubeSepiaStreamInfoItemExtractor(item, baseUrl);
} else {
if (isPlaylistInfoItem) {
extractor = new PeertubePlaylistInfoItemExtractor(item, baseUrl);
} else { } else {
extractor = new PeertubeStreamInfoItemExtractor(item, baseUrl); extractor = new PeertubeStreamInfoItemExtractor(item, baseUrl);
}
} }
collector.commit(extractor); collector.commit(extractor);
} }

View File

@ -0,0 +1,57 @@
package org.schabi.newpipe.extractor.services.peertube.extractors;
import com.grack.nanojson.JsonObject;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItemExtractor;
import javax.annotation.Nonnull;
public class PeertubePlaylistInfoItemExtractor implements PlaylistInfoItemExtractor {
final JsonObject item;
final JsonObject uploader;
final String baseUrl;
public PeertubePlaylistInfoItemExtractor(@Nonnull final JsonObject item,
@Nonnull final String baseUrl) {
this.item = item;
this.uploader = item.getObject("uploader");
this.baseUrl = baseUrl;
}
@Override
public String getName() throws ParsingException {
return item.getString("displayName");
}
@Override
public String getUrl() throws ParsingException {
return item.getString("url");
}
@Override
public String getThumbnailUrl() throws ParsingException {
return baseUrl + item.getString("thumbnailPath");
}
@Override
public String getUploaderName() throws ParsingException {
return uploader.getString("displayName");
}
@Override
public String getUploaderUrl() throws ParsingException {
return uploader.getString("url");
}
@Override
public boolean isUploaderVerified() throws ParsingException {
return false;
}
@Override
public long getStreamCount() throws ParsingException {
return item.getInt("videosLength");
}
}

View File

@ -329,7 +329,7 @@ public class PeertubeStreamExtractor extends StreamExtractor {
@Nonnull @Nonnull
private String getRelatedItemsUrl(@Nonnull final List<String> tags) private String getRelatedItemsUrl(@Nonnull final List<String> tags)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
final String url = baseUrl + PeertubeSearchQueryHandlerFactory.SEARCH_ENDPOINT; final String url = baseUrl + PeertubeSearchQueryHandlerFactory.SEARCH_ENDPOINT_VIDEOS;
final StringBuilder params = new StringBuilder(); final StringBuilder params = new StringBuilder();
params.append("start=0&count=8&sort=-createdAt"); params.append("start=0&count=8&sort=-createdAt");
for (final String tag : tags) { for (final String tag : tags) {

View File

@ -13,6 +13,7 @@ public final class PeertubePlaylistLinkHandlerFactory extends ListLinkHandlerFac
private static final PeertubePlaylistLinkHandlerFactory INSTANCE private static final PeertubePlaylistLinkHandlerFactory INSTANCE
= new PeertubePlaylistLinkHandlerFactory(); = new PeertubePlaylistLinkHandlerFactory();
private static final String ID_PATTERN = "(/videos/watch/playlist/|/w/p/)([^/?&#]*)"; private static final String ID_PATTERN = "(/videos/watch/playlist/|/w/p/)([^/?&#]*)";
private static final String API_ID_PATTERN = "/video-playlists/([^/?&#]*)";
private PeertubePlaylistLinkHandlerFactory() { private PeertubePlaylistLinkHandlerFactory() {
} }
@ -38,7 +39,12 @@ public final class PeertubePlaylistLinkHandlerFactory extends ListLinkHandlerFac
@Override @Override
public String getId(final String url) throws ParsingException { public String getId(final String url) throws ParsingException {
try {
return Parser.matchGroup(ID_PATTERN, url, 2); return Parser.matchGroup(ID_PATTERN, url, 2);
} catch (final ParsingException ignored) {
// might also be an API url, no reason to throw an exception here
}
return Parser.matchGroup1(API_ID_PATTERN, url);
} }
@Override @Override

View File

@ -12,8 +12,10 @@ public final class PeertubeSearchQueryHandlerFactory extends SearchQueryHandlerF
public static final String VIDEOS = "videos"; public static final String VIDEOS = "videos";
public static final String SEPIA_VIDEOS = "sepia_videos"; // sepia is the global index public static final String SEPIA_VIDEOS = "sepia_videos"; // sepia is the global index
public static final String PLAYLISTS = "playlists";
public static final String SEPIA_BASE_URL = "https://sepiasearch.org"; public static final String SEPIA_BASE_URL = "https://sepiasearch.org";
public static final String SEARCH_ENDPOINT = "/api/v1/search/videos"; public static final String SEARCH_ENDPOINT_PLAYLISTS = "/api/v1/search/video-playlists";
public static final String SEARCH_ENDPOINT_VIDEOS = "/api/v1/search/videos";
private PeertubeSearchQueryHandlerFactory() { private PeertubeSearchQueryHandlerFactory() {
} }
@ -41,7 +43,15 @@ public final class PeertubeSearchQueryHandlerFactory extends SearchQueryHandlerF
final String sortFilter, final String sortFilter,
final String baseUrl) throws ParsingException { final String baseUrl) throws ParsingException {
try { try {
return baseUrl + SEARCH_ENDPOINT + "?search=" + Utils.encodeUrlUtf8(searchString); final String endpoint;
if (contentFilters.isEmpty()
|| contentFilters.get(0).equals(VIDEOS)
|| contentFilters.get(0).equals(SEPIA_VIDEOS)) {
endpoint = SEARCH_ENDPOINT_VIDEOS;
} else {
endpoint = SEARCH_ENDPOINT_PLAYLISTS;
}
return baseUrl + endpoint + "?search=" + Utils.encodeUrlUtf8(searchString);
} catch (final UnsupportedEncodingException e) { } catch (final UnsupportedEncodingException e) {
throw new ParsingException("Could not encode query", e); throw new ParsingException("Could not encode query", e);
} }
@ -51,7 +61,8 @@ public final class PeertubeSearchQueryHandlerFactory extends SearchQueryHandlerF
public String[] getAvailableContentFilter() { public String[] getAvailableContentFilter() {
return new String[]{ return new String[]{
VIDEOS, VIDEOS,
SEPIA_VIDEOS PLAYLISTS,
SEPIA_VIDEOS,
}; };
} }
} }

View File

@ -18,13 +18,23 @@ public class PeertubeSearchQHTest {
} }
@Test @Test
public void testRegularValues() throws Exception { void testVideoSearch() throws Exception {
assertEquals("https://peertube.mastodon.host/api/v1/search/videos?search=asdf", PeerTube.getSearchQHFactory().fromQuery("asdf").getUrl()); assertEquals("https://peertube.mastodon.host/api/v1/search/videos?search=asdf", PeerTube.getSearchQHFactory().fromQuery("asdf").getUrl());
assertEquals("https://peertube.mastodon.host/api/v1/search/videos?search=hans", PeerTube.getSearchQHFactory().fromQuery("hans").getUrl()); assertEquals("https://peertube.mastodon.host/api/v1/search/videos?search=hans", PeerTube.getSearchQHFactory().fromQuery("hans").getUrl());
assertEquals("https://peertube.mastodon.host/api/v1/search/videos?search=Poifj%26jaijf", PeerTube.getSearchQHFactory().fromQuery("Poifj&jaijf").getUrl()); assertEquals("https://peertube.mastodon.host/api/v1/search/videos?search=Poifj%26jaijf", PeerTube.getSearchQHFactory().fromQuery("Poifj&jaijf").getUrl());
assertEquals("https://peertube.mastodon.host/api/v1/search/videos?search=G%C3%BCl%C3%BCm", PeerTube.getSearchQHFactory().fromQuery("Gülüm").getUrl()); assertEquals("https://peertube.mastodon.host/api/v1/search/videos?search=G%C3%BCl%C3%BCm", PeerTube.getSearchQHFactory().fromQuery("Gülüm").getUrl());
assertEquals("https://peertube.mastodon.host/api/v1/search/videos?search=%3Fj%24%29H%C2%A7B", PeerTube.getSearchQHFactory().fromQuery("?j$)H§B").getUrl()); assertEquals("https://peertube.mastodon.host/api/v1/search/videos?search=%3Fj%24%29H%C2%A7B", PeerTube.getSearchQHFactory().fromQuery("?j$)H§B").getUrl());
}
@Test
void testSepiaVideoSearch() throws Exception {
assertEquals("https://sepiasearch.org/api/v1/search/videos?search=%3Fj%24%29H%C2%A7B", PeerTube.getSearchQHFactory().fromQuery("?j$)H§B", singletonList(PeertubeSearchQueryHandlerFactory.SEPIA_VIDEOS), "").getUrl()); assertEquals("https://sepiasearch.org/api/v1/search/videos?search=%3Fj%24%29H%C2%A7B", PeerTube.getSearchQHFactory().fromQuery("?j$)H§B", singletonList(PeertubeSearchQueryHandlerFactory.SEPIA_VIDEOS), "").getUrl());
assertEquals("https://anotherpeertubeindex.com/api/v1/search/videos?search=%3Fj%24%29H%C2%A7B", PeerTube.getSearchQHFactory().fromQuery("?j$)H§B", singletonList(PeertubeSearchQueryHandlerFactory.SEPIA_VIDEOS), "", "https://anotherpeertubeindex.com").getUrl()); assertEquals("https://anotherpeertubeindex.com/api/v1/search/videos?search=%3Fj%24%29H%C2%A7B", PeerTube.getSearchQHFactory().fromQuery("?j$)H§B", singletonList(PeertubeSearchQueryHandlerFactory.SEPIA_VIDEOS), "", "https://anotherpeertubeindex.com").getUrl());
} }
@Test
void testPlaylistSearch() throws Exception {
assertEquals("https://peertube.mastodon.host/api/v1/search/video-playlists?search=asdf", PeerTube.getSearchQHFactory().fromQuery("asdf", singletonList(PeertubeSearchQueryHandlerFactory.PLAYLISTS), "").getUrl());
assertEquals("https://peertube.mastodon.host/api/v1/search/video-playlists?search=hans", PeerTube.getSearchQHFactory().fromQuery("hans", singletonList(PeertubeSearchQueryHandlerFactory.PLAYLISTS), "").getUrl());
}
} }