diff --git a/src/main/java/me/kavin/piped/ServerLauncher.java b/src/main/java/me/kavin/piped/ServerLauncher.java index 29e2adf..e50e469 100644 --- a/src/main/java/me/kavin/piped/ServerLauncher.java +++ b/src/main/java/me/kavin/piped/ServerLauncher.java @@ -135,6 +135,16 @@ public class ServerLauncher extends MultithreadedHttpServerLauncher { } catch (Exception e) { return getErrorResponse(e, request.getPath()); } + })).map(GET, "/channels/tabs", AsyncServlet.ofBlocking(executor, request -> { + try { + String nextpage = request.getQueryParameter("nextpage"); + if (StringUtils.isEmpty(nextpage)) + return getJsonResponse(ResponseHelper.channelTabResponse(request.getQueryParameter("data")), "public, max-age=3600", true); + else + return getJsonResponse(ResponseHelper.channelTabPageResponse(request.getQueryParameter("data"), nextpage), "public, max-age=3600", true); + } catch (Exception e) { + return getErrorResponse(e, request.getPath()); + } })).map(GET, "/playlists/:playlistId", AsyncServlet.ofBlocking(executor, request -> { try { var playlistId = request.getPathParameter("playlistId"); diff --git a/src/main/java/me/kavin/piped/consts/Constants.java b/src/main/java/me/kavin/piped/consts/Constants.java index 3d93789..ac39a39 100644 --- a/src/main/java/me/kavin/piped/consts/Constants.java +++ b/src/main/java/me/kavin/piped/consts/Constants.java @@ -1,6 +1,7 @@ package me.kavin.piped.consts; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import me.kavin.piped.utils.PageMixin; @@ -69,7 +70,9 @@ public class Constants { public static final String VERSION; - public static final ObjectMapper mapper = new ObjectMapper().addMixIn(Page.class, PageMixin.class); + public static final ObjectMapper mapper = JsonMapper.builder() + .addMixIn(Page.class, PageMixin.class) + .build(); public static final Object2ObjectOpenHashMap hibernateProperties = new Object2ObjectOpenHashMap<>(); diff --git a/src/main/java/me/kavin/piped/utils/ResponseHelper.java b/src/main/java/me/kavin/piped/utils/ResponseHelper.java index 64b0b02..5f9550b 100644 --- a/src/main/java/me/kavin/piped/utils/ResponseHelper.java +++ b/src/main/java/me/kavin/piped/utils/ResponseHelper.java @@ -19,8 +19,6 @@ import me.kavin.piped.utils.obj.Channel; import me.kavin.piped.utils.obj.Playlist; import me.kavin.piped.utils.obj.*; import me.kavin.piped.utils.obj.db.*; -import me.kavin.piped.utils.obj.search.SearchChannel; -import me.kavin.piped.utils.obj.search.SearchPlaylist; import me.kavin.piped.utils.resp.*; import okhttp3.FormBody; import okhttp3.Request; @@ -34,6 +32,7 @@ import org.schabi.newpipe.extractor.ListExtractor.InfoItemsPage; import org.schabi.newpipe.extractor.Page; import org.schabi.newpipe.extractor.channel.ChannelInfo; import org.schabi.newpipe.extractor.channel.ChannelInfoItem; +import org.schabi.newpipe.extractor.channel.ChannelTabInfo; import org.schabi.newpipe.extractor.comments.CommentsInfo; import org.schabi.newpipe.extractor.comments.CommentsInfoItem; import org.schabi.newpipe.extractor.exceptions.ExtractionException; @@ -45,6 +44,7 @@ import org.schabi.newpipe.extractor.localization.ContentCountry; import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; import org.schabi.newpipe.extractor.search.SearchInfo; +import org.schabi.newpipe.extractor.services.youtube.linkHandler.YouTubeChannelTabHandler; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamType; @@ -158,12 +158,7 @@ public class ResponseHelper { stream.getInitEnd(), stream.getIndexStart(), stream.getIndexEnd(), stream.getCodec()))); } - final List relatedStreams = new ObjectArrayList<>(); - - info.getRelatedItems().forEach(o -> { - if (o instanceof StreamInfoItem) - relatedStreams.add(collectRelatedStream(o)); - }); + final List relatedStreams = collectRelatedItems(info.getRelatedItems()); long time = info.getUploadDate() != null ? info.getUploadDate().offsetDateTime().toInstant().toEpochMilli() : System.currentTimeMillis(); @@ -224,9 +219,7 @@ public class ResponseHelper { final ChannelInfo info = ChannelInfo.getInfo("https://youtube.com/" + channelPath); - final List relatedStreams = new ObjectArrayList<>(); - - info.getRelatedItems().forEach(o -> relatedStreams.add(collectRelatedStream(o))); + final List relatedStreams = collectRelatedItems(info.getRelatedItems()); Multithreading.runAsync(() -> { @@ -292,9 +285,19 @@ public class ResponseHelper { nextpage = mapper.writeValueAsString(page); } + List tabs = info.getTabs() + .stream() + .map(tab -> { + try { + return new ChannelTab(tab.getTab().name(), mapper.writeValueAsString(tab)); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + }).toList(); + final Channel channel = new Channel(info.getId(), info.getName(), rewriteURL(info.getAvatarUrl()), rewriteURL(info.getBannerUrl()), info.getDescription(), info.getSubscriberCount(), info.isVerified(), - nextpage, relatedStreams); + nextpage, relatedStreams, tabs); IPFS.publishData(channel); @@ -313,9 +316,7 @@ public class ResponseHelper { InfoItemsPage info = ChannelInfo.getMoreItems(YOUTUBE_SERVICE, "https://youtube.com/channel/" + channelId, prevpage); - final List relatedStreams = new ObjectArrayList<>(); - - info.getItems().forEach(o -> relatedStreams.add(collectRelatedStream(o))); + final List relatedStreams = collectRelatedItems(info.getItems()); String nextpage = null; if (info.hasNextPage()) { @@ -329,13 +330,49 @@ public class ResponseHelper { } + public static byte[] channelTabResponse(String data) + throws IOException, ExtractionException { + + if (StringUtils.isEmpty(data)) + return mapper.writeValueAsBytes(new InvalidRequestResponse()); + + YouTubeChannelTabHandler tabHandler = mapper.readValue(data, YouTubeChannelTabHandlerMixin.class); + + var info = ChannelTabInfo.getInfo(YOUTUBE_SERVICE, tabHandler); + + List items = collectRelatedItems(info.getRelatedItems()); + + String nextpage = null; + if (info.hasNextPage()) { + Page page = info.getNextPage(); + nextpage = mapper.writeValueAsString(page); + } + + return mapper.writeValueAsBytes(new ChannelTabData(nextpage, items)); + } + + public static byte[] channelTabPageResponse(String data, String nextpage) throws Exception { + + if (StringUtils.isEmpty(data)) + return mapper.writeValueAsBytes(new InvalidRequestResponse()); + + YouTubeChannelTabHandler tabHandler = mapper.readValue(data, YouTubeChannelTabHandlerMixin.class); + + Page nextPage = mapper.readValue(nextpage, Page.class); + + var info = ChannelTabInfo.getMoreItems(YOUTUBE_SERVICE, tabHandler, nextPage); + + List items = collectRelatedItems(info.getItems()); + + return mapper.writeValueAsBytes(new ChannelTabData(null, items)); + } + public static byte[] trendingResponse(String region) throws ExtractionException, IOException { if (region == null) return mapper.writeValueAsBytes(new InvalidRequestResponse()); - final List relatedStreams = new ObjectArrayList<>(); KioskList kioskList = YOUTUBE_SERVICE.getKioskList(); kioskList.forceContentCountry(new ContentCountry(region)); @@ -343,7 +380,7 @@ public class ResponseHelper { extractor.fetchPage(); KioskInfo info = KioskInfo.getInfo(extractor); - info.getRelatedItems().forEach(o -> relatedStreams.add(collectRelatedStream(o))); + final List relatedStreams = collectRelatedItems(info.getRelatedItems()); return mapper.writeValueAsBytes(relatedStreams); } @@ -376,7 +413,7 @@ public class ResponseHelper { return mapper.writeValueAsBytes(mapper.createObjectNode() .put("error", "Playlist not found")); - final List relatedStreams = new ObjectArrayList<>(); + final List relatedStreams = new ObjectArrayList<>(); var videos = pl.getVideos(); @@ -399,9 +436,7 @@ public class ResponseHelper { final PlaylistInfo info = PlaylistInfo.getInfo("https://www.youtube.com/playlist?list=" + playlistId); - final List relatedStreams = new ObjectArrayList<>(); - - info.getRelatedItems().forEach(o -> relatedStreams.add(collectRelatedStream(o))); + final List relatedStreams = collectRelatedItems(info.getRelatedItems()); String nextpage = null; if (info.hasNextPage()) { @@ -430,9 +465,7 @@ public class ResponseHelper { InfoItemsPage info = PlaylistInfo.getMoreItems(YOUTUBE_SERVICE, "https://www.youtube.com/playlist?list=" + playlistId, prevpage); - final List relatedStreams = new ObjectArrayList<>(); - - info.getItems().forEach(o -> relatedStreams.add(collectRelatedStream(o))); + final List relatedStreams = collectRelatedItems(info.getItems()); String nextpage = null; if (info.hasNextPage()) { @@ -556,24 +589,7 @@ public class ResponseHelper { final SearchInfo info = SearchInfo.getInfo(YOUTUBE_SERVICE, YOUTUBE_SERVICE.getSearchQHFactory().fromQuery(q, Collections.singletonList(filter), null)); - ObjectArrayList items = new ObjectArrayList<>(); - - info.getRelatedItems().forEach(item -> { - switch (item.getInfoType()) { - case STREAM -> items.add(collectRelatedStream(item)); - case CHANNEL -> { - ChannelInfoItem channel = (ChannelInfoItem) item; - items.add(new SearchChannel(item.getName(), rewriteURL(item.getThumbnailUrl()), - substringYouTube(item.getUrl()), channel.getDescription(), channel.getSubscriberCount(), - channel.getStreamCount(), channel.isVerified())); - } - case PLAYLIST -> { - PlaylistInfoItem playlist = (PlaylistInfoItem) item; - items.add(new SearchPlaylist(item.getName(), rewriteURL(item.getThumbnailUrl()), - substringYouTube(item.getUrl()), playlist.getUploaderName(), playlist.getStreamCount())); - } - } - }); + List items = collectRelatedItems(info.getRelatedItems()); Page nextpage = info.getNextPage(); @@ -593,24 +609,7 @@ public class ResponseHelper { InfoItemsPage pages = SearchInfo.getMoreItems(YOUTUBE_SERVICE, YOUTUBE_SERVICE.getSearchQHFactory().fromQuery(q, Collections.singletonList(filter), null), prevpage); - ObjectArrayList items = new ObjectArrayList<>(); - - pages.getItems().forEach(item -> { - switch (item.getInfoType()) { - case STREAM -> items.add(collectRelatedStream(item)); - case CHANNEL -> { - ChannelInfoItem channel = (ChannelInfoItem) item; - items.add(new SearchChannel(item.getName(), rewriteURL(item.getThumbnailUrl()), - substringYouTube(item.getUrl()), channel.getDescription(), channel.getSubscriberCount(), - channel.getStreamCount(), channel.isVerified())); - } - case PLAYLIST -> { - PlaylistInfoItem playlist = (PlaylistInfoItem) item; - items.add(new SearchPlaylist(item.getName(), rewriteURL(item.getThumbnailUrl()), - substringYouTube(item.getUrl()), playlist.getUploaderName(), playlist.getStreamCount())); - } - } - }); + List items = collectRelatedItems(pages.getItems()); Page nextpage = pages.getNextPage(); @@ -1754,31 +1753,47 @@ public class ResponseHelper { formBuilder.add("hub.mode", "subscribe"); formBuilder.add("hub.lease_seconds", "432000"); - var resp = Constants.h2client + try (var resp = Constants.h2client .newCall(builder.post(formBuilder.build()) - .build()).execute(); + .build()).execute()) { - if (resp.code() == 202) { - try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) { - var tr = s.beginTransaction(); - if (pubsub == null) { - pubsub = new PubSub(channelId, System.currentTimeMillis()); - s.insert(pubsub); - } else { - pubsub.setSubbedAt(System.currentTimeMillis()); - s.update(pubsub); + if (resp.code() == 202) { + try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) { + var tr = s.beginTransaction(); + if (pubsub == null) { + pubsub = new PubSub(channelId, System.currentTimeMillis()); + s.insert(pubsub); + } else { + pubsub.setSubbedAt(System.currentTimeMillis()); + s.update(pubsub); + } + tr.commit(); } - tr.commit(); - } - } else - System.out.println("Failed to subscribe: " + resp.code() + "\n" + Objects.requireNonNull(resp.body()).string()); + } else + System.out.println("Failed to subscribe: " + resp.code() + "\n" + Objects.requireNonNull(resp.body()).string()); - resp.close(); + } } } + private static List collectRelatedItems(List items) { + return items + .stream() + .parallel() + .map(item -> { + if (item instanceof StreamInfoItem) + return collectRelatedStream(item); + else if (item instanceof PlaylistInfoItem) + return collectRelatedPlaylist(item); + else if (item instanceof ChannelInfoItem) + return collectRelatedChannel(item); + else + throw new RuntimeException("Unknown item type: " + item.getClass().getName()); + }).toList(); + } + private static StreamItem collectRelatedStream(Object o) { StreamInfoItem item = (StreamInfoItem) o; @@ -1788,4 +1803,20 @@ public class ResponseHelper { rewriteURL(item.getUploaderAvatarUrl()), item.getTextualUploadDate(), item.getShortDescription(), item.getDuration(), item.getViewCount(), item.getUploadDate() != null ? item.getUploadDate().offsetDateTime().toInstant().toEpochMilli() : -1, item.isUploaderVerified(), item.isShortFormContent()); } + + private static PlaylistItem collectRelatedPlaylist(Object o) { + + PlaylistInfoItem item = (PlaylistInfoItem) o; + + return new PlaylistItem(substringYouTube(item.getUrl()), item.getName(), rewriteURL(item.getThumbnailUrl()), + item.getUploaderName(), item.getPlaylistType().name(), item.getStreamCount()); + } + + private static ChannelItem collectRelatedChannel(Object o) { + + ChannelInfoItem item = (ChannelInfoItem) o; + + return new ChannelItem(substringYouTube(item.getUrl()), item.getName(), rewriteURL(item.getThumbnailUrl()), + item.getDescription(), item.getSubscriberCount(), item.getStreamCount(), item.isVerified()); + } } diff --git a/src/main/java/me/kavin/piped/utils/YouTubeChannelTabHandlerMixin.java b/src/main/java/me/kavin/piped/utils/YouTubeChannelTabHandlerMixin.java new file mode 100644 index 0000000..0bb92db --- /dev/null +++ b/src/main/java/me/kavin/piped/utils/YouTubeChannelTabHandlerMixin.java @@ -0,0 +1,23 @@ +package me.kavin.piped.utils; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.schabi.newpipe.extractor.linkhandler.ChannelTabHandler; +import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; +import org.schabi.newpipe.extractor.services.youtube.linkHandler.YouTubeChannelTabHandler; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class YouTubeChannelTabHandlerMixin extends YouTubeChannelTabHandler { + + @JsonCreator + @JsonIgnoreProperties(ignoreUnknown = true) + public YouTubeChannelTabHandlerMixin(@JsonProperty("originalUrl") String originalUrl, @JsonProperty("url") String url, + @JsonProperty("id") String id, @JsonProperty("contentFilters") List contentFilters, + @JsonProperty("sortFilter") String sortFilter, @JsonProperty("tab") ChannelTabHandler.Tab tab, + @JsonProperty("visitorData") String visitorData) { + super(new ListLinkHandler(originalUrl, url, id, contentFilters, sortFilter), tab, visitorData); + } +} diff --git a/src/main/java/me/kavin/piped/utils/obj/Channel.java b/src/main/java/me/kavin/piped/utils/obj/Channel.java index 598edc4..49826dc 100644 --- a/src/main/java/me/kavin/piped/utils/obj/Channel.java +++ b/src/main/java/me/kavin/piped/utils/obj/Channel.java @@ -7,10 +7,12 @@ public class Channel { public String id, name, avatarUrl, bannerUrl, description, nextpage; public long subscriberCount; public boolean verified; - public List relatedStreams; + public List relatedStreams; + + public List tabs; public Channel(String id, String name, String avatarUrl, String bannerUrl, String description, long subscriberCount, - boolean verified, String nextpage, List relatedStreams) { + boolean verified, String nextpage, List relatedStreams, List tabs) { this.id = id; this.name = name; this.avatarUrl = avatarUrl; @@ -20,5 +22,6 @@ public class Channel { this.verified = verified; this.nextpage = nextpage; this.relatedStreams = relatedStreams; + this.tabs = tabs; } } diff --git a/src/main/java/me/kavin/piped/utils/obj/ChannelItem.java b/src/main/java/me/kavin/piped/utils/obj/ChannelItem.java new file mode 100644 index 0000000..4fbc957 --- /dev/null +++ b/src/main/java/me/kavin/piped/utils/obj/ChannelItem.java @@ -0,0 +1,23 @@ +package me.kavin.piped.utils.obj; + +public class ChannelItem extends ContentItem { + + public final String type = "channel"; + + public String name; + public String thumbnail; + public String description; + public long subscribers, videos; + public boolean verified; + + public ChannelItem(String url, String name, String thumbnail, String description, long subscribers, long videos, + boolean verified) { + super(url); + this.name = name; + this.thumbnail = thumbnail; + this.description = description; + this.subscribers = subscribers; + this.videos = videos; + this.verified = verified; + } +} diff --git a/src/main/java/me/kavin/piped/utils/obj/ChannelTab.java b/src/main/java/me/kavin/piped/utils/obj/ChannelTab.java new file mode 100644 index 0000000..3763287 --- /dev/null +++ b/src/main/java/me/kavin/piped/utils/obj/ChannelTab.java @@ -0,0 +1,12 @@ +package me.kavin.piped.utils.obj; + +public class ChannelTab { + + public String name; + public String data; + + public ChannelTab(String name, String data) { + this.name = name; + this.data = data; + } +} diff --git a/src/main/java/me/kavin/piped/utils/obj/ChannelTabData.java b/src/main/java/me/kavin/piped/utils/obj/ChannelTabData.java new file mode 100644 index 0000000..3407be2 --- /dev/null +++ b/src/main/java/me/kavin/piped/utils/obj/ChannelTabData.java @@ -0,0 +1,14 @@ +package me.kavin.piped.utils.obj; + +import java.util.List; + +public class ChannelTabData { + + public String nextpage; + public List content; + + public ChannelTabData(String nextpage, List content) { + this.nextpage = nextpage; + this.content = content; + } +} diff --git a/src/main/java/me/kavin/piped/utils/obj/ContentItem.java b/src/main/java/me/kavin/piped/utils/obj/ContentItem.java new file mode 100644 index 0000000..31cc3f3 --- /dev/null +++ b/src/main/java/me/kavin/piped/utils/obj/ContentItem.java @@ -0,0 +1,10 @@ +package me.kavin.piped.utils.obj; + +public class ContentItem { + + public String url; + + public ContentItem(String url) { + this.url = url; + } +} diff --git a/src/main/java/me/kavin/piped/utils/obj/Playlist.java b/src/main/java/me/kavin/piped/utils/obj/Playlist.java index 7124eb8..4d30103 100644 --- a/src/main/java/me/kavin/piped/utils/obj/Playlist.java +++ b/src/main/java/me/kavin/piped/utils/obj/Playlist.java @@ -6,10 +6,10 @@ public class Playlist { public String name, thumbnailUrl, bannerUrl, nextpage, uploader, uploaderUrl, uploaderAvatar; public int videos; - public List relatedStreams; + public List relatedStreams; public Playlist(String name, String thumbnailUrl, String bannerUrl, String nextpage, String uploader, - String uploaderUrl, String uploaderAvatar, int videos, List relatedStreams) { + String uploaderUrl, String uploaderAvatar, int videos, List relatedStreams) { this.name = name; this.thumbnailUrl = thumbnailUrl; this.bannerUrl = bannerUrl; diff --git a/src/main/java/me/kavin/piped/utils/obj/PlaylistItem.java b/src/main/java/me/kavin/piped/utils/obj/PlaylistItem.java new file mode 100644 index 0000000..9e8f024 --- /dev/null +++ b/src/main/java/me/kavin/piped/utils/obj/PlaylistItem.java @@ -0,0 +1,23 @@ +package me.kavin.piped.utils.obj; + +public class PlaylistItem extends ContentItem { + + public final String type = "playlist"; + + public String name; + public String thumbnail; + public String uploaderName; + public String playlistType; + + public long videos; + + + public PlaylistItem(String url, String name, String thumbnail, String uploaderName, String playlistType, long videos) { + super(url); + this.name = name; + this.thumbnail = thumbnail; + this.uploaderName = uploaderName; + this.playlistType = playlistType; + this.videos = videos; + } +} diff --git a/src/main/java/me/kavin/piped/utils/obj/SearchResults.java b/src/main/java/me/kavin/piped/utils/obj/SearchResults.java index 72c2728..77fe762 100644 --- a/src/main/java/me/kavin/piped/utils/obj/SearchResults.java +++ b/src/main/java/me/kavin/piped/utils/obj/SearchResults.java @@ -1,19 +1,19 @@ package me.kavin.piped.utils.obj; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import java.util.List; public class SearchResults { - public ObjectArrayList items; + public List items; public String nextpage, suggestion; public boolean corrected; - public SearchResults(ObjectArrayList items, String nextpage) { + public SearchResults(List items, String nextpage) { this.nextpage = nextpage; this.items = items; } - public SearchResults(ObjectArrayList items, String nextpage, String suggestion, boolean corrected) { + public SearchResults(List items, String nextpage, String suggestion, boolean corrected) { this.items = items; this.nextpage = nextpage; this.suggestion = suggestion; diff --git a/src/main/java/me/kavin/piped/utils/obj/StreamItem.java b/src/main/java/me/kavin/piped/utils/obj/StreamItem.java index 058febb..e5ccf86 100644 --- a/src/main/java/me/kavin/piped/utils/obj/StreamItem.java +++ b/src/main/java/me/kavin/piped/utils/obj/StreamItem.java @@ -1,16 +1,16 @@ package me.kavin.piped.utils.obj; -public class StreamItem { +public class StreamItem extends ContentItem { - private final String type = "video"; + public final String type = "stream"; - public String url, title, thumbnail, uploaderName, uploaderUrl, uploaderAvatar, uploadedDate, shortDescription; + public String title, thumbnail, uploaderName, uploaderUrl, uploaderAvatar, uploadedDate, shortDescription; public long duration, views, uploaded; public boolean uploaderVerified, isShort; public StreamItem(String url, String title, String thumbnail, String uploaderName, String uploaderUrl, String uploaderAvatar, String uploadedDate, String shortDescription, long duration, long views, long uploaded, boolean uploaderVerified, boolean isShort) { - this.url = url; + super(url); this.title = title; this.thumbnail = thumbnail; this.uploaderName = uploaderName; diff --git a/src/main/java/me/kavin/piped/utils/obj/Streams.java b/src/main/java/me/kavin/piped/utils/obj/Streams.java index ed1dac7..c903058 100644 --- a/src/main/java/me/kavin/piped/utils/obj/Streams.java +++ b/src/main/java/me/kavin/piped/utils/obj/Streams.java @@ -15,7 +15,7 @@ public class Streams { public List audioStreams, videoStreams; - public List relatedStreams; + public List relatedStreams; public List subtitles; @@ -28,7 +28,7 @@ public class Streams { public Streams(String title, String description, String uploadDate, String uploader, String uploaderUrl, String uploaderAvatar, String thumbnailUrl, long duration, long views, long likes, long dislikes, long uploaderSubscriberCount, boolean uploaderVerified, List audioStreams, List videoStreams, - List relatedStreams, List subtitles, boolean livestream, String hls, String dash, + List relatedStreams, List subtitles, boolean livestream, String hls, String dash, String lbryId, List chapters) { this.title = title; this.description = description; diff --git a/src/main/java/me/kavin/piped/utils/obj/StreamsPage.java b/src/main/java/me/kavin/piped/utils/obj/StreamsPage.java index e6d729c..70b921e 100644 --- a/src/main/java/me/kavin/piped/utils/obj/StreamsPage.java +++ b/src/main/java/me/kavin/piped/utils/obj/StreamsPage.java @@ -5,9 +5,9 @@ import java.util.List; public class StreamsPage { public String nextpage; - public List relatedStreams; + public List relatedStreams; - public StreamsPage(String nextpage, List relatedStreams) { + public StreamsPage(String nextpage, List relatedStreams) { this.nextpage = nextpage; this.relatedStreams = relatedStreams; } diff --git a/src/main/java/me/kavin/piped/utils/obj/search/SearchChannel.java b/src/main/java/me/kavin/piped/utils/obj/search/SearchChannel.java deleted file mode 100644 index 102aac8..0000000 --- a/src/main/java/me/kavin/piped/utils/obj/search/SearchChannel.java +++ /dev/null @@ -1,33 +0,0 @@ -package me.kavin.piped.utils.obj.search; - -public class SearchChannel extends SearchItem { - - private String description; - private long subscribers, videos; - private boolean verified; - - public SearchChannel(String name, String thumbnail, String url, String description, long subscribers, long videos, - boolean verified) { - super(name, thumbnail, url); - this.description = description; - this.subscribers = subscribers; - this.videos = videos; - this.verified = verified; - } - - public String getDescription() { - return description; - } - - public long getSubscribers() { - return subscribers; - } - - public long getVideos() { - return videos; - } - - public boolean isVerified() { - return verified; - } -} diff --git a/src/main/java/me/kavin/piped/utils/obj/search/SearchItem.java b/src/main/java/me/kavin/piped/utils/obj/search/SearchItem.java deleted file mode 100644 index 9cb0864..0000000 --- a/src/main/java/me/kavin/piped/utils/obj/search/SearchItem.java +++ /dev/null @@ -1,24 +0,0 @@ -package me.kavin.piped.utils.obj.search; - -public class SearchItem { - - private String name, thumbnail, url; - - public SearchItem(String name, String thumbnail, String url) { - this.name = name; - this.thumbnail = thumbnail; - this.url = url; - } - - public String getName() { - return name; - } - - public String getThumbnail() { - return thumbnail; - } - - public String getUrl() { - return url; - } -} diff --git a/src/main/java/me/kavin/piped/utils/obj/search/SearchPlaylist.java b/src/main/java/me/kavin/piped/utils/obj/search/SearchPlaylist.java deleted file mode 100644 index 6fe25b3..0000000 --- a/src/main/java/me/kavin/piped/utils/obj/search/SearchPlaylist.java +++ /dev/null @@ -1,21 +0,0 @@ -package me.kavin.piped.utils.obj.search; - -public class SearchPlaylist extends SearchItem { - - private String uploaderName; - private long videos; - - public SearchPlaylist(String name, String thumbnail, String url, String uploaderName, long videos) { - super(name, thumbnail, url); - this.uploaderName = uploaderName; - this.videos = videos; - } - - public String getUploaderName() { - return uploaderName; - } - - public long getVideos() { - return videos; - } -} diff --git a/src/main/java/me/kavin/piped/utils/obj/search/SearchStream.java b/src/main/java/me/kavin/piped/utils/obj/search/SearchStream.java deleted file mode 100644 index 09d5192..0000000 --- a/src/main/java/me/kavin/piped/utils/obj/search/SearchStream.java +++ /dev/null @@ -1,43 +0,0 @@ -package me.kavin.piped.utils.obj.search; - -public class SearchStream extends SearchItem { - - private String uploadDate, uploader, uploaderUrl; - private long views, duration; - private boolean uploaderVerified; - - public SearchStream(String name, String thumbnail, String url, String uploadDate, String uploader, - String uploaderUrl, long views, long duration, boolean uploaderVerified) { - super(name, thumbnail, url); - this.uploadDate = uploadDate; - this.uploader = uploader; - this.uploaderUrl = uploaderUrl; - this.views = views; - this.duration = duration; - this.uploaderVerified = uploaderVerified; - } - - public String getUploadDate() { - return uploadDate; - } - - public String getUploader() { - return uploader; - } - - public String getUploaderUrl() { - return uploaderUrl; - } - - public long getViews() { - return views; - } - - public long getDuration() { - return duration; - } - - public boolean isUploaderVerified() { - return uploaderVerified; - } -} diff --git a/testing/api-test.sh b/testing/api-test.sh index a66ac26..3f2489c 100755 --- a/testing/api-test.sh +++ b/testing/api-test.sh @@ -21,6 +21,10 @@ curl ${CURLOPTS[@]} $HOST/user/Kurzgesagt || exit 1 CHANNEL_NEXTPAGE=$(curl -s -o - -f $HOST/channel/UCsXVk37bltHxD1rDPwtNM8Q | jq -r .nextpage) curl ${CURLOPTS[@]} $HOST/nextpage/channel/UCsXVk37bltHxD1rDPwtNM8Q -G --data-urlencode "nextpage=$CHANNEL_NEXTPAGE" || exit 1 +# Channel Tab +CHANNEL_TAB_DATA=$(curl -s -o - -f $HOST/channel/UCsXVk37bltHxD1rDPwtNM8Q | jq -r .tabs[0].data) +curl ${CURLOPTS[@]} $HOST/channels/tabs -G --data-urlencode "data=$CHANNEL_TAB_DATA" || exit 1 + # Playlist curl ${CURLOPTS[@]} $HOST/playlists/PLQSoWXSpjA3-egtFq45DcUydZ885W7MTT || exit 1