Merge from master
[fanfix.git] / library / WebLibraryServer.java
index 97f2f0e8f69c6c07e217e1022ee4aa0fa96eaa4d..5cda3b5d712e6aa062ca87e9b16b4d157a40752f 100644 (file)
@@ -3,7 +3,9 @@ package be.nikiroo.fanfix.library;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.URL;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -25,6 +27,7 @@ import be.nikiroo.utils.LoginResult;
 import be.nikiroo.utils.NanoHTTPD;
 import be.nikiroo.utils.NanoHTTPD.Response;
 import be.nikiroo.utils.NanoHTTPD.Response.Status;
+import be.nikiroo.utils.Progress;
 
 public class WebLibraryServer extends WebLibraryServerHtml {
        class WLoginResult extends LoginResult {
@@ -72,6 +75,8 @@ public class WebLibraryServer extends WebLibraryServerHtml {
        private List<String> whitelist;
        private List<String> blacklist;
 
+       private Map<String, Progress> imprts = new HashMap<String, Progress>();
+
        public WebLibraryServer(boolean secure) throws IOException {
                super(secure);
 
@@ -182,17 +187,17 @@ public class WebLibraryServer extends WebLibraryServerHtml {
        // /story/luid/json <-- json, whole chapter (no images)
        @Override
        protected Response getStoryPart(String uri, WLoginResult login) {
-               String[] cover = uri.split("/");
+               String[] uriParts = uri.split("/");
                int off = 2;
 
-               if (cover.length < off + 2) {
+               if (uriParts.length < off + 2) {
                        return NanoHTTPD.newFixedLengthResponse(Status.BAD_REQUEST,
                                        NanoHTTPD.MIME_PLAINTEXT, null);
                }
 
-               String luid = cover[off + 0];
-               String chapterStr = cover[off + 1];
-               String imageStr = cover.length < off + 3 ? null : cover[off + 2];
+               String luid = uriParts[off + 0];
+               String chapterStr = uriParts[off + 1];
+               String imageStr = uriParts.length < off + 3 ? null : uriParts[off + 2];
 
                // 1-based (0 = desc)
                int chapter = 0;
@@ -228,7 +233,7 @@ public class WebLibraryServer extends WebLibraryServerHtml {
                InputStream in = null;
                try {
                        if ("cover".equals(chapterStr)) {
-                               Image img = cover(luid, login);
+                               Image img = storyCover(luid, login);
                                if (img != null) {
                                        in = img.newInputStream();
                                }
@@ -287,6 +292,169 @@ public class WebLibraryServer extends WebLibraryServerHtml {
                return newInputStreamResponse(mimeType, in);
        }
 
+       // /story/luid/source
+       // /story/luid/title
+       // /story/luid/author
+       @Override
+       protected Response setStoryPart(String uri, String value,
+                       WLoginResult login) throws IOException {
+               String[] uriParts = uri.split("/");
+               int off = 2; // "" and "story"
+
+               if (uriParts.length < off + 2) {
+                       return NanoHTTPD.newFixedLengthResponse(Status.BAD_REQUEST,
+                                       NanoHTTPD.MIME_PLAINTEXT, "Invalid story part request");
+               }
+
+               String luid = uriParts[off + 0];
+               String type = uriParts[off + 1];
+
+               if (!Arrays.asList("source", "title", "author").contains(type)) {
+                       return NanoHTTPD.newFixedLengthResponse(Status.BAD_REQUEST,
+                                       NanoHTTPD.MIME_PLAINTEXT,
+                                       "Invalid SET story part: " + type);
+               }
+
+               if (meta(luid, login) != null) {
+                       BasicLibrary lib = Instance.getInstance().getLibrary();
+                       if ("source".equals(type)) {
+                               lib.changeSource(luid, value, null);
+                       } else if ("title".equals(type)) {
+                               lib.changeTitle(luid, value, null);
+                       } else if ("author".equals(type)) {
+                               lib.changeAuthor(luid, value, null);
+                       }
+               }
+
+               return newInputStreamResponse(NanoHTTPD.MIME_PLAINTEXT, null);
+       }
+
+       @Override
+       protected Response getCover(String uri, WLoginResult login)
+                       throws IOException {
+               String[] uriParts = uri.split("/");
+               int off = 2; // "" and "cover"
+
+               if (uriParts.length < off + 2) {
+                       return NanoHTTPD.newFixedLengthResponse(Status.BAD_REQUEST,
+                                       NanoHTTPD.MIME_PLAINTEXT, "Invalid cover request");
+               }
+
+               String type = uriParts[off + 0];
+               String id = uriParts[off + 1];
+
+               InputStream in = null;
+
+               if ("story".equals(type)) {
+                       Image img = storyCover(id, login);
+                       if (img != null) {
+                               in = img.newInputStream();
+                       }
+               } else if ("source".equals(type)) {
+                       Image img = sourceCover(id, login);
+                       if (img != null) {
+                               in = img.newInputStream();
+                       }
+               } else if ("author".equals(type)) {
+                       Image img = authorCover(id, login);
+                       if (img != null) {
+                               in = img.newInputStream();
+                       }
+               } else {
+                       return NanoHTTPD.newFixedLengthResponse(Status.BAD_REQUEST,
+                                       NanoHTTPD.MIME_PLAINTEXT,
+                                       "Invalid GET cover type: " + type);
+               }
+
+               // TODO: get correct image type
+               return newInputStreamResponse("image/png", in);
+       }
+
+       @Override
+       protected Response setCover(String uri, String luid, WLoginResult login)
+                       throws IOException {
+               String[] uriParts = uri.split("/");
+               int off = 2; // "" and "cover"
+
+               if (uriParts.length < off + 2) {
+                       return NanoHTTPD.newFixedLengthResponse(Status.BAD_REQUEST,
+                                       NanoHTTPD.MIME_PLAINTEXT, "Invalid cover request");
+               }
+
+               String type = uriParts[off + 0];
+               String id = uriParts[off + 1];
+
+               if ("source".equals(type)) {
+                       sourceCover(id, login, luid);
+               } else if ("author".equals(type)) {
+                       authorCover(id, login, luid);
+               } else {
+                       return NanoHTTPD.newFixedLengthResponse(Status.BAD_REQUEST,
+                                       NanoHTTPD.MIME_PLAINTEXT,
+                                       "Invalid SET cover type: " + type);
+               }
+
+               return newInputStreamResponse(NanoHTTPD.MIME_PLAINTEXT, null);
+       }
+
+       @Override
+       protected Response imprt(String uri, String urlStr, WLoginResult login)
+                       throws IOException {
+               final BasicLibrary lib = Instance.getInstance().getLibrary();
+
+               final URL url = new URL(urlStr);
+               final Progress pg = new Progress();
+               final String luid = lib.getNextId();
+
+               synchronized (imprts) {
+                       imprts.put(luid, pg);
+               }
+
+               new Thread(new Runnable() {
+                       @Override
+                       public void run() {
+                               try {
+                                       lib.imprt(url, pg);
+                               } catch (IOException e) {
+                                       Instance.getInstance().getTraceHandler().error(e);
+                               } finally {
+                                       synchronized (imprts) {
+                                               imprts.remove(luid);
+                                       }
+                               }
+                       }
+               }, "Import story: " + urlStr).start();
+
+               lib.imprt(url, pg);
+
+               return NanoHTTPD.newFixedLengthResponse(Status.OK,
+                               NanoHTTPD.MIME_PLAINTEXT, luid);
+       }
+
+       @Override
+       protected Response imprtProgress(String uri, WLoginResult login) {
+               String[] uriParts = uri.split("/");
+               int off = 2; // "" and "import"
+
+               if (uriParts.length < off + 1) {
+                       return NanoHTTPD.newFixedLengthResponse(Status.BAD_REQUEST,
+                                       NanoHTTPD.MIME_PLAINTEXT, "Invalid cover request");
+               }
+
+               String luid = uriParts[off + 0];
+
+               Progress pg = null;
+               synchronized (imprts) {
+                       pg = imprts.get(luid);
+               }
+               if (pg != null) {
+                       return NanoHTTPD.newFixedLengthResponse(Status.OK,
+                                       "application/json", JsonIO.toJson(pg).toString());
+               }
+
+               return newInputStreamResponse(NanoHTTPD.MIME_PLAINTEXT, null);
+       }
+
        @Override
        protected List<MetaData> metas(WLoginResult login) throws IOException {
                BasicLibrary lib = Instance.getInstance().getLibrary();
@@ -348,7 +516,8 @@ public class WebLibraryServer extends WebLibraryServerHtml {
                return meta;
        }
 
-       private Image cover(String luid, WLoginResult login) throws IOException {
+       private Image storyCover(String luid, WLoginResult login)
+                       throws IOException {
                MetaData meta = meta(luid, login);
                if (meta != null) {
                        BasicLibrary lib = Instance.getInstance().getLibrary();
@@ -358,13 +527,74 @@ public class WebLibraryServer extends WebLibraryServerHtml {
                return null;
        }
 
+       private Image authorCover(String author, WLoginResult login)
+                       throws IOException {
+               Image img = null;
+
+               List<MetaData> metas = new MetaResultList(metas(login)).filter(null,
+                               author, null);
+               if (metas.size() > 0) {
+                       BasicLibrary lib = Instance.getInstance().getLibrary();
+                       img = lib.getCustomAuthorCover(author);
+                       if (img == null)
+                               img = lib.getCover(metas.get(0).getLuid());
+               }
+
+               return img;
+
+       }
+
+       private void authorCover(String author, WLoginResult login, String luid)
+                       throws IOException {
+               if (meta(luid, login) != null) {
+                       List<MetaData> metas = new MetaResultList(metas(login)).filter(null,
+                                       author, null);
+                       if (metas.size() > 0) {
+                               BasicLibrary lib = Instance.getInstance().getLibrary();
+                               lib.setAuthorCover(author, luid);
+                       }
+               }
+       }
+
+       private Image sourceCover(String source, WLoginResult login)
+                       throws IOException {
+               Image img = null;
+
+               List<MetaData> metas = new MetaResultList(metas(login)).filter(source,
+                               null, null);
+               if (metas.size() > 0) {
+                       BasicLibrary lib = Instance.getInstance().getLibrary();
+                       img = lib.getCustomSourceCover(source);
+                       if (img == null)
+                               img = lib.getCover(metas.get(0).getLuid());
+               }
+
+               return img;
+       }
+
+       private void sourceCover(String source, WLoginResult login, String luid)
+                       throws IOException {
+               if (meta(luid, login) != null) {
+                       List<MetaData> metas = new MetaResultList(metas(login))
+                                       .filter(source, null, null);
+                       if (metas.size() > 0) {
+                               BasicLibrary lib = Instance.getInstance().getLibrary();
+                               lib.setSourceCover(source, luid);
+                       }
+               }
+       }
+
        private boolean isAllowed(MetaData meta, WLoginResult login) {
-               if (login.isWl() && !whitelist.isEmpty()
-                               && !whitelist.contains(meta.getSource())) {
-                       return false;
+               MetaResultList one = new MetaResultList(Arrays.asList(meta));
+               if (login.isWl() && !whitelist.isEmpty()) {
+                       if (one.filter(whitelist, null, null).isEmpty()) {
+                               return false;
+                       }
                }
-               if (login.isBl() && blacklist.contains(meta.getSource())) {
-                       return false;
+               if (login.isBl() && !blacklist.isEmpty()) {
+                       if (!one.filter(blacklist, null, null).isEmpty()) {
+                               return false;
+                       }
                }
 
                return true;