mirror of
https://github.com/TeamPiped/Piped-Backend.git
synced 2024-08-14 23:51:41 +00:00
Merge pull request #400 from TeamPiped/channel-tabs
Implement support for channel tabs.
This commit is contained in:
commit
8c1a80f8be
20 changed files with 249 additions and 214 deletions
|
@ -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");
|
||||
|
|
|
@ -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<String, String> hibernateProperties = new Object2ObjectOpenHashMap<>();
|
||||
|
||||
|
|
|
@ -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<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
|
||||
info.getRelatedItems().forEach(o -> {
|
||||
if (o instanceof StreamInfoItem)
|
||||
relatedStreams.add(collectRelatedStream(o));
|
||||
});
|
||||
final List<ContentItem> 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<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
|
||||
info.getRelatedItems().forEach(o -> relatedStreams.add(collectRelatedStream(o)));
|
||||
final List<ContentItem> relatedStreams = collectRelatedItems(info.getRelatedItems());
|
||||
|
||||
Multithreading.runAsync(() -> {
|
||||
|
||||
|
@ -292,9 +285,19 @@ public class ResponseHelper {
|
|||
nextpage = mapper.writeValueAsString(page);
|
||||
}
|
||||
|
||||
List<ChannelTab> 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<StreamInfoItem> info = ChannelInfo.getMoreItems(YOUTUBE_SERVICE,
|
||||
"https://youtube.com/channel/" + channelId, prevpage);
|
||||
|
||||
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
|
||||
info.getItems().forEach(o -> relatedStreams.add(collectRelatedStream(o)));
|
||||
final List<ContentItem> 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<ContentItem> 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<ContentItem> 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<StreamItem> 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<ContentItem> 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<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
final List<ContentItem> 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<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
|
||||
info.getRelatedItems().forEach(o -> relatedStreams.add(collectRelatedStream(o)));
|
||||
final List<ContentItem> relatedStreams = collectRelatedItems(info.getRelatedItems());
|
||||
|
||||
String nextpage = null;
|
||||
if (info.hasNextPage()) {
|
||||
|
@ -430,9 +465,7 @@ public class ResponseHelper {
|
|||
InfoItemsPage<StreamInfoItem> info = PlaylistInfo.getMoreItems(YOUTUBE_SERVICE,
|
||||
"https://www.youtube.com/playlist?list=" + playlistId, prevpage);
|
||||
|
||||
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
|
||||
info.getItems().forEach(o -> relatedStreams.add(collectRelatedStream(o)));
|
||||
final List<ContentItem> 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<Object> 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<ContentItem> items = collectRelatedItems(info.getRelatedItems());
|
||||
|
||||
Page nextpage = info.getNextPage();
|
||||
|
||||
|
@ -593,24 +609,7 @@ public class ResponseHelper {
|
|||
InfoItemsPage<InfoItem> pages = SearchInfo.getMoreItems(YOUTUBE_SERVICE,
|
||||
YOUTUBE_SERVICE.getSearchQHFactory().fromQuery(q, Collections.singletonList(filter), null), prevpage);
|
||||
|
||||
ObjectArrayList<Object> 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<ContentItem> items = collectRelatedItems(pages.getItems());
|
||||
|
||||
Page nextpage = pages.getNextPage();
|
||||
|
||||
|
@ -1754,9 +1753,9 @@ 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()) {
|
||||
|
@ -1774,11 +1773,27 @@ public class ResponseHelper {
|
|||
} else
|
||||
System.out.println("Failed to subscribe: " + resp.code() + "\n" + Objects.requireNonNull(resp.body()).string());
|
||||
|
||||
resp.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static List<ContentItem> collectRelatedItems(List<? extends InfoItem> 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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<String> contentFilters,
|
||||
@JsonProperty("sortFilter") String sortFilter, @JsonProperty("tab") ChannelTabHandler.Tab tab,
|
||||
@JsonProperty("visitorData") String visitorData) {
|
||||
super(new ListLinkHandler(originalUrl, url, id, contentFilters, sortFilter), tab, visitorData);
|
||||
}
|
||||
}
|
|
@ -7,10 +7,12 @@ public class Channel {
|
|||
public String id, name, avatarUrl, bannerUrl, description, nextpage;
|
||||
public long subscriberCount;
|
||||
public boolean verified;
|
||||
public List<StreamItem> relatedStreams;
|
||||
public List<ContentItem> relatedStreams;
|
||||
|
||||
public List<ChannelTab> tabs;
|
||||
|
||||
public Channel(String id, String name, String avatarUrl, String bannerUrl, String description, long subscriberCount,
|
||||
boolean verified, String nextpage, List<StreamItem> relatedStreams) {
|
||||
boolean verified, String nextpage, List<ContentItem> relatedStreams, List<ChannelTab> 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;
|
||||
}
|
||||
}
|
||||
|
|
23
src/main/java/me/kavin/piped/utils/obj/ChannelItem.java
Normal file
23
src/main/java/me/kavin/piped/utils/obj/ChannelItem.java
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
12
src/main/java/me/kavin/piped/utils/obj/ChannelTab.java
Normal file
12
src/main/java/me/kavin/piped/utils/obj/ChannelTab.java
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
14
src/main/java/me/kavin/piped/utils/obj/ChannelTabData.java
Normal file
14
src/main/java/me/kavin/piped/utils/obj/ChannelTabData.java
Normal file
|
@ -0,0 +1,14 @@
|
|||
package me.kavin.piped.utils.obj;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ChannelTabData {
|
||||
|
||||
public String nextpage;
|
||||
public List<ContentItem> content;
|
||||
|
||||
public ChannelTabData(String nextpage, List<ContentItem> content) {
|
||||
this.nextpage = nextpage;
|
||||
this.content = content;
|
||||
}
|
||||
}
|
10
src/main/java/me/kavin/piped/utils/obj/ContentItem.java
Normal file
10
src/main/java/me/kavin/piped/utils/obj/ContentItem.java
Normal file
|
@ -0,0 +1,10 @@
|
|||
package me.kavin.piped.utils.obj;
|
||||
|
||||
public class ContentItem {
|
||||
|
||||
public String url;
|
||||
|
||||
public ContentItem(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
}
|
|
@ -6,10 +6,10 @@ public class Playlist {
|
|||
|
||||
public String name, thumbnailUrl, bannerUrl, nextpage, uploader, uploaderUrl, uploaderAvatar;
|
||||
public int videos;
|
||||
public List<StreamItem> relatedStreams;
|
||||
public List<ContentItem> relatedStreams;
|
||||
|
||||
public Playlist(String name, String thumbnailUrl, String bannerUrl, String nextpage, String uploader,
|
||||
String uploaderUrl, String uploaderAvatar, int videos, List<StreamItem> relatedStreams) {
|
||||
String uploaderUrl, String uploaderAvatar, int videos, List<ContentItem> relatedStreams) {
|
||||
this.name = name;
|
||||
this.thumbnailUrl = thumbnailUrl;
|
||||
this.bannerUrl = bannerUrl;
|
||||
|
|
23
src/main/java/me/kavin/piped/utils/obj/PlaylistItem.java
Normal file
23
src/main/java/me/kavin/piped/utils/obj/PlaylistItem.java
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<Object> items;
|
||||
public List<ContentItem> items;
|
||||
public String nextpage, suggestion;
|
||||
public boolean corrected;
|
||||
|
||||
public SearchResults(ObjectArrayList<Object> items, String nextpage) {
|
||||
public SearchResults(List<ContentItem> items, String nextpage) {
|
||||
this.nextpage = nextpage;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
public SearchResults(ObjectArrayList<Object> items, String nextpage, String suggestion, boolean corrected) {
|
||||
public SearchResults(List<ContentItem> items, String nextpage, String suggestion, boolean corrected) {
|
||||
this.items = items;
|
||||
this.nextpage = nextpage;
|
||||
this.suggestion = suggestion;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -15,7 +15,7 @@ public class Streams {
|
|||
|
||||
public List<PipedStream> audioStreams, videoStreams;
|
||||
|
||||
public List<StreamItem> relatedStreams;
|
||||
public List<ContentItem> relatedStreams;
|
||||
|
||||
public List<Subtitle> 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<PipedStream> audioStreams, List<PipedStream> videoStreams,
|
||||
List<StreamItem> relatedStreams, List<Subtitle> subtitles, boolean livestream, String hls, String dash,
|
||||
List<ContentItem> relatedStreams, List<Subtitle> subtitles, boolean livestream, String hls, String dash,
|
||||
String lbryId, List<ChapterSegment> chapters) {
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
|
|
|
@ -5,9 +5,9 @@ import java.util.List;
|
|||
public class StreamsPage {
|
||||
|
||||
public String nextpage;
|
||||
public List<StreamItem> relatedStreams;
|
||||
public List<ContentItem> relatedStreams;
|
||||
|
||||
public StreamsPage(String nextpage, List<StreamItem> relatedStreams) {
|
||||
public StreamsPage(String nextpage, List<ContentItem> relatedStreams) {
|
||||
this.nextpage = nextpage;
|
||||
this.relatedStreams = relatedStreams;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue