mirror of
https://github.com/TeamPiped/Piped-Backend.git
synced 2025-04-29 08:20:30 +05:30
Channel Pages and search suggestions.
This commit is contained in:
parent
f3ab50402c
commit
9527ad4133
@ -20,8 +20,6 @@ public class Main {
|
|||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
System.setProperty("file.encoding", "UTF-8");
|
|
||||||
|
|
||||||
// SyndFeed feed = new SyndFeedInput().build(new XmlReader(new FileInputStream("pubsub.xml")));
|
// SyndFeed feed = new SyndFeedInput().build(new XmlReader(new FileInputStream("pubsub.xml")));
|
||||||
//
|
//
|
||||||
// feed.getEntries().forEach(entry -> {
|
// feed.getEntries().forEach(entry -> {
|
||||||
@ -97,6 +95,35 @@ public class Main {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
routes.get("/nextpage/channels/{channelId}", (req, res) -> {
|
||||||
|
|
||||||
|
QueryStringDecoder query = new QueryStringDecoder(req.uri());
|
||||||
|
|
||||||
|
try {
|
||||||
|
return writeResponse(res, ResponseHelper.channelPageResponse(req.param("channelId"),
|
||||||
|
query.parameters().get("url").get(0)), 200, "public, max-age=3600");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private");
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
routes.get("/suggestions", (req, res) -> {
|
||||||
|
|
||||||
|
QueryStringDecoder query = new QueryStringDecoder(req.uri());
|
||||||
|
|
||||||
|
try {
|
||||||
|
return writeResponse(res,
|
||||||
|
ResponseHelper.suggestionsResponse(query.parameters().get("query").get(0)), 200,
|
||||||
|
"public, max-age=600");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private");
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
routes.get("/trending", (req, res) -> {
|
routes.get("/trending", (req, res) -> {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -11,23 +11,29 @@ import java.util.List;
|
|||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
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.ChannelInfo;
|
||||||
import org.schabi.newpipe.extractor.comments.CommentsInfo;
|
import org.schabi.newpipe.extractor.comments.CommentsInfo;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
import org.schabi.newpipe.extractor.kiosk.KioskInfo;
|
import org.schabi.newpipe.extractor.kiosk.KioskInfo;
|
||||||
|
import org.schabi.newpipe.extractor.stream.Stream;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
import me.kavin.piped.consts.Constants;
|
import me.kavin.piped.consts.Constants;
|
||||||
import me.kavin.piped.utils.obj.Channel;
|
import me.kavin.piped.utils.obj.Channel;
|
||||||
import me.kavin.piped.utils.obj.Stream;
|
import me.kavin.piped.utils.obj.ChannelPage;
|
||||||
|
import me.kavin.piped.utils.obj.PipedStream;
|
||||||
import me.kavin.piped.utils.obj.StreamItem;
|
import me.kavin.piped.utils.obj.StreamItem;
|
||||||
import me.kavin.piped.utils.obj.Streams;
|
import me.kavin.piped.utils.obj.Streams;
|
||||||
import me.kavin.piped.utils.obj.Subtitle;
|
import me.kavin.piped.utils.obj.Subtitle;
|
||||||
@ -65,13 +71,13 @@ public class ResponseHelper {
|
|||||||
info.getSubtitles().forEach(subtitle -> subtitles
|
info.getSubtitles().forEach(subtitle -> subtitles
|
||||||
.add(new Subtitle(rewriteURL(subtitle.getUrl()), subtitle.getFormat().getMimeType())));
|
.add(new Subtitle(rewriteURL(subtitle.getUrl()), subtitle.getFormat().getMimeType())));
|
||||||
|
|
||||||
final List<Stream> videoStreams = new ObjectArrayList<>();
|
final List<PipedStream> videoStreams = new ObjectArrayList<>();
|
||||||
final List<Stream> audioStreams = new ObjectArrayList<>();
|
final List<PipedStream> audioStreams = new ObjectArrayList<>();
|
||||||
|
|
||||||
final String lbryURL = futureLBRY.get();
|
final String lbryURL = futureLBRY.get();
|
||||||
|
|
||||||
if (lbryURL != null)
|
if (lbryURL != null)
|
||||||
videoStreams.add(new Stream(lbryURL, "MP4", "LBRY", "video/mp4"));
|
videoStreams.add(new PipedStream(lbryURL, "MP4", "LBRY", "video/mp4"));
|
||||||
|
|
||||||
String hls = null;
|
String hls = null;
|
||||||
boolean livestream = false;
|
boolean livestream = false;
|
||||||
@ -79,13 +85,31 @@ public class ResponseHelper {
|
|||||||
if ((hls = info.getHlsUrl()) != null && !hls.isEmpty())
|
if ((hls = info.getHlsUrl()) != null && !hls.isEmpty())
|
||||||
livestream = true;
|
livestream = true;
|
||||||
|
|
||||||
info.getVideoOnlyStreams().forEach(stream -> videoStreams.add(new Stream(rewriteURL(stream.getUrl()),
|
long minexpire = Long.MAX_VALUE;
|
||||||
|
|
||||||
|
ObjectArrayList<Stream> allStreams = new ObjectArrayList<>();
|
||||||
|
|
||||||
|
allStreams.addAll(info.getVideoStreams());
|
||||||
|
allStreams.addAll(info.getAudioStreams());
|
||||||
|
allStreams.addAll(info.getVideoOnlyStreams());
|
||||||
|
|
||||||
|
for (Stream stream : allStreams) {
|
||||||
|
|
||||||
|
long expire = Long.parseLong(StringUtils.substringBetween(stream.getUrl(), "expire=", "&"));
|
||||||
|
|
||||||
|
if (expire < minexpire)
|
||||||
|
minexpire = expire;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
info.getVideoOnlyStreams().forEach(stream -> videoStreams.add(new PipedStream(rewriteURL(stream.getUrl()),
|
||||||
String.valueOf(stream.getFormat()), stream.getResolution(), stream.getFormat().getMimeType())));
|
String.valueOf(stream.getFormat()), stream.getResolution(), stream.getFormat().getMimeType())));
|
||||||
info.getVideoStreams().forEach(stream -> videoStreams.add(new Stream(rewriteURL(stream.getUrl()),
|
info.getVideoStreams().forEach(stream -> videoStreams.add(new PipedStream(rewriteURL(stream.getUrl()),
|
||||||
String.valueOf(stream.getFormat()), stream.getResolution(), stream.getFormat().getMimeType())));
|
String.valueOf(stream.getFormat()), stream.getResolution(), stream.getFormat().getMimeType())));
|
||||||
|
|
||||||
info.getAudioStreams().forEach(
|
info.getAudioStreams()
|
||||||
stream -> audioStreams.add(new Stream(rewriteURL(stream.getUrl()), String.valueOf(stream.getFormat()),
|
.forEach(stream -> audioStreams
|
||||||
|
.add(new PipedStream(rewriteURL(stream.getUrl()), String.valueOf(stream.getFormat()),
|
||||||
stream.getAverageBitrate() + " kbps", stream.getFormat().getMimeType())));
|
stream.getAverageBitrate() + " kbps", stream.getFormat().getMimeType())));
|
||||||
|
|
||||||
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||||
@ -121,13 +145,38 @@ public class ResponseHelper {
|
|||||||
item.getDuration(), item.getViewCount()));
|
item.getDuration(), item.getViewCount()));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
String nextpage = info.hasNextPage() ? info.getNextPage().getUrl() : null;
|
||||||
|
|
||||||
final Channel channel = new Channel(info.getName(), info.getAvatarUrl(), info.getBannerUrl(),
|
final Channel channel = new Channel(info.getName(), info.getAvatarUrl(), info.getBannerUrl(),
|
||||||
info.getDescription(), relatedStreams);
|
info.getDescription(), nextpage, relatedStreams);
|
||||||
|
|
||||||
return Constants.mapper.writeValueAsString(channel);
|
return Constants.mapper.writeValueAsString(channel);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final String channelPageResponse(String channelId, String url)
|
||||||
|
throws IOException, ExtractionException, InterruptedException {
|
||||||
|
|
||||||
|
InfoItemsPage<StreamInfoItem> page = ChannelInfo.getMoreItems(Constants.YOUTUBE_SERVICE,
|
||||||
|
"https://youtube.com/channel/" + channelId, new Page(url));
|
||||||
|
|
||||||
|
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||||
|
|
||||||
|
page.getItems().forEach(o -> {
|
||||||
|
StreamInfoItem item = o;
|
||||||
|
relatedStreams.add(new StreamItem(item.getUrl().substring(23), item.getName(),
|
||||||
|
rewriteURL(item.getThumbnailUrl()), item.getUploaderName(), item.getUploaderUrl().substring(23),
|
||||||
|
item.getDuration(), item.getViewCount()));
|
||||||
|
});
|
||||||
|
|
||||||
|
String nextpage = page.hasNextPage() ? page.getNextPage().getUrl() : null;
|
||||||
|
|
||||||
|
final ChannelPage channelpage = new ChannelPage(nextpage, relatedStreams);
|
||||||
|
|
||||||
|
return Constants.mapper.writeValueAsString(channelpage);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||||
|
|
||||||
public static final String trendingResponse() throws ParsingException, ExtractionException, IOException {
|
public static final String trendingResponse() throws ParsingException, ExtractionException, IOException {
|
||||||
@ -148,6 +197,14 @@ public class ResponseHelper {
|
|||||||
return Constants.mapper.writeValueAsString(relatedStreams);
|
return Constants.mapper.writeValueAsString(relatedStreams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final String suggestionsResponse(String query)
|
||||||
|
throws JsonProcessingException, IOException, ExtractionException {
|
||||||
|
|
||||||
|
return Constants.mapper
|
||||||
|
.writeValueAsString(Constants.YOUTUBE_SERVICE.getSuggestionExtractor().suggestionList(query));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private static final String getLBRYStreamURL(String videoId) throws IOException, InterruptedException {
|
private static final String getLBRYStreamURL(String videoId) throws IOException, InterruptedException {
|
||||||
|
|
||||||
String lbryId = new JSONObject(Constants.h2client.send(HttpRequest
|
String lbryId = new JSONObject(Constants.h2client.send(HttpRequest
|
||||||
|
@ -4,14 +4,15 @@ import java.util.List;
|
|||||||
|
|
||||||
public class Channel {
|
public class Channel {
|
||||||
|
|
||||||
private String name, avatarUrl, bannerUrl, description;
|
private String name, avatarUrl, bannerUrl, description, nextpage;
|
||||||
private List<StreamItem> relatedStreams;
|
private List<StreamItem> relatedStreams;
|
||||||
|
|
||||||
public Channel(String name, String avatarUrl, String bannerUrl, String description,
|
public Channel(String name, String avatarUrl, String bannerUrl, String description, String nextpage,
|
||||||
List<StreamItem> relatedStreams) {
|
List<StreamItem> relatedStreams) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.avatarUrl = avatarUrl;
|
this.avatarUrl = avatarUrl;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
|
this.nextpage = nextpage;
|
||||||
this.relatedStreams = relatedStreams;
|
this.relatedStreams = relatedStreams;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,6 +32,10 @@ public class Channel {
|
|||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getNextpage() {
|
||||||
|
return nextpage;
|
||||||
|
}
|
||||||
|
|
||||||
public List<StreamItem> getRelatedStreams() {
|
public List<StreamItem> getRelatedStreams() {
|
||||||
return relatedStreams;
|
return relatedStreams;
|
||||||
}
|
}
|
||||||
|
22
src/main/java/me/kavin/piped/utils/obj/ChannelPage.java
Normal file
22
src/main/java/me/kavin/piped/utils/obj/ChannelPage.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package me.kavin.piped.utils.obj;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ChannelPage {
|
||||||
|
|
||||||
|
private String nextpage;
|
||||||
|
private List<StreamItem> relatedStreams;
|
||||||
|
|
||||||
|
public ChannelPage(String nextpage, List<StreamItem> relatedStreams) {
|
||||||
|
this.nextpage = nextpage;
|
||||||
|
this.relatedStreams = relatedStreams;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNextpage() {
|
||||||
|
return nextpage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<StreamItem> getRelatedStreams() {
|
||||||
|
return relatedStreams;
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
package me.kavin.piped.utils.obj;
|
package me.kavin.piped.utils.obj;
|
||||||
|
|
||||||
public class Stream {
|
public class PipedStream {
|
||||||
|
|
||||||
private String url, format, quality, mimeType;
|
private String url, format, quality, mimeType;
|
||||||
|
|
||||||
public Stream(String url, String format, String quality, String mimeType) {
|
public PipedStream(String url, String format, String quality, String mimeType) {
|
||||||
this.url = url;
|
this.url = url;
|
||||||
this.format = format;
|
this.format = format;
|
||||||
this.quality = quality;
|
this.quality = quality;
|
@ -8,7 +8,7 @@ public class Streams {
|
|||||||
|
|
||||||
private long duration, views, likes, dislikes;
|
private long duration, views, likes, dislikes;
|
||||||
|
|
||||||
private List<Stream> audioStreams, videoStreams;
|
private List<PipedStream> audioStreams, videoStreams;
|
||||||
|
|
||||||
private List<StreamItem> relatedStreams;
|
private List<StreamItem> relatedStreams;
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ public class Streams {
|
|||||||
|
|
||||||
public Streams(String title, String description, String uploadDate, String uploader, String uploaderUrl,
|
public Streams(String title, String description, String uploadDate, String uploader, String uploaderUrl,
|
||||||
String uploaderAvatar, String thumbnailUrl, long duration, long views, long likes, long dislikes,
|
String uploaderAvatar, String thumbnailUrl, long duration, long views, long likes, long dislikes,
|
||||||
List<Stream> audioStreams, List<Stream> videoStreams, List<StreamItem> relatedStreams,
|
List<PipedStream> audioStreams, List<PipedStream> videoStreams, List<StreamItem> relatedStreams,
|
||||||
List<Subtitle> subtitles, boolean livestream, String hls) {
|
List<Subtitle> subtitles, boolean livestream, String hls) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
@ -83,11 +83,11 @@ public class Streams {
|
|||||||
return dislikes;
|
return dislikes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Stream> getAudioStreams() {
|
public List<PipedStream> getAudioStreams() {
|
||||||
return audioStreams;
|
return audioStreams;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Stream> getVideoStreams() {
|
public List<PipedStream> getVideoStreams() {
|
||||||
return videoStreams;
|
return videoStreams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user