From dea6d8ce4c4af1014ce306e27e739d7106eea918 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Sun, 4 Dec 2022 19:15:44 +0100 Subject: [PATCH 1/3] [PeerTube] Support searching for playlists --- .../peertube/PeertubeParsingHelper.java | 13 ++++- .../PeertubePlaylistInfoItemExtractor.java | 57 +++++++++++++++++++ .../extractors/PeertubeStreamExtractor.java | 2 +- .../PeertubePlaylistLinkHandlerFactory.java | 8 ++- .../PeertubeSearchQueryHandlerFactory.java | 17 +++++- .../peertube/search/PeertubeSearchQHTest.java | 12 +++- 6 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubePlaylistInfoItemExtractor.java diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeParsingHelper.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeParsingHelper.java index afe491869..1c07dce1f 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeParsingHelper.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeParsingHelper.java @@ -2,10 +2,13 @@ package org.schabi.newpipe.extractor.services.peertube; import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; + +import org.schabi.newpipe.extractor.InfoItemExtractor; import org.schabi.newpipe.extractor.InfoItemsCollector; import org.schabi.newpipe.extractor.Page; import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; 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.PeertubeStreamInfoItemExtractor; import org.schabi.newpipe.extractor.utils.JsonUtils; @@ -101,12 +104,18 @@ public final class PeertubeParsingHelper { if (item.has("video")) { item = item.getObject("video"); } + final boolean isPlaylistInfoItem = item.has("videosLength"); - final PeertubeStreamInfoItemExtractor extractor; + final InfoItemExtractor extractor; if (sepia) { extractor = new PeertubeSepiaStreamInfoItemExtractor(item, baseUrl); } else { - extractor = new PeertubeStreamInfoItemExtractor(item, baseUrl); + if (isPlaylistInfoItem) { + extractor = new PeertubePlaylistInfoItemExtractor(item, baseUrl); + } else { + extractor = new PeertubeStreamInfoItemExtractor(item, baseUrl); + + } } collector.commit(extractor); } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubePlaylistInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubePlaylistInfoItemExtractor.java new file mode 100644 index 000000000..219113da7 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubePlaylistInfoItemExtractor.java @@ -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"); + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeStreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeStreamExtractor.java index a83ccf9b2..32d3ed4a7 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeStreamExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeStreamExtractor.java @@ -329,7 +329,7 @@ public class PeertubeStreamExtractor extends StreamExtractor { @Nonnull private String getRelatedItemsUrl(@Nonnull final List tags) throws UnsupportedEncodingException { - final String url = baseUrl + PeertubeSearchQueryHandlerFactory.SEARCH_ENDPOINT; + final String url = baseUrl + PeertubeSearchQueryHandlerFactory.SEARCH_ENDPOINT_VIDEOS; final StringBuilder params = new StringBuilder(); params.append("start=0&count=8&sort=-createdAt"); for (final String tag : tags) { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubePlaylistLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubePlaylistLinkHandlerFactory.java index fa48fe32c..a5318e581 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubePlaylistLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubePlaylistLinkHandlerFactory.java @@ -13,6 +13,7 @@ public final class PeertubePlaylistLinkHandlerFactory extends ListLinkHandlerFac private static final PeertubePlaylistLinkHandlerFactory INSTANCE = new PeertubePlaylistLinkHandlerFactory(); private static final String ID_PATTERN = "(/videos/watch/playlist/|/w/p/)([^/?&#]*)"; + private static final String API_ID_PATTERN = "/video-playlists/([^/?&#]*)"; private PeertubePlaylistLinkHandlerFactory() { } @@ -38,7 +39,12 @@ public final class PeertubePlaylistLinkHandlerFactory extends ListLinkHandlerFac @Override public String getId(final String url) throws ParsingException { - return Parser.matchGroup(ID_PATTERN, url, 2); + try { + 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 diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeSearchQueryHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeSearchQueryHandlerFactory.java index 42d386bcb..39a475f3c 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeSearchQueryHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeSearchQueryHandlerFactory.java @@ -12,8 +12,10 @@ public final class PeertubeSearchQueryHandlerFactory extends SearchQueryHandlerF public static final String VIDEOS = "videos"; 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 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() { } @@ -41,7 +43,15 @@ public final class PeertubeSearchQueryHandlerFactory extends SearchQueryHandlerF final String sortFilter, final String baseUrl) throws ParsingException { 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) { throw new ParsingException("Could not encode query", e); } @@ -51,7 +61,8 @@ public final class PeertubeSearchQueryHandlerFactory extends SearchQueryHandlerF public String[] getAvailableContentFilter() { return new String[]{ VIDEOS, - SEPIA_VIDEOS + PLAYLISTS, + SEPIA_VIDEOS, }; } } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/peertube/search/PeertubeSearchQHTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/peertube/search/PeertubeSearchQHTest.java index ea396f86f..415e818be 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/peertube/search/PeertubeSearchQHTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/peertube/search/PeertubeSearchQHTest.java @@ -18,13 +18,23 @@ public class PeertubeSearchQHTest { } @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=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=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()); + } + + @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://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()); + } } \ No newline at end of file From d75a997611d6c4d3f66be371592330b623ef0ad3 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Sun, 4 Dec 2022 21:44:00 +0100 Subject: [PATCH 2/3] [PeerTube] Support searching for channels --- .../peertube/PeertubeParsingHelper.java | 5 +- .../PeertubeChannelInfoItemExtractor.java | 70 +++++++++++++++++++ .../PeertubeSearchQueryHandlerFactory.java | 5 ++ .../peertube/search/PeertubeSearchQHTest.java | 7 ++ 4 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelInfoItemExtractor.java diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeParsingHelper.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeParsingHelper.java index 1c07dce1f..fb01f2d4a 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeParsingHelper.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeParsingHelper.java @@ -8,6 +8,7 @@ import org.schabi.newpipe.extractor.InfoItemsCollector; import org.schabi.newpipe.extractor.Page; import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubeChannelInfoItemExtractor; 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.PeertubeStreamInfoItemExtractor; @@ -105,6 +106,7 @@ public final class PeertubeParsingHelper { item = item.getObject("video"); } final boolean isPlaylistInfoItem = item.has("videosLength"); + final boolean isChannelInfoItem = item.has("followersCount"); final InfoItemExtractor extractor; if (sepia) { @@ -112,9 +114,10 @@ public final class PeertubeParsingHelper { } else { if (isPlaylistInfoItem) { extractor = new PeertubePlaylistInfoItemExtractor(item, baseUrl); + } else if (isChannelInfoItem) { + extractor = new PeertubeChannelInfoItemExtractor(item, baseUrl); } else { extractor = new PeertubeStreamInfoItemExtractor(item, baseUrl); - } } collector.commit(extractor); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelInfoItemExtractor.java new file mode 100644 index 000000000..7bdfe6806 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelInfoItemExtractor.java @@ -0,0 +1,70 @@ +package org.schabi.newpipe.extractor.services.peertube.extractors; + +import com.grack.nanojson.JsonArray; +import com.grack.nanojson.JsonObject; + +import org.schabi.newpipe.extractor.channel.ChannelExtractor; +import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor; +import org.schabi.newpipe.extractor.exceptions.ParsingException; + +import javax.annotation.Nonnull; + +public class PeertubeChannelInfoItemExtractor implements ChannelInfoItemExtractor { + + final JsonObject item; + final JsonObject uploader; + final String baseUrl; + public PeertubeChannelInfoItemExtractor(@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 { + final JsonArray avatars = item.getArray("avatars"); + if (avatars.isEmpty()) { + return null; + } + int highestRes = -1; + JsonObject avatar = null; + for (final Object a: avatars) { + if (((JsonObject) a).getInt("width") > highestRes) { + avatar = (JsonObject) a; + highestRes = avatar.getInt("width"); + } + } + return baseUrl + avatar.getString("path"); + } + + @Override + public String getDescription() throws ParsingException { + return item.getString("description"); + } + + @Override + public long getSubscriberCount() throws ParsingException { + return item.getInt("followersCount"); + } + + @Override + public long getStreamCount() throws ParsingException { + return ChannelExtractor.ITEM_COUNT_UNKNOWN; + } + + @Override + public boolean isVerified() throws ParsingException { + return false; + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeSearchQueryHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeSearchQueryHandlerFactory.java index 39a475f3c..db9dfe38c 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeSearchQueryHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/linkHandler/PeertubeSearchQueryHandlerFactory.java @@ -13,9 +13,11 @@ public final class PeertubeSearchQueryHandlerFactory extends SearchQueryHandlerF public static final String VIDEOS = "videos"; public static final String SEPIA_VIDEOS = "sepia_videos"; // sepia is the global index public static final String PLAYLISTS = "playlists"; + public static final String CHANNELS = "channels"; public static final String SEPIA_BASE_URL = "https://sepiasearch.org"; public static final String SEARCH_ENDPOINT_PLAYLISTS = "/api/v1/search/video-playlists"; public static final String SEARCH_ENDPOINT_VIDEOS = "/api/v1/search/videos"; + public static final String SEARCH_ENDPOINT_CHANNELS = "/api/v1/search/video-channels"; private PeertubeSearchQueryHandlerFactory() { } @@ -48,6 +50,8 @@ public final class PeertubeSearchQueryHandlerFactory extends SearchQueryHandlerF || contentFilters.get(0).equals(VIDEOS) || contentFilters.get(0).equals(SEPIA_VIDEOS)) { endpoint = SEARCH_ENDPOINT_VIDEOS; + } else if (contentFilters.get(0).equals(CHANNELS)) { + endpoint = SEARCH_ENDPOINT_CHANNELS; } else { endpoint = SEARCH_ENDPOINT_PLAYLISTS; } @@ -62,6 +66,7 @@ public final class PeertubeSearchQueryHandlerFactory extends SearchQueryHandlerF return new String[]{ VIDEOS, PLAYLISTS, + CHANNELS, SEPIA_VIDEOS, }; } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/peertube/search/PeertubeSearchQHTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/peertube/search/PeertubeSearchQHTest.java index 415e818be..36613a86f 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/peertube/search/PeertubeSearchQHTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/peertube/search/PeertubeSearchQHTest.java @@ -37,4 +37,11 @@ public class PeertubeSearchQHTest { 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()); } + + @Test + void testChannelSearch() throws Exception { + assertEquals("https://peertube.mastodon.host/api/v1/search/video-channels?search=asdf", PeerTube.getSearchQHFactory().fromQuery("asdf", singletonList(PeertubeSearchQueryHandlerFactory.CHANNELS), "").getUrl()); + assertEquals("https://peertube.mastodon.host/api/v1/search/video-channels?search=hans", PeerTube.getSearchQHFactory().fromQuery("hans", singletonList(PeertubeSearchQueryHandlerFactory.CHANNELS), "").getUrl()); + + } } \ No newline at end of file From 2a8729aeb28c5ed3d24891f51923b9fe98cf10a0 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Sat, 31 Dec 2022 18:23:28 +0100 Subject: [PATCH 3/3] Apply suggestions Co-authored-by: Stypox --- .../peertube/PeertubeParsingHelper.java | 12 +++++----- .../PeertubeChannelInfoItemExtractor.java | 22 ++++++------------- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeParsingHelper.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeParsingHelper.java index fb01f2d4a..260c3409a 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeParsingHelper.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/PeertubeParsingHelper.java @@ -111,14 +111,12 @@ public final class PeertubeParsingHelper { final InfoItemExtractor extractor; if (sepia) { extractor = new PeertubeSepiaStreamInfoItemExtractor(item, baseUrl); + } else if (isPlaylistInfoItem) { + extractor = new PeertubePlaylistInfoItemExtractor(item, baseUrl); + } else if (isChannelInfoItem) { + extractor = new PeertubeChannelInfoItemExtractor(item, baseUrl); } else { - if (isPlaylistInfoItem) { - extractor = new PeertubePlaylistInfoItemExtractor(item, baseUrl); - } else if (isChannelInfoItem) { - extractor = new PeertubeChannelInfoItemExtractor(item, baseUrl); - } else { - extractor = new PeertubeStreamInfoItemExtractor(item, baseUrl); - } + extractor = new PeertubeStreamInfoItemExtractor(item, baseUrl); } collector.commit(extractor); } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelInfoItemExtractor.java index 7bdfe6806..3ab1be539 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeChannelInfoItemExtractor.java @@ -1,13 +1,12 @@ package org.schabi.newpipe.extractor.services.peertube.extractors; -import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; - import org.schabi.newpipe.extractor.channel.ChannelExtractor; import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor; import org.schabi.newpipe.extractor.exceptions.ParsingException; import javax.annotation.Nonnull; +import java.util.Comparator; public class PeertubeChannelInfoItemExtractor implements ChannelInfoItemExtractor { @@ -33,19 +32,12 @@ public class PeertubeChannelInfoItemExtractor implements ChannelInfoItemExtracto @Override public String getThumbnailUrl() throws ParsingException { - final JsonArray avatars = item.getArray("avatars"); - if (avatars.isEmpty()) { - return null; - } - int highestRes = -1; - JsonObject avatar = null; - for (final Object a: avatars) { - if (((JsonObject) a).getInt("width") > highestRes) { - avatar = (JsonObject) a; - highestRes = avatar.getInt("width"); - } - } - return baseUrl + avatar.getString("path"); + return item.getArray("avatars").stream() + .filter(JsonObject.class::isInstance) + .map(JsonObject.class::cast) + .max(Comparator.comparingInt(avatar -> avatar.getInt("width"))) + .map(avatar -> baseUrl + avatar.getString("path")) + .orElse(null); } @Override