Add endpoint to update metadata
This commit is contained in:
parent
d826999380
commit
ae1d9e2bc1
@ -4,7 +4,9 @@ import java.nio.file.Path;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import me.mrletsplay.simplehttpserver.http.server.HttpServer;
|
import me.mrletsplay.simplehttpserver.http.server.HttpServer;
|
||||||
import me.mrletsplay.videobase.library.Library;
|
import me.mrletsplay.videobase.library.Library;
|
||||||
@ -13,7 +15,7 @@ import me.mrletsplay.videobase.util.Hash;
|
|||||||
|
|
||||||
public class VideoBase {
|
public class VideoBase {
|
||||||
|
|
||||||
public static final Logger LOGGER = Logger.getLogger(VideoBase.class.getName());
|
public static final Logger LOGGER = LoggerFactory.getLogger(VideoBase.class.getName());
|
||||||
|
|
||||||
private static ScheduledExecutorService executor;
|
private static ScheduledExecutorService executor;
|
||||||
private static Library library;
|
private static Library library;
|
||||||
@ -32,6 +34,7 @@ public class VideoBase {
|
|||||||
.port(6969)
|
.port(6969)
|
||||||
.poolSize(20)
|
.poolSize(20)
|
||||||
.ioWorkers(3)
|
.ioWorkers(3)
|
||||||
|
// .logger(NOPLogger.NOP_LOGGER)
|
||||||
.create());
|
.create());
|
||||||
|
|
||||||
new LibraryAPI().register(server.getDocumentProvider());
|
new LibraryAPI().register(server.getDocumentProvider());
|
||||||
|
@ -8,7 +8,6 @@ import java.util.Comparator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import me.mrletsplay.mrcore.json.JSONObject;
|
import me.mrletsplay.mrcore.json.JSONObject;
|
||||||
@ -76,6 +75,19 @@ public class Library {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateMetadata(Video video, VideoMetadata metadata) {
|
||||||
|
VideoMetadata oldMetadata = video.getMetadata();
|
||||||
|
video.setMetadata(VideoMetadata.inherit(oldMetadata, metadata));
|
||||||
|
// TODO: save metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean updateMetadata(String videoId, VideoMetadata metadata) {
|
||||||
|
Video video = findVideoById(videoId);
|
||||||
|
if(video == null) return false;
|
||||||
|
updateMetadata(video, metadata);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public static Library load(Path path) {
|
public static Library load(Path path) {
|
||||||
List<Video> videos = new ArrayList<>();
|
List<Video> videos = new ArrayList<>();
|
||||||
load(path, path, videos, VideoMetadata.DEFAULT_METADATA);
|
load(path, path, videos, VideoMetadata.DEFAULT_METADATA);
|
||||||
@ -95,7 +107,7 @@ public class Library {
|
|||||||
libraryMeta = JSONConverter.decodeObject(obj, LibraryMetadata.class);
|
libraryMeta = JSONConverter.decodeObject(obj, LibraryMetadata.class);
|
||||||
defaultMetadata = VideoMetadata.inherit(defaultMetadata, libraryMeta.getDefault());
|
defaultMetadata = VideoMetadata.inherit(defaultMetadata, libraryMeta.getDefault());
|
||||||
}catch(IOException | JSONParseException | ClassCastException e) {
|
}catch(IOException | JSONParseException | ClassCastException e) {
|
||||||
VideoBase.LOGGER.log(Level.WARNING, "Failed to parse metadata at " + path, e);
|
VideoBase.LOGGER.warn("Failed to parse metadata at " + path, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +144,7 @@ public class Library {
|
|||||||
JSONObject obj = new JSONObject(Files.readString(videoMetaPath));
|
JSONObject obj = new JSONObject(Files.readString(videoMetaPath));
|
||||||
videoMeta = VideoMetadata.inherit(videoMeta, JSONConverter.decodeObject(obj, VideoMetadata.class));
|
videoMeta = VideoMetadata.inherit(videoMeta, JSONConverter.decodeObject(obj, VideoMetadata.class));
|
||||||
}catch(IOException | JSONParseException | ClassCastException e) {
|
}catch(IOException | JSONParseException | ClassCastException e) {
|
||||||
VideoBase.LOGGER.log(Level.WARNING, "Failed to parse metadata at " + path, e);
|
VideoBase.LOGGER.warn("Failed to parse metadata at " + path, e);
|
||||||
}
|
}
|
||||||
}else if(libraryMeta != null && libraryMeta.getOverrides().containsKey(fileName)) {
|
}else if(libraryMeta != null && libraryMeta.getOverrides().containsKey(fileName)) {
|
||||||
videoMeta = VideoMetadata.inherit(videoMeta, libraryMeta.getOverrides().get(fileName));
|
videoMeta = VideoMetadata.inherit(videoMeta, libraryMeta.getOverrides().get(fileName));
|
||||||
@ -142,7 +154,7 @@ public class Library {
|
|||||||
videos.add(new Video(subPath, id, videoMeta == null ? VideoMetadata.DEFAULT_METADATA : videoMeta));
|
videos.add(new Video(subPath, id, videoMeta == null ? VideoMetadata.DEFAULT_METADATA : videoMeta));
|
||||||
}
|
}
|
||||||
}catch(IOException e) {
|
}catch(IOException e) {
|
||||||
VideoBase.LOGGER.log(Level.WARNING, "Failed to load folder at " + path, e);
|
VideoBase.LOGGER.warn("Failed to load folder at " + path, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,10 @@ public class Video {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMetadata(VideoMetadata metadata) {
|
||||||
|
this.metadata = metadata;
|
||||||
|
}
|
||||||
|
|
||||||
public VideoMetadata getMetadata() {
|
public VideoMetadata getMetadata() {
|
||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,10 @@ import java.util.Map;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import me.mrletsplay.mrcore.json.JSONObject;
|
import me.mrletsplay.mrcore.json.JSONObject;
|
||||||
|
import me.mrletsplay.mrcore.json.JSONType;
|
||||||
import me.mrletsplay.mrcore.json.converter.JSONConstructor;
|
import me.mrletsplay.mrcore.json.converter.JSONConstructor;
|
||||||
import me.mrletsplay.mrcore.json.converter.JSONConvertible;
|
import me.mrletsplay.mrcore.json.converter.JSONConvertible;
|
||||||
|
import me.mrletsplay.simplehttpserver.http.validation.JsonObjectValidator;
|
||||||
|
|
||||||
public class VideoMetadata implements JSONConvertible {
|
public class VideoMetadata implements JSONConvertible {
|
||||||
|
|
||||||
@ -30,6 +32,12 @@ public class VideoMetadata implements JSONConvertible {
|
|||||||
FIELD_INDEX, DEFAULT_INDEX
|
FIELD_INDEX, DEFAULT_INDEX
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
public static final JsonObjectValidator VALIDATOR = new JsonObjectValidator()
|
||||||
|
.optional(FIELD_SERIES, JSONType.STRING)
|
||||||
|
.optional(FIELD_TITLE, JSONType.STRING)
|
||||||
|
.optional(FIELD_AUTHOR, JSONType.STRING)
|
||||||
|
.optional(FIELD_INDEX, JSONType.INTEGER);
|
||||||
|
|
||||||
private JSONObject metadata;
|
private JSONObject metadata;
|
||||||
|
|
||||||
@JSONConstructor
|
@JSONConstructor
|
||||||
@ -56,6 +64,10 @@ public class VideoMetadata implements JSONConvertible {
|
|||||||
return metadata.optInt(FIELD_INDEX).orElse(null);
|
return metadata.optInt(FIELD_INDEX).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JSONObject getRaw() {
|
||||||
|
return new JSONObject(metadata);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preDeserialize(JSONObject object) {
|
public void preDeserialize(JSONObject object) {
|
||||||
this.metadata = object;
|
this.metadata = object;
|
||||||
@ -79,7 +91,16 @@ public class VideoMetadata implements JSONConvertible {
|
|||||||
|
|
||||||
JSONObject meta = new JSONObject(parent == null ? null : parent.metadata);
|
JSONObject meta = new JSONObject(parent == null ? null : parent.metadata);
|
||||||
for(String key : child.metadata.keys()) {
|
for(String key : child.metadata.keys()) {
|
||||||
meta.set(key, child.metadata.get(key));
|
Object value = child.metadata.get(key);
|
||||||
|
if(value == null) { // Setting to null resets to default value if available, otherwise removes attribute
|
||||||
|
value = DEFAULT_METADATA.metadata.opt(key).orElse(null);
|
||||||
|
if(value == null) {
|
||||||
|
meta.remove(key);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
meta.set(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new VideoMetadata(meta);
|
return new VideoMetadata(meta);
|
||||||
|
@ -4,18 +4,20 @@ import java.util.List;
|
|||||||
|
|
||||||
import me.mrletsplay.mrcore.json.JSONArray;
|
import me.mrletsplay.mrcore.json.JSONArray;
|
||||||
import me.mrletsplay.mrcore.json.JSONObject;
|
import me.mrletsplay.mrcore.json.JSONObject;
|
||||||
import me.mrletsplay.mrcore.json.converter.SerializationOption;
|
|
||||||
import me.mrletsplay.simplehttpserver.http.HttpRequestMethod;
|
import me.mrletsplay.simplehttpserver.http.HttpRequestMethod;
|
||||||
import me.mrletsplay.simplehttpserver.http.HttpStatusCodes;
|
import me.mrletsplay.simplehttpserver.http.HttpStatusCodes;
|
||||||
import me.mrletsplay.simplehttpserver.http.endpoint.Endpoint;
|
import me.mrletsplay.simplehttpserver.http.endpoint.Endpoint;
|
||||||
import me.mrletsplay.simplehttpserver.http.endpoint.EndpointCollection;
|
import me.mrletsplay.simplehttpserver.http.endpoint.EndpointCollection;
|
||||||
import me.mrletsplay.simplehttpserver.http.endpoint.RequestParameter;
|
import me.mrletsplay.simplehttpserver.http.endpoint.RequestParameter;
|
||||||
|
import me.mrletsplay.simplehttpserver.http.header.DefaultClientContentTypes;
|
||||||
import me.mrletsplay.simplehttpserver.http.request.HttpRequestContext;
|
import me.mrletsplay.simplehttpserver.http.request.HttpRequestContext;
|
||||||
import me.mrletsplay.simplehttpserver.http.response.JsonResponse;
|
import me.mrletsplay.simplehttpserver.http.response.JsonResponse;
|
||||||
import me.mrletsplay.simplehttpserver.http.response.TextResponse;
|
import me.mrletsplay.simplehttpserver.http.response.TextResponse;
|
||||||
|
import me.mrletsplay.simplehttpserver.http.validation.result.ValidationResult;
|
||||||
import me.mrletsplay.videobase.VideoBase;
|
import me.mrletsplay.videobase.VideoBase;
|
||||||
import me.mrletsplay.videobase.library.Library;
|
import me.mrletsplay.videobase.library.Library;
|
||||||
import me.mrletsplay.videobase.library.Video;
|
import me.mrletsplay.videobase.library.Video;
|
||||||
|
import me.mrletsplay.videobase.library.VideoMetadata;
|
||||||
|
|
||||||
public class LibraryAPI implements EndpointCollection {
|
public class LibraryAPI implements EndpointCollection {
|
||||||
|
|
||||||
@ -89,10 +91,35 @@ public class LibraryAPI implements EndpointCollection {
|
|||||||
ctx.respond(HttpStatusCodes.OK_200, new JsonResponse(videoToJSON(video)));
|
ctx.respond(HttpStatusCodes.OK_200, new JsonResponse(videoToJSON(video)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Endpoint(method = HttpRequestMethod.PUT, path = "/video/{video}/metadata", pathPattern = true)
|
||||||
|
public void updateVideoMetadata(HttpRequestContext ctx, @RequestParameter("video") String videoId) {
|
||||||
|
Library library = VideoBase.getLibrary();
|
||||||
|
Video video = VideoBase.getLibrary().findVideoById(videoId);
|
||||||
|
if(video == null) {
|
||||||
|
ctx.respond(HttpStatusCodes.NOT_FOUND_404, new TextResponse("Not found"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject metadata = ctx.expectContent(DefaultClientContentTypes.JSON_OBJECT);
|
||||||
|
if(metadata == null) {
|
||||||
|
ctx.respond(HttpStatusCodes.BAD_REQUEST_400, ValidationResult.error("_", "Invalid content").asJsonResponse());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValidationResult result = VideoMetadata.VALIDATOR.validate(metadata);
|
||||||
|
if(!result.isOk()) {
|
||||||
|
ctx.respond(HttpStatusCodes.BAD_REQUEST_400, result.asJsonResponse());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
library.updateMetadata(video, new VideoMetadata(metadata));
|
||||||
|
ctx.respond(HttpStatusCodes.OK_200, new JsonResponse(video.getMetadata().getRaw()));
|
||||||
|
}
|
||||||
|
|
||||||
private JSONObject videoToJSON(Video video) {
|
private JSONObject videoToJSON(Video video) {
|
||||||
JSONObject v = new JSONObject();
|
JSONObject v = new JSONObject();
|
||||||
v.put("id", video.getId());
|
v.put("id", video.getId());
|
||||||
v.put("metadata", video.getMetadata().toJSON(SerializationOption.DONT_INCLUDE_CLASS));
|
v.put("metadata", video.getMetadata().getRaw());
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user