From 3989dfc5ced262e3c8d07fc796ec06ce5513c6b8 Mon Sep 17 00:00:00 2001 From: Niki Roo Date: Wed, 20 Mar 2019 18:13:00 +0100 Subject: [PATCH] cover: allow custom author covers --- .../nikiroo/fanfix/library/BasicLibrary.java | 51 +++++++++++- .../nikiroo/fanfix/library/CacheLibrary.java | 35 ++++++++ .../nikiroo/fanfix/library/LocalLibrary.java | 81 ++++++++++++++++++- .../nikiroo/fanfix/library/RemoteLibrary.java | 27 ++++++- .../fanfix/library/RemoteLibraryServer.java | 30 +++++-- 5 files changed, 209 insertions(+), 15 deletions(-) diff --git a/src/be/nikiroo/fanfix/library/BasicLibrary.java b/src/be/nikiroo/fanfix/library/BasicLibrary.java index 8ec4e56..78d20d6 100644 --- a/src/be/nikiroo/fanfix/library/BasicLibrary.java +++ b/src/be/nikiroo/fanfix/library/BasicLibrary.java @@ -119,6 +119,31 @@ abstract public class BasicLibrary { return null; } + /** + * Return the cover image associated to this author. + *

+ * By default, return the custom cover if any, and if not, return the cover + * of the first story with this author. + * + * @param author + * the author + * + * @return the cover image or NULL + */ + public Image getAuthorCover(String author) { + Image custom = getCustomAuthorCover(author); + if (custom != null) { + return custom; + } + + List metas = getListByAuthor(author); + if (metas.size() > 0) { + return getCover(metas.get(0).getLuid()); + } + + return null; + } + /** * Return the custom cover image associated to this source. *

@@ -134,7 +159,21 @@ abstract public class BasicLibrary { } /** - * Fix the source cover to the given story cover. + * Return the custom cover image associated to this author. + *

+ * By default, return NULL. + * + * @param author + * the author to look for + * + * @return the custom cover or NULL if none + */ + public Image getCustomAuthorCover(@SuppressWarnings("unused") String author) { + return null; + } + + /** + * Set the source cover to the given story cover. * * @param source * the source to change @@ -143,6 +182,16 @@ abstract public class BasicLibrary { */ public abstract void setSourceCover(String source, String luid); + /** + * Set the author cover to the given story cover. + * + * @param source + * the author to change + * @param luid + * the story LUID + */ + public abstract void setAuthorCover(String author, String luid); + /** * Return the list of stories (represented by their {@link MetaData}, which * MAY not have the cover included). diff --git a/src/be/nikiroo/fanfix/library/CacheLibrary.java b/src/be/nikiroo/fanfix/library/CacheLibrary.java index 918b763..0f28318 100644 --- a/src/be/nikiroo/fanfix/library/CacheLibrary.java +++ b/src/be/nikiroo/fanfix/library/CacheLibrary.java @@ -125,6 +125,22 @@ public class CacheLibrary extends BasicLibrary { return lib.getSourceCover(source); } + @Override + public Image getAuthorCover(String author) { + Image custom = getCustomSourceCover(author); + if (custom != null) { + return custom; + } + + Image cached = cacheLib.getSourceCover(author); + if (cached != null) { + return cached; + } + + return lib.getSourceCover(author); + + } + @Override public Image getCustomSourceCover(String source) { Image custom = cacheLib.getCustomSourceCover(source); @@ -137,6 +153,19 @@ public class CacheLibrary extends BasicLibrary { return custom; } + + @Override + public Image getCustomAuthorCover(String author) { + Image custom = cacheLib.getCustomAuthorCover(author); + if (custom == null) { + custom = lib.getCustomAuthorCover(author); + if (custom != null) { + cacheLib.setAuthorCover(author, custom); + } + } + + return custom; + } @Override public void setSourceCover(String source, String luid) { @@ -144,6 +173,12 @@ public class CacheLibrary extends BasicLibrary { cacheLib.setSourceCover(source, getCover(luid)); } + @Override + public void setAuthorCover(String author, String luid) { + lib.setAuthorCover(author, luid); + cacheLib.setAuthorCover(author, getCover(luid)); + } + @Override protected void updateInfo(MetaData meta) { if (meta != null && metas != null) { diff --git a/src/be/nikiroo/fanfix/library/LocalLibrary.java b/src/be/nikiroo/fanfix/library/LocalLibrary.java index e9c67f3..1752dc7 100644 --- a/src/be/nikiroo/fanfix/library/LocalLibrary.java +++ b/src/be/nikiroo/fanfix/library/LocalLibrary.java @@ -22,6 +22,7 @@ import be.nikiroo.fanfix.supported.InfoReader; import be.nikiroo.utils.IOUtils; import be.nikiroo.utils.Image; import be.nikiroo.utils.Progress; +import be.nikiroo.utils.StringUtils; /** * This {@link BasicLibrary} will store the stories locally on disk. @@ -32,6 +33,7 @@ public class LocalLibrary extends BasicLibrary { private int lastId; private Map stories; // Files: [ infoFile, TargetFile ] private Map sourceCovers; + private Map authorCovers; private File baseDir; private OutputType text; @@ -251,13 +253,43 @@ public class LocalLibrary extends BasicLibrary { return sourceCovers.get(source); } + @Override + public synchronized Image getCustomAuthorCover(String author) { + File cover = getAuthorCoverFile(author); + if (cover.exists()) { + InputStream in; + try { + in = new FileInputStream(cover); + try { + authorCovers.put(author, new Image(in)); + } finally { + in.close(); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + Instance.getTraceHandler().error( + new IOException( + "Cannot load the existing custom author cover: " + + cover, e)); + } + } + + return authorCovers.get(author); + } + @Override public void setSourceCover(String source, String luid) { setSourceCover(source, getCover(luid)); } + @Override + public void setAuthorCover(String author, String luid) { + setAuthorCover(author, getCover(luid)); + } + /** - * Fix the source cover to the given story cover. + * Set the source cover to the given story cover. * * @param source * the source to change @@ -278,6 +310,27 @@ public class LocalLibrary extends BasicLibrary { } } + /** + * Set the author cover to the given story cover. + * + * @param author + * the author to change + * @param coverImage + * the cover image + */ + synchronized void setAuthorCover(String author, Image coverImage) { + File cover = getAuthorCoverFile(author); + cover.getParentFile().mkdirs(); + try { + Instance.getCache().saveAsImage(coverImage, cover, true); + if (authorCovers != null) { + authorCovers.put(author, coverImage); + } + } catch (IOException e) { + Instance.getTraceHandler().error(e); + } + } + @Override public void imprt(BasicLibrary other, String luid, Progress pg) throws IOException { @@ -387,6 +440,9 @@ public class LocalLibrary extends BasicLibrary { title = ""; } title = title.replaceAll("[^a-zA-Z0-9._+-]", "_"); + if (title.length() > 40) { + title = title.substring(0, 40); + } return new File(getExpectedDir(key.getSource()), key.getLuid() + "_" + title); } @@ -403,7 +459,8 @@ public class LocalLibrary extends BasicLibrary { private File getExpectedDir(String source) { String sanitizedSource = source.replaceAll("[^a-zA-Z0-9._+/-]", "_"); - while (sanitizedSource.startsWith("/")) { + while (sanitizedSource.startsWith("/") + || sanitizedSource.startsWith("_")) { if (sanitizedSource.length() > 1) { sanitizedSource = sanitizedSource.substring(1); } else { @@ -414,12 +471,30 @@ public class LocalLibrary extends BasicLibrary { sanitizedSource = sanitizedSource.replace("/", File.separator); if (sanitizedSource.isEmpty()) { - sanitizedSource = "EMPTY"; + sanitizedSource = "_EMPTY"; } return new File(baseDir, sanitizedSource); } + /** + * Return the full path to the file to use for the custom cover of this + * author. + *

+ * One or more of the parent directories MAY not exist. + * + * @param author + * the author + * + * @return the custom cover file + */ + private File getAuthorCoverFile(String author) { + File aDir = new File(baseDir, "_AUTHORS"); + String hash = StringUtils.getMd5Hash(author); + String ext = Instance.getConfig().getString(Config.IMAGE_FORMAT_COVER); + return new File(aDir, hash + "." + ext.toLowerCase()); + } + /** * Return the list of files/directories on disk for this {@link Story}. *

diff --git a/src/be/nikiroo/fanfix/library/RemoteLibrary.java b/src/be/nikiroo/fanfix/library/RemoteLibrary.java index c01275b..8442aed 100644 --- a/src/be/nikiroo/fanfix/library/RemoteLibrary.java +++ b/src/be/nikiroo/fanfix/library/RemoteLibrary.java @@ -120,14 +120,24 @@ public class RemoteLibrary extends BasicLibrary { @Override public Image getCustomSourceCover(final String source) { + return getCustomCover(source, "SOURCE"); + } + + @Override + public Image getCustomAuthorCover(final String author) { + return getCustomCover(author, "AUTHOR"); + } + + // type: "SOURCE" or "AUTHOR" + private Image getCustomCover(final String source, final String type) { final Image[] result = new Image[1]; try { new ConnectActionClientObject(host, port, true) { @Override public void action(Version serverVersion) throws Exception { - Object rep = send(new Object[] { md5, - "GET_CUSTOM_SOURCE_COVER", source }); + Object rep = send(new Object[] { md5, "GET_CUSTOM_COVER", + type, source }); result[0] = (Image) rep; } @@ -265,11 +275,22 @@ public class RemoteLibrary extends BasicLibrary { @Override public void setSourceCover(final String source, final String luid) { + setCover(source, luid, "SOURCE"); + } + + @Override + public void setAuthorCover(final String author, final String luid) { + setCover(author, luid, "AUTHOR"); + } + + // type = "SOURCE" | "AUTHOR" + private void setCover(final String value, final String luid, + final String type) { try { new ConnectActionClientObject(host, port, true) { @Override public void action(Version serverVersion) throws Exception { - send(new Object[] { md5, "SET_SOURCE_COVER", source, luid }); + send(new Object[] { md5, "SET_COVER", type, value, luid }); } @Override diff --git a/src/be/nikiroo/fanfix/library/RemoteLibraryServer.java b/src/be/nikiroo/fanfix/library/RemoteLibraryServer.java index aa5f305..d739438 100644 --- a/src/be/nikiroo/fanfix/library/RemoteLibraryServer.java +++ b/src/be/nikiroo/fanfix/library/RemoteLibraryServer.java @@ -41,9 +41,10 @@ import be.nikiroo.utils.serial.server.ServerObject; * the LUID *

  • [md5] DELETE_STORY [luid]: delete the story of LUID luid
  • *
  • [md5] GET_COVER [luid]: return the cover of the story
  • - *
  • [md5] GET_CUSTOM_SOURCE_COVER [source]: return the cover for this source
  • - *
  • [md5] SET_SOURCE_COVER [source], [luid]: set the default cover for the - * given source to the cover of the story denoted by luid
  • + *
  • [md5] GET_CUSTOM_COVER ["SOURCE"|"AUTHOR"] [source]: return the cover for + * this source/author
  • + *
  • [md5] SET_COVER ["SOURCE"|"AUTHOR"] [value] [luid]: set the default cover + * for the given source/author to the cover of the story denoted by luid
  • *
  • [md5] CHANGE_SOURCE [luid] [new source]: change the source of the story * of LUID luid
  • *
  • [md5] EXIT: stop the server
  • @@ -180,11 +181,24 @@ public class RemoteLibraryServer extends ServerObject { Instance.getLibrary().delete((String) args[0]); } else if ("GET_COVER".equals(command)) { return Instance.getLibrary().getCover((String) args[0]); - } else if ("GET_CUSTOM_SOURCE_COVER".equals(command)) { - return Instance.getLibrary().getCustomSourceCover((String) args[0]); - } else if ("SET_SOURCE_COVER".equals(command)) { - Instance.getLibrary().setSourceCover((String) args[0], - (String) args[1]); + } else if ("GET_CUSTOM_COVER".equals(command)) { + if ("SOURCE".equals(args[0])) { + return Instance.getLibrary().getCustomSourceCover( + (String) args[1]); + } else if ("AUTHOR".equals(args[0])) { + return Instance.getLibrary().getCustomAuthorCover( + (String) args[1]); + } else { + return null; + } + } else if ("SET_COVER".equals(command)) { + if ("SOURCE".equals(args[0])) { + Instance.getLibrary().setSourceCover((String) args[1], + (String) args[2]); + } else if ("AUTHOR".equals(args[0])) { + Instance.getLibrary().setAuthorCover((String) args[1], + (String) args[2]); + } } else if ("CHANGE_STA".equals(command)) { Progress pg = createPgForwarder(action); Instance.getLibrary().changeSTA((String) args[0], (String) args[1], -- 2.27.0