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.io.FeedException;
 | 
			
		||||
import com.rometools.rome.io.SyndFeedOutput;
 | 
			
		||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
 | 
			
		||||
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.*;
 | 
			
		||||
import me.kavin.piped.utils.obj.StreamItem;
 | 
			
		||||
| 
						 | 
				
			
			@ -104,24 +101,7 @@ public class FeedHandlers {
 | 
			
		|||
        if (user != null) {
 | 
			
		||||
            try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
 | 
			
		||||
 | 
			
		||||
                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")));
 | 
			
		||||
 | 
			
		||||
                List<StreamItem> feedItems = s.createQuery(criteria).setTimeout(20).stream()
 | 
			
		||||
                List<StreamItem> feedItems = FeedHelpers.generateAuthenticatedFeed(s, user.getId(), Integer.MAX_VALUE)
 | 
			
		||||
                        .parallel().map(video -> {
 | 
			
		||||
                            var channel = video.getChannel();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -147,41 +127,13 @@ public class FeedHandlers {
 | 
			
		|||
        User user = DatabaseHelper.getUserFromSession(session);
 | 
			
		||||
 | 
			
		||||
        if (user != null) {
 | 
			
		||||
 | 
			
		||||
            try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
 | 
			
		||||
                SyndFeed feed = FeedHelpers.createRssFeed(user.getUsername());
 | 
			
		||||
 | 
			
		||||
                SyndFeed feed = new SyndFeedImpl();
 | 
			
		||||
                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()
 | 
			
		||||
                final List<SyndEntry> entries = FeedHelpers.generateAuthenticatedFeed(s, user.getId(), 100)
 | 
			
		||||
                        .map(video -> {
 | 
			
		||||
                            var channel = video.getChannel();
 | 
			
		||||
                            SyndEntry entry = ChannelHelpers.createEntry(video, channel);
 | 
			
		||||
                            return entry;
 | 
			
		||||
                            return ChannelHelpers.createEntry(video, channel);
 | 
			
		||||
                        }).toList();
 | 
			
		||||
 | 
			
		||||
                feed.setEntries(entries);
 | 
			
		||||
| 
						 | 
				
			
			@ -196,29 +148,15 @@ public class FeedHandlers {
 | 
			
		|||
 | 
			
		||||
    public static byte[] unauthenticatedFeedResponse(String[] channelIds) throws Exception {
 | 
			
		||||
 | 
			
		||||
        Set<String> filtered = Arrays.stream(channelIds)
 | 
			
		||||
        Set<String> filteredChannels = Arrays.stream(channelIds)
 | 
			
		||||
                .filter(ChannelHelpers::isValidId)
 | 
			
		||||
                .collect(Collectors.toUnmodifiableSet());
 | 
			
		||||
 | 
			
		||||
        if (filtered.isEmpty())
 | 
			
		||||
        if (filteredChannels.isEmpty())
 | 
			
		||||
            return mapper.writeValueAsBytes(Collections.EMPTY_LIST);
 | 
			
		||||
 | 
			
		||||
        try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
 | 
			
		||||
 | 
			
		||||
            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()
 | 
			
		||||
            List<StreamItem> feedItems = FeedHelpers.generateUnauthenticatedFeed(s, filteredChannels, Integer.MAX_VALUE)
 | 
			
		||||
                    .parallel().map(video -> {
 | 
			
		||||
                        var channel = video.getChannel();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -228,8 +166,8 @@ public class FeedHandlers {
 | 
			
		|||
                                video.getUploaded(), channel.isVerified(), video.isShort());
 | 
			
		||||
                    }).toList();
 | 
			
		||||
 | 
			
		||||
            updateSubscribedTime(filtered);
 | 
			
		||||
            addMissingChannels(filtered);
 | 
			
		||||
            updateSubscribedTime(filteredChannels);
 | 
			
		||||
            addMissingChannels(filteredChannels);
 | 
			
		||||
 | 
			
		||||
            return mapper.writeValueAsBytes(feedItems);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -245,39 +183,13 @@ public class FeedHandlers {
 | 
			
		|||
            ExceptionHandler.throwErrorResponse(new InvalidRequestResponse("No valid channel IDs provided"));
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
            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);
 | 
			
		||||
            }
 | 
			
		||||
            SyndFeed feed = FeedHelpers.createRssFeed(null);
 | 
			
		||||
 | 
			
		||||
            if (filteredChannels.size() == 1) {
 | 
			
		||||
                if (!videos.isEmpty()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -440,12 +352,8 @@ public class FeedHandlers {
 | 
			
		|||
                query.select(root)
 | 
			
		||||
                        .where(root.get("uploader_id").in(subquery));
 | 
			
		||||
 | 
			
		||||
                List<SubscriptionChannel> subscriptionItems = s.createQuery(query)
 | 
			
		||||
                        .stream().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()))
 | 
			
		||||
                List<SubscriptionChannel> subscriptionItems = FeedHelpers
 | 
			
		||||
                        .generateSubscriptionsList(s.createQuery(query).stream())
 | 
			
		||||
                        .toList();
 | 
			
		||||
 | 
			
		||||
                return mapper.writeValueAsBytes(subscriptionItems);
 | 
			
		||||
| 
						 | 
				
			
			@ -475,12 +383,8 @@ public class FeedHandlers {
 | 
			
		|||
            query.select(root);
 | 
			
		||||
            query.where(root.get("uploader_id").in(filtered));
 | 
			
		||||
 | 
			
		||||
            List<SubscriptionChannel> subscriptionItems = s.createQuery(query)
 | 
			
		||||
                    .stream().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()))
 | 
			
		||||
            List<SubscriptionChannel> subscriptionItems = FeedHelpers
 | 
			
		||||
                    .generateSubscriptionsList(s.createQuery(query).stream())
 | 
			
		||||
                    .toList();
 | 
			
		||||
 | 
			
		||||
            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…
	
	Add table
		Add a link
		
	
		Reference in a new issue