mirror of
https://github.com/TeamPiped/Piped-Backend.git
synced 2024-08-14 23:51:41 +00:00
commit
edf9ae5b8f
7 changed files with 565 additions and 15 deletions
|
@ -17,6 +17,7 @@ import me.kavin.piped.utils.*;
|
|||
import me.kavin.piped.utils.resp.ErrorResponse;
|
||||
import me.kavin.piped.utils.resp.LoginRequest;
|
||||
import me.kavin.piped.utils.resp.SubscriptionUpdateRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.hibernate.Session;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -129,8 +130,10 @@ public class ServerLauncher extends MultithreadedHttpServerLauncher {
|
|||
}
|
||||
})).map(GET, "/playlists/:playlistId", AsyncServlet.ofBlocking(executor, request -> {
|
||||
try {
|
||||
return getJsonResponse(ResponseHelper.playlistResponse(request.getPathParameter("playlistId")),
|
||||
"public, max-age=600", true);
|
||||
var playlistId = request.getPathParameter("playlistId");
|
||||
var cache = StringUtils.isBlank(playlistId) || playlistId.length() != 36 ?
|
||||
"public, max-age=600" : "private";
|
||||
return getJsonResponse(ResponseHelper.playlistResponse(playlistId), cache, true);
|
||||
} catch (Exception e) {
|
||||
return getErrorResponse(e, request.getPath());
|
||||
}
|
||||
|
@ -278,6 +281,45 @@ public class ServerLauncher extends MultithreadedHttpServerLauncher {
|
|||
} catch (Exception e) {
|
||||
return getErrorResponse(e, request.getPath());
|
||||
}
|
||||
})).map(POST, "/user/playlists/create", AsyncServlet.ofBlocking(executor, request -> {
|
||||
try {
|
||||
var name = Constants.mapper.readTree(request.loadBody().getResult().asArray()).get("name").asText();
|
||||
return getJsonResponse(ResponseHelper.createPlaylist(request.getHeader(AUTHORIZATION), name), "private");
|
||||
} catch (Exception e) {
|
||||
return getErrorResponse(e, request.getPath());
|
||||
}
|
||||
})).map(GET, "/user/playlists", AsyncServlet.ofBlocking(executor, request -> {
|
||||
try {
|
||||
return getJsonResponse(ResponseHelper.playlistsResponse(request.getHeader(AUTHORIZATION)), "private");
|
||||
} catch (Exception e) {
|
||||
return getErrorResponse(e, request.getPath());
|
||||
}
|
||||
})).map(POST, "/user/playlists/add", AsyncServlet.ofBlocking(executor, request -> {
|
||||
try {
|
||||
var json = Constants.mapper.readTree(request.loadBody().getResult().asArray());
|
||||
var playlistId = json.get("playlistId").asText();
|
||||
var videoId = json.get("videoId").asText();
|
||||
return getJsonResponse(ResponseHelper.addToPlaylistResponse(request.getHeader(AUTHORIZATION), playlistId, videoId), "private");
|
||||
} catch (Exception e) {
|
||||
return getErrorResponse(e, request.getPath());
|
||||
}
|
||||
})).map(POST, "/user/playlists/remove", AsyncServlet.ofBlocking(executor, request -> {
|
||||
try {
|
||||
var json = Constants.mapper.readTree(request.loadBody().getResult().asArray());
|
||||
var playlistId = json.get("playlistId").asText();
|
||||
var index = json.get("index").asInt();
|
||||
return getJsonResponse(ResponseHelper.removeFromPlaylistResponse(request.getHeader(AUTHORIZATION), playlistId, index), "private");
|
||||
} catch (Exception e) {
|
||||
return getErrorResponse(e, request.getPath());
|
||||
}
|
||||
})).map(POST, "/user/playlists/delete", AsyncServlet.ofBlocking(executor, request -> {
|
||||
try {
|
||||
var json = Constants.mapper.readTree(request.loadBody().getResult().asArray());
|
||||
var playlistId = json.get("playlistId").asText();
|
||||
return getJsonResponse(ResponseHelper.deletePlaylistResponse(request.getHeader(AUTHORIZATION), playlistId), "private");
|
||||
} catch (Exception e) {
|
||||
return getErrorResponse(e, request.getPath());
|
||||
}
|
||||
})).map(GET, "/registered/badge", AsyncServlet.ofBlocking(executor, request -> {
|
||||
try {
|
||||
return HttpResponse.ofCode(302).withHeader(LOCATION, ResponseHelper.registeredBadgeRedirect())
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
package me.kavin.piped.utils;
|
||||
|
||||
import me.kavin.piped.utils.obj.db.Channel;
|
||||
import me.kavin.piped.utils.obj.db.PubSub;
|
||||
import me.kavin.piped.utils.obj.db.User;
|
||||
import me.kavin.piped.utils.obj.db.Video;
|
||||
import me.kavin.piped.utils.obj.db.*;
|
||||
import org.hibernate.Session;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.JoinType;
|
||||
import javax.persistence.criteria.Root;
|
||||
import java.util.UUID;
|
||||
|
||||
public class DatabaseHelper {
|
||||
|
||||
public static final User getUserFromSession(String session) {
|
||||
public static User getUserFromSession(String session) {
|
||||
try (Session s = DatabaseSessionFactory.createSession()) {
|
||||
CriteriaBuilder cb = s.getCriteriaBuilder();
|
||||
CriteriaQuery<User> cr = cb.createQuery(User.class);
|
||||
|
@ -24,7 +22,7 @@ public class DatabaseHelper {
|
|||
}
|
||||
}
|
||||
|
||||
public static final User getUserFromSessionWithSubscribed(String session) {
|
||||
public static User getUserFromSessionWithSubscribed(String session) {
|
||||
try (Session s = DatabaseSessionFactory.createSession()) {
|
||||
CriteriaBuilder cb = s.getCriteriaBuilder();
|
||||
CriteriaQuery<User> cr = cb.createQuery(User.class);
|
||||
|
@ -36,7 +34,7 @@ public class DatabaseHelper {
|
|||
}
|
||||
}
|
||||
|
||||
public static final Channel getChannelFromId(Session s, String id) {
|
||||
public static Channel getChannelFromId(Session s, String id) {
|
||||
CriteriaBuilder cb = s.getCriteriaBuilder();
|
||||
CriteriaQuery<Channel> cr = cb.createQuery(Channel.class);
|
||||
Root<Channel> root = cr.from(Channel.class);
|
||||
|
@ -45,7 +43,7 @@ public class DatabaseHelper {
|
|||
return s.createQuery(cr).uniqueResult();
|
||||
}
|
||||
|
||||
public static final Video getVideoFromId(Session s, String id) {
|
||||
public static Video getVideoFromId(Session s, String id) {
|
||||
CriteriaBuilder cb = s.getCriteriaBuilder();
|
||||
CriteriaQuery<Video> cr = cb.createQuery(Video.class);
|
||||
Root<Video> root = cr.from(Video.class);
|
||||
|
@ -54,7 +52,25 @@ public class DatabaseHelper {
|
|||
return s.createQuery(cr).uniqueResult();
|
||||
}
|
||||
|
||||
public static final PubSub getPubSubFromId(Session s, String id) {
|
||||
public static PlaylistVideo getPlaylistVideoFromId(Session s, String id) {
|
||||
CriteriaBuilder cb = s.getCriteriaBuilder();
|
||||
CriteriaQuery<PlaylistVideo> cr = cb.createQuery(PlaylistVideo.class);
|
||||
Root<PlaylistVideo> root = cr.from(PlaylistVideo.class);
|
||||
cr.select(root).where(cb.equal(root.get("id"), id));
|
||||
|
||||
return s.createQuery(cr).uniqueResult();
|
||||
}
|
||||
|
||||
public static Playlist getPlaylistFromId(Session s, String id) {
|
||||
CriteriaBuilder cb = s.getCriteriaBuilder();
|
||||
CriteriaQuery<Playlist> cr = cb.createQuery(Playlist.class);
|
||||
Root<Playlist> root = cr.from(Playlist.class);
|
||||
cr.select(root).where(cb.equal(root.get("playlist_id"), UUID.fromString(id)));
|
||||
|
||||
return s.createQuery(cr).uniqueResult();
|
||||
}
|
||||
|
||||
public static PubSub getPubSubFromId(Session s, String id) {
|
||||
CriteriaBuilder cb = s.getCriteriaBuilder();
|
||||
CriteriaQuery<PubSub> cr = cb.createQuery(PubSub.class);
|
||||
Root<PubSub> root = cr.from(PubSub.class);
|
||||
|
|
|
@ -2,6 +2,8 @@ package me.kavin.piped.utils;
|
|||
|
||||
import me.kavin.piped.consts.Constants;
|
||||
import me.kavin.piped.utils.obj.db.Channel;
|
||||
import me.kavin.piped.utils.obj.db.Playlist;
|
||||
import me.kavin.piped.utils.obj.db.PlaylistVideo;
|
||||
import me.kavin.piped.utils.obj.db.PubSub;
|
||||
import me.kavin.piped.utils.obj.db.User;
|
||||
import me.kavin.piped.utils.obj.db.Video;
|
||||
|
@ -21,8 +23,9 @@ public class DatabaseSessionFactory {
|
|||
configuration.setProperty("hibernate.temp.use_jdbc_metadata_defaults", "false");
|
||||
configuration.configure();
|
||||
|
||||
sessionFactory = configuration.addAnnotatedClass(User.class).addAnnotatedClass(Video.class)
|
||||
.addAnnotatedClass(Channel.class).addAnnotatedClass(PubSub.class).buildSessionFactory();
|
||||
sessionFactory = configuration.addAnnotatedClass(User.class).addAnnotatedClass(Channel.class)
|
||||
.addAnnotatedClass(Video.class).addAnnotatedClass(PubSub.class).addAnnotatedClass(Playlist.class)
|
||||
.addAnnotatedClass(PlaylistVideo.class).buildSessionFactory();
|
||||
}
|
||||
|
||||
public static final Session createSession() {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package me.kavin.piped.utils;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.grack.nanojson.JsonObject;
|
||||
import com.grack.nanojson.JsonWriter;
|
||||
import com.rometools.rome.feed.synd.*;
|
||||
|
@ -10,6 +11,7 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
|||
import me.kavin.piped.consts.Constants;
|
||||
import me.kavin.piped.ipfs.IPFS;
|
||||
import me.kavin.piped.utils.obj.*;
|
||||
import me.kavin.piped.utils.obj.db.PlaylistVideo;
|
||||
import me.kavin.piped.utils.obj.db.PubSub;
|
||||
import me.kavin.piped.utils.obj.db.User;
|
||||
import me.kavin.piped.utils.obj.db.Video;
|
||||
|
@ -278,7 +280,53 @@ public class ResponseHelper {
|
|||
return Constants.mapper.writeValueAsBytes(relatedStreams);
|
||||
}
|
||||
|
||||
public static byte[] playlistResponse(String playlistId)
|
||||
public static byte[] playlistResponse(String playlistId) throws ExtractionException, IOException {
|
||||
|
||||
if (StringUtils.isBlank(playlistId))
|
||||
return Constants.mapper.writeValueAsBytes(new InvalidRequestResponse());
|
||||
|
||||
if (playlistId.matches("[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"))
|
||||
return playlistPipedResponse(playlistId);
|
||||
|
||||
return playlistYouTubeResponse(playlistId);
|
||||
}
|
||||
|
||||
private static byte[] playlistPipedResponse(String playlistId) throws IOException {
|
||||
try (Session s = DatabaseSessionFactory.createSession()) {
|
||||
var cb = s.getCriteriaBuilder();
|
||||
var cq = cb.createQuery(me.kavin.piped.utils.obj.db.Playlist.class);
|
||||
var root = cq.from(me.kavin.piped.utils.obj.db.Playlist.class);
|
||||
root.fetch("videos", JoinType.LEFT)
|
||||
.fetch("channel", JoinType.LEFT);
|
||||
root.fetch("owner", JoinType.INNER);
|
||||
cq.select(root);
|
||||
cq.where(cb.equal(root.get("playlist_id"), UUID.fromString(playlistId)));
|
||||
var query = s.createQuery(cq);
|
||||
var pl = query.uniqueResult();
|
||||
|
||||
if (pl == null)
|
||||
return Constants.mapper.writeValueAsBytes(Constants.mapper.createObjectNode()
|
||||
.put("error", "Playlist not found"));
|
||||
|
||||
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
|
||||
var videos = pl.getVideos();
|
||||
|
||||
for (var video : videos) {
|
||||
var channel = video.getChannel();
|
||||
relatedStreams.add(new StreamItem("/watch?v=" + video.getId(), video.getTitle(), rewriteURL(video.getThumbnail()), channel.getUploader(),
|
||||
"/channel/" + channel.getUploaderId(), rewriteURL(channel.getUploaderAvatar()), null, null,
|
||||
video.getDuration(), -1, -1, channel.isVerified()));
|
||||
}
|
||||
|
||||
final Playlist playlist = new Playlist(pl.getName(), rewriteURL(pl.getThumbnail()), null, null, pl.getOwner().getUsername(),
|
||||
null, null, videos.size(), relatedStreams);
|
||||
|
||||
return Constants.mapper.writeValueAsBytes(playlist);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] playlistYouTubeResponse(String playlistId)
|
||||
throws IOException, ExtractionException {
|
||||
|
||||
final PlaylistInfo info = PlaylistInfo.getInfo("https://www.youtube.com/playlist?list=" + playlistId);
|
||||
|
@ -327,7 +375,58 @@ public class ResponseHelper {
|
|||
|
||||
}
|
||||
|
||||
public static byte[] playlistRSSResponse(String playlistId)
|
||||
public static byte[] playlistRSSResponse(String playlistId) throws ExtractionException, IOException, FeedException {
|
||||
|
||||
if (StringUtils.isBlank(playlistId))
|
||||
return Constants.mapper.writeValueAsBytes(new InvalidRequestResponse());
|
||||
|
||||
if (playlistId.matches("[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"))
|
||||
return playlistPipedRSSResponse(playlistId);
|
||||
|
||||
return playlistYouTubeRSSResponse(playlistId);
|
||||
}
|
||||
|
||||
private static byte[] playlistPipedRSSResponse(String playlistId)
|
||||
throws FeedException {
|
||||
|
||||
try (Session s = DatabaseSessionFactory.createSession()) {
|
||||
var cb = s.getCriteriaBuilder();
|
||||
var cq = cb.createQuery(me.kavin.piped.utils.obj.db.Playlist.class);
|
||||
var root = cq.from(me.kavin.piped.utils.obj.db.Playlist.class);
|
||||
root.fetch("videos", JoinType.LEFT)
|
||||
.fetch("channel", JoinType.LEFT);
|
||||
root.fetch("owner", JoinType.INNER);
|
||||
cq.select(root);
|
||||
cq.where(cb.equal(root.get("playlist_id"), UUID.fromString(playlistId)));
|
||||
var query = s.createQuery(cq);
|
||||
var pl = query.uniqueResult();
|
||||
|
||||
final List<SyndEntry> entries = new ObjectArrayList<>();
|
||||
|
||||
SyndFeed feed = new SyndFeedImpl();
|
||||
feed.setFeedType("rss_2.0");
|
||||
feed.setTitle(pl.getName());
|
||||
feed.setAuthor(pl.getOwner().getUsername());
|
||||
feed.setDescription(String.format("%s - Piped", pl.getName()));
|
||||
feed.setLink(Constants.FRONTEND_URL + "/playlist?list=" + pl.getPlaylistId());
|
||||
feed.setPublishedDate(new Date());
|
||||
|
||||
for (var video : pl.getVideos()) {
|
||||
SyndEntry entry = new SyndEntryImpl();
|
||||
entry.setAuthor(video.getChannel().getUploader());
|
||||
entry.setLink(Constants.FRONTEND_URL + "/video?id=" + video.getId());
|
||||
entry.setUri(Constants.FRONTEND_URL + "/video?id=" + video.getId());
|
||||
entry.setTitle(video.getTitle());
|
||||
entries.add(entry);
|
||||
}
|
||||
|
||||
feed.setEntries(entries);
|
||||
|
||||
return new SyndFeedOutput().outputString(feed).getBytes(UTF_8);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] playlistYouTubeRSSResponse(String playlistId)
|
||||
throws IOException, ExtractionException, FeedException {
|
||||
|
||||
final PlaylistInfo info = PlaylistInfo.getInfo("https://www.youtube.com/playlist?list=" + playlistId);
|
||||
|
@ -910,6 +1009,194 @@ public class ResponseHelper {
|
|||
|
||||
}
|
||||
|
||||
public static byte[] createPlaylist(String session, String name) throws IOException {
|
||||
|
||||
if (StringUtils.isBlank(name))
|
||||
return Constants.mapper.writeValueAsBytes(new InvalidRequestResponse());
|
||||
|
||||
User user = DatabaseHelper.getUserFromSession(session);
|
||||
|
||||
if (user == null)
|
||||
return Constants.mapper.writeValueAsBytes(new AuthenticationFailureResponse());
|
||||
|
||||
try (Session s = DatabaseSessionFactory.createSession()) {
|
||||
var playlist = new me.kavin.piped.utils.obj.db.Playlist(name, user, "https://i.ytimg.com/");
|
||||
s.save(playlist);
|
||||
s.getTransaction().begin();
|
||||
s.getTransaction().commit();
|
||||
|
||||
ObjectNode response = Constants.mapper.createObjectNode();
|
||||
response.put("playlistId", String.valueOf(playlist.getPlaylistId()));
|
||||
|
||||
return Constants.mapper.writeValueAsBytes(response);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] deletePlaylistResponse(String session, String playlistId) throws IOException {
|
||||
|
||||
if (StringUtils.isBlank(playlistId))
|
||||
return Constants.mapper.writeValueAsBytes(new InvalidRequestResponse());
|
||||
|
||||
User user = DatabaseHelper.getUserFromSession(session);
|
||||
|
||||
if (user == null)
|
||||
return Constants.mapper.writeValueAsBytes(new AuthenticationFailureResponse());
|
||||
|
||||
try (Session s = DatabaseSessionFactory.createSession()) {
|
||||
var playlist = DatabaseHelper.getPlaylistFromId(s, playlistId);
|
||||
|
||||
if (playlist == null)
|
||||
return Constants.mapper.writeValueAsBytes(Constants.mapper.createObjectNode()
|
||||
.put("error", "Playlist not found"));
|
||||
|
||||
if (playlist.getOwner().getId() != user.getId())
|
||||
return Constants.mapper.writeValueAsBytes(Constants.mapper.createObjectNode()
|
||||
.put("error", "You do not own this playlist"));
|
||||
|
||||
s.delete(playlist);
|
||||
|
||||
s.getTransaction().begin();
|
||||
s.getTransaction().commit();
|
||||
}
|
||||
|
||||
return Constants.mapper.writeValueAsBytes(new AcceptedResponse());
|
||||
}
|
||||
|
||||
public static byte[] playlistsResponse(String session) throws IOException {
|
||||
|
||||
User user = DatabaseHelper.getUserFromSession(session);
|
||||
|
||||
if (user == null)
|
||||
return Constants.mapper.writeValueAsBytes(new AuthenticationFailureResponse());
|
||||
|
||||
try (Session s = DatabaseSessionFactory.createSession()) {
|
||||
var cb = s.getCriteriaBuilder();
|
||||
var query = cb.createQuery(me.kavin.piped.utils.obj.db.Playlist.class);
|
||||
var root = query.from(me.kavin.piped.utils.obj.db.Playlist.class);
|
||||
query.select(root);
|
||||
query.where(cb.equal(root.get("owner"), user));
|
||||
|
||||
var playlists = new ObjectArrayList<>();
|
||||
|
||||
for (var playlist : s.createQuery(query).list()) {
|
||||
ObjectNode node = Constants.mapper.createObjectNode();
|
||||
node.put("id", String.valueOf(playlist.getPlaylistId()));
|
||||
node.put("name", playlist.getName());
|
||||
node.put("shortDescription", playlist.getShortDescription());
|
||||
node.put("thumbnail", rewriteURL(playlist.getThumbnail()));
|
||||
playlists.add(node);
|
||||
}
|
||||
|
||||
return Constants.mapper.writeValueAsBytes(playlists);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] addToPlaylistResponse(String session, String playlistId, String videoId) throws IOException, ExtractionException {
|
||||
|
||||
if (StringUtils.isBlank(playlistId) || StringUtils.isBlank(videoId))
|
||||
return Constants.mapper.writeValueAsBytes(new InvalidRequestResponse());
|
||||
|
||||
var user = DatabaseHelper.getUserFromSession(session);
|
||||
|
||||
if (user == null)
|
||||
return Constants.mapper.writeValueAsBytes(new AuthenticationFailureResponse());
|
||||
|
||||
try (Session s = DatabaseSessionFactory.createSession()) {
|
||||
var cb = s.getCriteriaBuilder();
|
||||
var query = cb.createQuery(me.kavin.piped.utils.obj.db.Playlist.class);
|
||||
var root = query.from(me.kavin.piped.utils.obj.db.Playlist.class);
|
||||
root.fetch("videos", JoinType.LEFT);
|
||||
root.fetch("owner", JoinType.LEFT);
|
||||
query.where(cb.equal(root.get("playlist_id"), UUID.fromString(playlistId)));
|
||||
var playlist = s.createQuery(query).uniqueResult();
|
||||
|
||||
if (playlist == null)
|
||||
return Constants.mapper.writeValueAsBytes(Constants.mapper.createObjectNode()
|
||||
.put("error", "Playlist not found"));
|
||||
|
||||
if (playlist.getOwner().getId() != user.getId())
|
||||
return Constants.mapper.writeValueAsBytes(Constants.mapper.createObjectNode()
|
||||
.put("error", "You are not the owner this playlist"));
|
||||
|
||||
var video = DatabaseHelper.getPlaylistVideoFromId(s, videoId);
|
||||
|
||||
if (video == null) {
|
||||
StreamInfo info = StreamInfo.getInfo("https://www.youtube.com/watch?v=" + videoId);
|
||||
|
||||
String channelId = StringUtils.substringAfter(info.getUploaderUrl(), "/channel/");
|
||||
|
||||
var channel = DatabaseHelper.getChannelFromId(s, channelId);
|
||||
|
||||
if (channel == null) {
|
||||
ChannelInfo channelInfo = ChannelInfo.getInfo(info.getUploaderUrl());
|
||||
|
||||
channel = new me.kavin.piped.utils.obj.db.Channel(channelId, channelInfo.getName(),
|
||||
channelInfo.getAvatarUrl(), channelInfo.isVerified());
|
||||
s.save(channel);
|
||||
|
||||
if (!s.getTransaction().isActive())
|
||||
s.getTransaction().begin();
|
||||
}
|
||||
|
||||
video = new PlaylistVideo(videoId, info.getName(), info.getThumbnailUrl(), info.getDuration(), channel);
|
||||
|
||||
s.save(video);
|
||||
|
||||
if (!s.getTransaction().isActive())
|
||||
s.getTransaction().begin();
|
||||
}
|
||||
|
||||
if (playlist.getVideos().isEmpty())
|
||||
playlist.setThumbnail(video.getThumbnail());
|
||||
|
||||
playlist.getVideos().add(video);
|
||||
|
||||
if (!s.getTransaction().isActive())
|
||||
s.getTransaction().begin();
|
||||
s.getTransaction().commit();
|
||||
|
||||
return Constants.mapper.writeValueAsBytes(new AcceptedResponse());
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] removeFromPlaylistResponse(String session, String playlistId, int index) throws IOException {
|
||||
|
||||
if (StringUtils.isBlank(playlistId))
|
||||
return Constants.mapper.writeValueAsBytes(new InvalidRequestResponse());
|
||||
|
||||
try (Session s = DatabaseSessionFactory.createSession()) {
|
||||
var cb = s.getCriteriaBuilder();
|
||||
var query = cb.createQuery(me.kavin.piped.utils.obj.db.Playlist.class);
|
||||
var root = query.from(me.kavin.piped.utils.obj.db.Playlist.class);
|
||||
root.fetch("videos", JoinType.LEFT);
|
||||
root.fetch("owner", JoinType.LEFT);
|
||||
query.where(cb.equal(root.get("playlist_id"), UUID.fromString(playlistId)));
|
||||
var playlist = s.createQuery(query).uniqueResult();
|
||||
|
||||
if (playlist == null)
|
||||
return Constants.mapper.writeValueAsBytes(Constants.mapper.createObjectNode()
|
||||
.put("error", "Playlist not found"));
|
||||
|
||||
if (playlist.getOwner().getId() != DatabaseHelper.getUserFromSession(session).getId())
|
||||
return Constants.mapper.writeValueAsBytes(Constants.mapper.createObjectNode()
|
||||
.put("error", "You are not the owner this playlist"));
|
||||
|
||||
if (index < 0 || index >= playlist.getVideos().size())
|
||||
return Constants.mapper.writeValueAsBytes(Constants.mapper.createObjectNode()
|
||||
.put("error", "Video Index out of bounds"));
|
||||
|
||||
playlist.getVideos().remove(index);
|
||||
|
||||
s.update(playlist);
|
||||
|
||||
if (!s.getTransaction().isActive())
|
||||
s.getTransaction().begin();
|
||||
s.getTransaction().commit();
|
||||
|
||||
return Constants.mapper.writeValueAsBytes(new AcceptedResponse());
|
||||
}
|
||||
}
|
||||
|
||||
public static String registeredBadgeRedirect() {
|
||||
try (Session s = DatabaseSessionFactory.createSession()) {
|
||||
long registered = (Long) s.createQuery("select count(*) from User").uniqueResult();
|
||||
|
|
102
src/main/java/me/kavin/piped/utils/obj/db/Playlist.java
Normal file
102
src/main/java/me/kavin/piped/utils/obj/db/Playlist.java
Normal file
|
@ -0,0 +1,102 @@
|
|||
package me.kavin.piped.utils.obj.db;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
@Table(name = "playlists", indexes = {@Index(columnList = "playlist_id", name = "playlists_playlist_id_idx")})
|
||||
public class Playlist {
|
||||
|
||||
public Playlist() {
|
||||
}
|
||||
|
||||
public Playlist(String name, User owner, String thumbnail) {
|
||||
this.name = name;
|
||||
this.owner = owner;
|
||||
this.videos = new ObjectArrayList<>();
|
||||
this.thumbnail = thumbnail;
|
||||
this.playlist_id = UUID.randomUUID();
|
||||
}
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private long id;
|
||||
|
||||
@Column(name = "playlist_id", unique = true, nullable = false)
|
||||
@GeneratedValue(generator = "UUID", strategy = GenerationType.IDENTITY)
|
||||
private UUID playlist_id;
|
||||
|
||||
@Column(name = "name", length = 100)
|
||||
private String name;
|
||||
|
||||
@Column(name = "short_description", length = 100)
|
||||
private String short_description;
|
||||
|
||||
@Column(name = "thumbnail", length = 300)
|
||||
private String thumbnail;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "owner")
|
||||
private User owner;
|
||||
|
||||
@ManyToMany
|
||||
@Column(name = "videos")
|
||||
@CollectionTable(name = "playlists_videos_ids")
|
||||
@OrderColumn(name = "videos_order")
|
||||
private List<PlaylistVideo> videos;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public UUID getPlaylistId() {
|
||||
return playlist_id;
|
||||
}
|
||||
|
||||
public void setPlaylistId(UUID playlist_id) {
|
||||
this.playlist_id = playlist_id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<PlaylistVideo> getVideos() {
|
||||
return videos;
|
||||
}
|
||||
|
||||
public void setVideos(List<PlaylistVideo> videos) {
|
||||
this.videos = videos;
|
||||
}
|
||||
|
||||
public String getShortDescription() {
|
||||
return short_description;
|
||||
}
|
||||
|
||||
public void setShortDescription(String short_description) {
|
||||
this.short_description = short_description;
|
||||
}
|
||||
|
||||
public String getThumbnail() {
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
public void setThumbnail(String thumbnail) {
|
||||
this.thumbnail = thumbnail;
|
||||
}
|
||||
|
||||
public User getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(User owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
}
|
77
src/main/java/me/kavin/piped/utils/obj/db/PlaylistVideo.java
Normal file
77
src/main/java/me/kavin/piped/utils/obj/db/PlaylistVideo.java
Normal file
|
@ -0,0 +1,77 @@
|
|||
package me.kavin.piped.utils.obj.db;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@Entity
|
||||
@Table(name = "playlist_videos", indexes = {@Index(columnList = "id", name = "playlist_videos_id_idx"),
|
||||
@Index(columnList = "uploader_id", name = "playlist_videos_uploader_id_idx")})
|
||||
public class PlaylistVideo {
|
||||
|
||||
public PlaylistVideo() {
|
||||
}
|
||||
|
||||
public PlaylistVideo(String id, String title, String thumbnail, long duration, Channel channel) {
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.thumbnail = thumbnail;
|
||||
this.duration = duration;
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
@Id
|
||||
@Column(name = "id", unique = true, length = 16)
|
||||
private String id;
|
||||
|
||||
@Column(name = "title", length = 120)
|
||||
private String title;
|
||||
|
||||
@Column(name = "duration")
|
||||
private long duration;
|
||||
|
||||
@Column(name = "thumbnail", length = 150)
|
||||
private String thumbnail;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "uploader_id")
|
||||
private Channel channel;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public long getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public void setDuration(long duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public String getThumbnail() {
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
public void setThumbnail(String thumbnail) {
|
||||
this.thumbnail = thumbnail;
|
||||
}
|
||||
|
||||
public Channel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public void setChannel(Channel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
}
|
|
@ -84,3 +84,26 @@ sleep 2
|
|||
|
||||
# Check Feed
|
||||
curl ${CURLOPTS[@]} $HOST/feed -G --data-urlencode "authToken=$AUTH_TOKEN" || exit 1
|
||||
|
||||
PLAYLIST_NAME=$(openssl rand -hex 6)
|
||||
|
||||
# Create a Playlist
|
||||
curl ${CURLOPTS[@]} $HOST/user/playlists/create -X POST -H "Content-Type: application/json" -H "Authorization: $AUTH_TOKEN" -d $(jq -n --compact-output --arg name "$PLAYLIST_NAME" '{"name": $name}') || exit 1
|
||||
|
||||
# See created playlists
|
||||
curl ${CURLOPTS[@]} $HOST/user/playlists -H "Authorization: $AUTH_TOKEN" || exit 1
|
||||
|
||||
# Get Playlist ID
|
||||
PLAYLIST_ID=$(curl -s -o - -f $HOST/user/playlists -H "Authorization: $AUTH_TOKEN" | jq -r ".[0].id") || exit 1
|
||||
|
||||
# Playlist Test
|
||||
curl ${CURLOPTS[@]} $HOST/playlists/$PLAYLIST_ID || exit 1
|
||||
|
||||
# Add to Playlist Test
|
||||
curl ${CURLOPTS[@]} $HOST/user/playlists/add -X POST -H "Content-Type: application/json" -H "Authorization: $AUTH_TOKEN" -d $(jq -n --compact-output --arg videoId "BtN-goy9VOY" --arg playlistId $PLAYLIST_ID '{"videoId": $videoId, "playlistId": $playlistId}') || exit 1
|
||||
|
||||
# Remove from Playlist Test
|
||||
curl ${CURLOPTS[@]} $HOST/user/playlists/remove -X POST -H "Content-Type: application/json" -H "Authorization: $AUTH_TOKEN" -d $(jq -n --compact-output --arg index "0" --arg playlistId $PLAYLIST_ID '{"index": $index, "playlistId": $playlistId}') || exit 1
|
||||
|
||||
# Delete Playlist Test
|
||||
curl ${CURLOPTS[@]} $HOST/user/playlists/delete -X POST -H "Content-Type: application/json" -H "Authorization: $AUTH_TOKEN" -d $(jq -n --compact-output --arg playlistId $PLAYLIST_ID '{"playlistId": $playlistId}') || exit 1
|
||||
|
|
Loading…
Reference in a new issue