mirror of
https://github.com/TeamPiped/Piped-Backend.git
synced 2024-08-14 23:51:41 +00:00
refactor: simplify FeedHandlers.java by introducing FeedHelpers.java
This commit is contained in:
parent
25a49ce137
commit
b0c6116d1f
2 changed files with 107 additions and 114 deletions
|
@ -3,10 +3,7 @@ package me.kavin.piped.server.handlers.auth;
|
||||||
import com.rometools.rome.feed.synd.*;
|
import com.rometools.rome.feed.synd.*;
|
||||||
import com.rometools.rome.io.FeedException;
|
import com.rometools.rome.io.FeedException;
|
||||||
import com.rometools.rome.io.SyndFeedOutput;
|
import com.rometools.rome.io.SyndFeedOutput;
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
|
||||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||||
import jakarta.persistence.criteria.CriteriaQuery;
|
|
||||||
import jakarta.persistence.criteria.JoinType;
|
|
||||||
import me.kavin.piped.consts.Constants;
|
import me.kavin.piped.consts.Constants;
|
||||||
import me.kavin.piped.utils.*;
|
import me.kavin.piped.utils.*;
|
||||||
import me.kavin.piped.utils.obj.StreamItem;
|
import me.kavin.piped.utils.obj.StreamItem;
|
||||||
|
@ -104,24 +101,7 @@ public class FeedHandlers {
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
|
try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
|
||||||
|
|
||||||
CriteriaBuilder cb = s.getCriteriaBuilder();
|
List<StreamItem> feedItems = FeedHelpers.generateAuthenticatedFeed(s, user.getId(), Integer.MAX_VALUE)
|
||||||
|
|
||||||
// Get all videos from subscribed channels, with channel info
|
|
||||||
CriteriaQuery<Video> criteria = cb.createQuery(Video.class);
|
|
||||||
var root = criteria.from(Video.class);
|
|
||||||
root.fetch("channel", JoinType.RIGHT);
|
|
||||||
var subquery = criteria.subquery(String.class);
|
|
||||||
var subroot = subquery.from(User.class);
|
|
||||||
subquery.select(subroot.get("subscribed_ids"))
|
|
||||||
.where(cb.equal(subroot.get("id"), user.getId()));
|
|
||||||
|
|
||||||
criteria.select(root)
|
|
||||||
.where(
|
|
||||||
root.get("channel").get("uploader_id").in(subquery)
|
|
||||||
)
|
|
||||||
.orderBy(cb.desc(root.get("uploaded")));
|
|
||||||
|
|
||||||
List<StreamItem> feedItems = s.createQuery(criteria).setTimeout(20).stream()
|
|
||||||
.parallel().map(video -> {
|
.parallel().map(video -> {
|
||||||
var channel = video.getChannel();
|
var channel = video.getChannel();
|
||||||
|
|
||||||
|
@ -147,41 +127,13 @@ public class FeedHandlers {
|
||||||
User user = DatabaseHelper.getUserFromSession(session);
|
User user = DatabaseHelper.getUserFromSession(session);
|
||||||
|
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
|
|
||||||
try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
|
try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
|
||||||
|
SyndFeed feed = FeedHelpers.createRssFeed(user.getUsername());
|
||||||
|
|
||||||
SyndFeed feed = new SyndFeedImpl();
|
final List<SyndEntry> entries = FeedHelpers.generateAuthenticatedFeed(s, user.getId(), 100)
|
||||||
feed.setFeedType("atom_1.0");
|
|
||||||
feed.setTitle("Piped - Feed");
|
|
||||||
feed.setDescription(String.format("Piped's RSS subscription feed for %s.", user.getUsername()));
|
|
||||||
feed.setUri(Constants.FRONTEND_URL + "/feed");
|
|
||||||
feed.setPublishedDate(new Date());
|
|
||||||
|
|
||||||
CriteriaBuilder cb = s.getCriteriaBuilder();
|
|
||||||
|
|
||||||
// Get all videos from subscribed channels, with channel info
|
|
||||||
CriteriaQuery<Video> criteria = cb.createQuery(Video.class);
|
|
||||||
var root = criteria.from(Video.class);
|
|
||||||
root.fetch("channel", JoinType.RIGHT);
|
|
||||||
var subquery = criteria.subquery(String.class);
|
|
||||||
var subroot = subquery.from(User.class);
|
|
||||||
subquery.select(subroot.get("subscribed_ids"))
|
|
||||||
.where(cb.equal(subroot.get("id"), user.getId()));
|
|
||||||
|
|
||||||
criteria.select(root)
|
|
||||||
.where(
|
|
||||||
root.get("channel").get("uploader_id").in(subquery)
|
|
||||||
)
|
|
||||||
.orderBy(cb.desc(root.get("uploaded")));
|
|
||||||
|
|
||||||
final List<SyndEntry> entries = s.createQuery(criteria)
|
|
||||||
.setTimeout(20)
|
|
||||||
.setMaxResults(100)
|
|
||||||
.stream()
|
|
||||||
.map(video -> {
|
.map(video -> {
|
||||||
var channel = video.getChannel();
|
var channel = video.getChannel();
|
||||||
SyndEntry entry = ChannelHelpers.createEntry(video, channel);
|
return ChannelHelpers.createEntry(video, channel);
|
||||||
return entry;
|
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
feed.setEntries(entries);
|
feed.setEntries(entries);
|
||||||
|
@ -196,29 +148,15 @@ public class FeedHandlers {
|
||||||
|
|
||||||
public static byte[] unauthenticatedFeedResponse(String[] channelIds) throws Exception {
|
public static byte[] unauthenticatedFeedResponse(String[] channelIds) throws Exception {
|
||||||
|
|
||||||
Set<String> filtered = Arrays.stream(channelIds)
|
Set<String> filteredChannels = Arrays.stream(channelIds)
|
||||||
.filter(ChannelHelpers::isValidId)
|
.filter(ChannelHelpers::isValidId)
|
||||||
.collect(Collectors.toUnmodifiableSet());
|
.collect(Collectors.toUnmodifiableSet());
|
||||||
|
|
||||||
if (filtered.isEmpty())
|
if (filteredChannels.isEmpty())
|
||||||
return mapper.writeValueAsBytes(Collections.EMPTY_LIST);
|
return mapper.writeValueAsBytes(Collections.EMPTY_LIST);
|
||||||
|
|
||||||
try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
|
try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
|
||||||
|
List<StreamItem> feedItems = FeedHelpers.generateUnauthenticatedFeed(s, filteredChannels, Integer.MAX_VALUE)
|
||||||
CriteriaBuilder cb = s.getCriteriaBuilder();
|
|
||||||
|
|
||||||
// Get all videos from subscribed channels, with channel info
|
|
||||||
CriteriaQuery<Video> criteria = cb.createQuery(Video.class);
|
|
||||||
var root = criteria.from(Video.class);
|
|
||||||
root.fetch("channel", JoinType.RIGHT);
|
|
||||||
|
|
||||||
criteria.select(root)
|
|
||||||
.where(cb.and(
|
|
||||||
root.get("channel").get("id").in(filtered)
|
|
||||||
))
|
|
||||||
.orderBy(cb.desc(root.get("uploaded")));
|
|
||||||
|
|
||||||
List<StreamItem> feedItems = s.createQuery(criteria).setTimeout(20).stream()
|
|
||||||
.parallel().map(video -> {
|
.parallel().map(video -> {
|
||||||
var channel = video.getChannel();
|
var channel = video.getChannel();
|
||||||
|
|
||||||
|
@ -228,8 +166,8 @@ public class FeedHandlers {
|
||||||
video.getUploaded(), channel.isVerified(), video.isShort());
|
video.getUploaded(), channel.isVerified(), video.isShort());
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
updateSubscribedTime(filtered);
|
updateSubscribedTime(filteredChannels);
|
||||||
addMissingChannels(filtered);
|
addMissingChannels(filteredChannels);
|
||||||
|
|
||||||
return mapper.writeValueAsBytes(feedItems);
|
return mapper.writeValueAsBytes(feedItems);
|
||||||
}
|
}
|
||||||
|
@ -245,39 +183,13 @@ public class FeedHandlers {
|
||||||
ExceptionHandler.throwErrorResponse(new InvalidRequestResponse("No valid channel IDs provided"));
|
ExceptionHandler.throwErrorResponse(new InvalidRequestResponse("No valid channel IDs provided"));
|
||||||
|
|
||||||
try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
|
try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
|
||||||
|
List<Video> videos = FeedHelpers.generateUnauthenticatedFeed(s, filteredChannels, 100).toList();
|
||||||
|
|
||||||
CriteriaBuilder cb = s.getCriteriaBuilder();
|
List<SyndEntry> entries = videos.stream()
|
||||||
|
.map(video -> ChannelHelpers.createEntry(video, video.getChannel()))
|
||||||
|
.toList();
|
||||||
|
|
||||||
// Get all videos from subscribed channels, with channel info
|
SyndFeed feed = FeedHelpers.createRssFeed(null);
|
||||||
CriteriaQuery<Video> criteria = cb.createQuery(Video.class);
|
|
||||||
var root = criteria.from(Video.class);
|
|
||||||
root.fetch("channel", JoinType.RIGHT);
|
|
||||||
|
|
||||||
criteria.select(root)
|
|
||||||
.where(cb.and(
|
|
||||||
root.get("channel").get("id").in(filteredChannels)
|
|
||||||
))
|
|
||||||
.orderBy(cb.desc(root.get("uploaded")));
|
|
||||||
|
|
||||||
List<Video> videos = s.createQuery(criteria)
|
|
||||||
.setTimeout(20)
|
|
||||||
.setMaxResults(100)
|
|
||||||
.list();
|
|
||||||
|
|
||||||
SyndFeed feed = new SyndFeedImpl();
|
|
||||||
feed.setFeedType("atom_1.0");
|
|
||||||
feed.setTitle("Piped - Feed");
|
|
||||||
feed.setDescription("Piped's RSS unauthenticated subscription feed.");
|
|
||||||
feed.setUri(Constants.FRONTEND_URL + "/feed");
|
|
||||||
feed.setPublishedDate(new Date());
|
|
||||||
|
|
||||||
final List<SyndEntry> entries = new ObjectArrayList<>();
|
|
||||||
|
|
||||||
for (Video video : videos) {
|
|
||||||
var channel = video.getChannel();
|
|
||||||
SyndEntry entry = ChannelHelpers.createEntry(video, channel);
|
|
||||||
entries.add(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filteredChannels.size() == 1) {
|
if (filteredChannels.size() == 1) {
|
||||||
if (!videos.isEmpty()) {
|
if (!videos.isEmpty()) {
|
||||||
|
@ -440,12 +352,8 @@ public class FeedHandlers {
|
||||||
query.select(root)
|
query.select(root)
|
||||||
.where(root.get("uploader_id").in(subquery));
|
.where(root.get("uploader_id").in(subquery));
|
||||||
|
|
||||||
List<SubscriptionChannel> subscriptionItems = s.createQuery(query)
|
List<SubscriptionChannel> subscriptionItems = FeedHelpers
|
||||||
.stream().parallel()
|
.generateSubscriptionsList(s.createQuery(query).stream())
|
||||||
.filter(channel -> channel.getUploader() != null)
|
|
||||||
.sorted(Comparator.comparing(Channel::getUploader, String.CASE_INSENSITIVE_ORDER))
|
|
||||||
.map(channel -> new SubscriptionChannel("/channel/" + channel.getUploaderId(),
|
|
||||||
channel.getUploader(), rewriteURL(channel.getUploaderAvatar()), channel.isVerified()))
|
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
return mapper.writeValueAsBytes(subscriptionItems);
|
return mapper.writeValueAsBytes(subscriptionItems);
|
||||||
|
@ -475,12 +383,8 @@ public class FeedHandlers {
|
||||||
query.select(root);
|
query.select(root);
|
||||||
query.where(root.get("uploader_id").in(filtered));
|
query.where(root.get("uploader_id").in(filtered));
|
||||||
|
|
||||||
List<SubscriptionChannel> subscriptionItems = s.createQuery(query)
|
List<SubscriptionChannel> subscriptionItems = FeedHelpers
|
||||||
.stream().parallel()
|
.generateSubscriptionsList(s.createQuery(query).stream())
|
||||||
.filter(channel -> channel.getUploader() != null)
|
|
||||||
.sorted(Comparator.comparing(Channel::getUploader, String.CASE_INSENSITIVE_ORDER))
|
|
||||||
.map(channel -> new SubscriptionChannel("/channel/" + channel.getUploaderId(),
|
|
||||||
channel.getUploader(), rewriteURL(channel.getUploaderAvatar()), channel.isVerified()))
|
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
return mapper.writeValueAsBytes(subscriptionItems);
|
return mapper.writeValueAsBytes(subscriptionItems);
|
||||||
|
|
89
src/main/java/me/kavin/piped/utils/FeedHelpers.java
Normal file
89
src/main/java/me/kavin/piped/utils/FeedHelpers.java
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
package me.kavin.piped.utils;
|
||||||
|
|
||||||
|
import com.rometools.rome.feed.synd.SyndFeed;
|
||||||
|
import com.rometools.rome.feed.synd.SyndFeedImpl;
|
||||||
|
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||||
|
import jakarta.persistence.criteria.CriteriaQuery;
|
||||||
|
import jakarta.persistence.criteria.JoinType;
|
||||||
|
import me.kavin.piped.consts.Constants;
|
||||||
|
import me.kavin.piped.utils.obj.SubscriptionChannel;
|
||||||
|
import me.kavin.piped.utils.obj.db.Channel;
|
||||||
|
import me.kavin.piped.utils.obj.db.User;
|
||||||
|
import me.kavin.piped.utils.obj.db.Video;
|
||||||
|
import org.hibernate.StatelessSession;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static me.kavin.piped.utils.URLUtils.rewriteURL;
|
||||||
|
|
||||||
|
public class FeedHelpers {
|
||||||
|
public static Stream<Video> generateAuthenticatedFeed(StatelessSession s, long userId, int maxResults) {
|
||||||
|
CriteriaBuilder cb = s.getCriteriaBuilder();
|
||||||
|
|
||||||
|
// Get all videos from subscribed channels, with channel info
|
||||||
|
CriteriaQuery<Video> criteria = cb.createQuery(Video.class);
|
||||||
|
var root = criteria.from(Video.class);
|
||||||
|
root.fetch("channel", JoinType.RIGHT);
|
||||||
|
var subquery = criteria.subquery(String.class);
|
||||||
|
var subroot = subquery.from(User.class);
|
||||||
|
subquery.select(subroot.get("subscribed_ids"))
|
||||||
|
.where(cb.equal(subroot.get("id"), userId));
|
||||||
|
|
||||||
|
criteria.select(root)
|
||||||
|
.where(
|
||||||
|
root.get("channel").get("uploader_id").in(subquery)
|
||||||
|
)
|
||||||
|
.orderBy(cb.desc(root.get("uploaded")));
|
||||||
|
|
||||||
|
return s.createQuery(criteria).setTimeout(20).setMaxResults(maxResults).stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Stream<Video> generateUnauthenticatedFeed(StatelessSession s, Set<String> channelIds, int maxResults) {
|
||||||
|
CriteriaBuilder cb = s.getCriteriaBuilder();
|
||||||
|
|
||||||
|
// Get all videos from subscribed channels, with channel info
|
||||||
|
CriteriaQuery<Video> criteria = cb.createQuery(Video.class);
|
||||||
|
var root = criteria.from(Video.class);
|
||||||
|
root.fetch("channel", JoinType.RIGHT);
|
||||||
|
|
||||||
|
criteria.select(root)
|
||||||
|
.where(cb.and(
|
||||||
|
root.get("channel").get("id").in(channelIds)
|
||||||
|
))
|
||||||
|
.orderBy(cb.desc(root.get("uploaded")));
|
||||||
|
|
||||||
|
return s.createQuery(criteria)
|
||||||
|
.setTimeout(20)
|
||||||
|
.setMaxResults(maxResults)
|
||||||
|
.stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SyndFeed createRssFeed(@Nullable String username) {
|
||||||
|
SyndFeed feed = new SyndFeedImpl();
|
||||||
|
feed.setFeedType("atom_1.0");
|
||||||
|
feed.setTitle("Piped - Feed");
|
||||||
|
|
||||||
|
if (username == null) {
|
||||||
|
feed.setDescription("Piped's RSS unauthenticated subscription feed.");
|
||||||
|
} else {
|
||||||
|
feed.setDescription(String.format("Piped's RSS subscription feed for %s.", username));
|
||||||
|
}
|
||||||
|
|
||||||
|
feed.setUri(Constants.FRONTEND_URL + "/feed");
|
||||||
|
feed.setPublishedDate(new Date());
|
||||||
|
|
||||||
|
return feed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Stream<SubscriptionChannel> generateSubscriptionsList(Stream<Channel> channels) {
|
||||||
|
return channels.parallel()
|
||||||
|
.filter(channel -> channel.getUploader() != null)
|
||||||
|
.sorted(Comparator.comparing(Channel::getUploader, String.CASE_INSENSITIVE_ORDER))
|
||||||
|
.map(channel -> new SubscriptionChannel("/channel/" + channel.getUploaderId(),
|
||||||
|
channel.getUploader(), rewriteURL(channel.getUploaderAvatar()), channel.isVerified()));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue