Fix: do not sysout/syserr in TUI mode + some fixes
authorNiki Roo <niki@nikiroo.be>
Fri, 14 Jul 2017 16:36:15 +0000 (18:36 +0200)
committerNiki Roo <niki@nikiroo.be>
Fri, 14 Jul 2017 16:36:15 +0000 (18:36 +0200)
src/be/nikiroo/fanfix/Cache.java
src/be/nikiroo/fanfix/Instance.java
src/be/nikiroo/fanfix/bundles/Config.java
src/be/nikiroo/fanfix/bundles/config.properties
src/be/nikiroo/fanfix/reader/TuiReaderApplication.java
src/be/nikiroo/fanfix/supported/FimfictionApi.java

index 9983d78fa71a761dda58800e505f49798d384a05..383fa7c87a8cdd3f40b1041c9ac49e5d091e0189 100644 (file)
@@ -141,10 +141,8 @@ public class Cache {
                // MUST NOT return null
                try {
                        InputStream in = load(originalUrl, false, stable);
-                       if (Instance.isDebug()) {
-                               System.err.println("Cache " + (in != null ? "hit" : "miss")
-                                               + ": " + url);
-                       }
+                       Instance.trace("Cache " + (in != null ? "hit" : "miss") + ": "
+                                       + url);
 
                        if (in == null) {
 
@@ -226,7 +224,7 @@ public class Cache {
         * @param getParams
         *            the GET parameters (priority over POST)
         * @param oauth
-        *            OAuth authorization (aka, "bearer XXXXXXX")
+        *            OAuth authorisation (aka, "bearer XXXXXXX")
         * @return the {@link InputStream} of the opened page
         * 
         * @throws IOException
@@ -236,9 +234,7 @@ public class Cache {
                        final URL originalUrl, Map<String, String> postParams,
                        Map<String, String> getParams, String oauth) throws IOException {
 
-               if (Instance.isDebug()) {
-                       System.err.println("Open no cache: " + url);
-               }
+               Instance.trace("Open no cache: " + url);
 
                URLConnection conn = openConnectionWithCookies(url, support);
                if (support != null) {
index 9b6448ecb1cb89d490dfe6642d404069382a8868..4cf6e86113e46c620ae50ed87022ddc49e4f0eeb 100644 (file)
@@ -21,17 +21,57 @@ import be.nikiroo.utils.resources.Bundles;
  * @author niki
  */
 public class Instance {
+       /**
+        * A handler when a recoverable exception was caught by the program.
+        * 
+        * @author niki
+        */
+       public interface SyserrHandler {
+               /**
+                * An exception happened, log it.
+                * 
+                * @param e
+                *            the exception
+                * @param showDetails
+                *            show more details (usually equivalent to the value of
+                *            DEBUG)
+                */
+               public void notify(Exception e, boolean showDetails);
+       }
+
+       /**
+        * A handler when a trace message is sent.
+        * 
+        * @author niki
+        */
+       public interface TraceHandler {
+               /**
+                * A trace happened, show it.
+                * <p>
+                * Will only be called if TRACE is true.
+                * 
+                * @param message
+                *            the trace message
+                */
+               public void trace(String message);
+       }
+
        private static ConfigBundle config;
        private static UiConfigBundle uiconfig;
        private static StringIdBundle trans;
        private static Cache cache;
        private static LocalLibrary lib;
        private static boolean debug;
+       private static boolean trace;
        private static File coverDir;
        private static File readerTmp;
        private static File remoteDir;
        private static String configDir;
 
+       private static SyserrHandler syserrHandler;
+
+       private static TraceHandler traceHandler;
+
        static {
                // Most of the rest is dependent upon this:
                config = new ConfigBundle();
@@ -84,6 +124,7 @@ public class Instance {
                }
 
                debug = Instance.getConfig().getBoolean(Config.DEBUG_ERR, false);
+               trace = Instance.getConfig().getBoolean(Config.DEBUG_TRACE, false);
                coverDir = getFile(Config.DEFAULT_COVERS_DIR);
                File tmp = getFile(Config.CACHE_DIR);
                readerTmp = getFile(UiConfig.CACHE_DIR_LOCAL_READER);
@@ -248,6 +289,26 @@ public class Instance {
                }
        }
 
+       /**
+        * Replace the global syserr handler.
+        * 
+        * @param syserrHandler
+        *            the new syserr handler
+        */
+       public static void setSyserrHandler(SyserrHandler syserrHandler) {
+               Instance.syserrHandler = syserrHandler;
+       }
+
+       /**
+        * Replace the global trace handler.
+        * 
+        * @param traceHandler
+        *            the new trace handler
+        */
+       public static void setTraceHandler(TraceHandler traceHandler) {
+               Instance.traceHandler = traceHandler;
+       }
+
        /**
         * Report an error to the user
         * 
@@ -255,20 +316,31 @@ public class Instance {
         *            the {@link Exception} to report
         */
        public static void syserr(Exception e) {
-               if (debug) {
-                       e.printStackTrace();
+               if (syserrHandler != null) {
+                       syserrHandler.notify(e, debug);
                } else {
-                       System.err.println(e.getMessage());
+                       if (debug) {
+                               e.printStackTrace();
+                       } else {
+                               System.err.println(e.getMessage());
+                       }
                }
        }
 
        /**
-        * The program is in DEBUG mode (more verbose).
+        * Notify of a debug message.
         * 
-        * @return TRUE if it is
+        * @param message
+        *            the message
         */
-       public static boolean isDebug() {
-               return debug;
+       public static void trace(String message) {
+               if (trace) {
+                       if (traceHandler != null) {
+                               traceHandler.trace(message);
+                       } else {
+                               System.out.println(message);
+                       }
+               }
        }
 
        /**
index ae60b75b3b74eb6bb35f13e4d179bfb81fabd32a..bd27edffc31589abb8346dfa0d59b8428c2da587 100644 (file)
@@ -29,6 +29,8 @@ public enum Config {
        LIBRARY_DIR, //
        @Meta(description = "boolean", format = Format.BOOLEAN, info = "Show debug information on errors")
        DEBUG_ERR, //
+       @Meta(description = "boolean", format = Format.BOOLEAN, info = "Show debug trace information")
+       DEBUG_TRACE, //
        @Meta(description = "image format", format = Format.COMBO_LIST, list = {
                        "PNG", "JPG", "BMP" }, info = "Image format to use for cover images")
        IMAGE_FORMAT_COVER, //
@@ -59,7 +61,7 @@ public enum Config {
        LOGIN_FIMFICTION_APIKEY_CLIENT_ID, //
        @Meta(description = "An API key required to create a token from FimFiction", format = Format.PASSWORD)
        LOGIN_FIMFICTION_APIKEY_CLIENT_SECRET, //
-       @Meta(description = "Do not use the new API, even if we have a token, and force HTML scraping", format = Format.BOOLEAN)
+       @Meta(description = "Do not use the new API, even if we have a token, and force HTML scraping (default is false, use API if token or ID present)", format = Format.BOOLEAN)
        LOGIN_FIMFICTION_APIKEY_FORCE_HTML, //
        @Meta(description = "A token is required to use the beta APIv2 from FimFiction (see APIKEY_CLIENT_*)", format = Format.PASSWORD)
        LOGIN_FIMFICTION_APIKEY_TOKEN, //
index 937c4217353b21675a772aaacbb205df7f8fa786..6e59fe694f0300f187caf764eaa82711d5fe1c04 100644 (file)
@@ -17,7 +17,7 @@ CACHE_DIR =
 CACHE_MAX_TIME_CHANGING = 24
 # delay in hours, or 0 for no cache, or -1 for infinite time (default)
 # (FORMAT: INT) The delay after which a cached resource that is thought to change rarely is considered too old and triggers a refresh
-CACHE_MAX_TIME_STABLE = 
+CACHE_MAX_TIME_STABLE = 720
 # string (FORMAT: STRING) The user-agent to use to download files
 USER_AGENT = Mozilla/5.0 (X11; Linux x86_64; rv:44.0) Gecko/20100101 Firefox/44.0 -- ELinks/0.9.3 (Linux 2.6.11 i686; 80x24)
 # absolute path, $HOME variable supported, / is always accepted as dir separator
@@ -28,6 +28,8 @@ DEFAULT_COVERS_DIR = $HOME/bin/epub/
 LIBRARY_DIR = $HOME/Books
 # boolean (FORMAT: BOOLEAN) Show debug information on errors
 DEBUG_ERR = false
+# boolean (FORMAT: BOOLEAN) Show debug trace information
+DEBUG_TRACE = false
 # image format (FORMAT: COMBO_LIST) Image format to use for cover images
 # ALLOWED VALUES: "PNG" "JPG" "BMP"
 IMAGE_FORMAT_COVER = png
@@ -65,9 +67,15 @@ LOGIN_YIFFSTAR_PASS =
 # If the last update check was done at least that many days, check for updates at startup (-1 for 'no checks' -- default is 1 day)
 # (FORMAT: INT) 
 UPDATE_INTERVAL = 
-# An API key required to use the beta APIv2 from FimFiction
+# An API key required to create a token from FimFiction
+# (FORMAT: STRING) 
+LOGIN_FIMFICTION_APIKEY_CLIENT_ID = 
+# An API key required to create a token from FimFiction
 # (FORMAT: PASSWORD) 
-LOGIN_FIMFICTION_APIKEY = 
-# Do not use the new API, even if we have an API key, and force HTML scraping
+LOGIN_FIMFICTION_APIKEY_CLIENT_SECRET = 
+# Do not use the new API, even if we have a token, and force HTML scraping (default is false, use API if token or ID present)
 # (FORMAT: BOOLEAN) 
-LOGIN_FIMFICTION_FORCE_HTML = 
+LOGIN_FIMFICTION_APIKEY_FORCE_HTML = 
+# A token is required to use the beta APIv2 from FimFiction (see APIKEY_CLIENT_*)
+# (FORMAT: PASSWORD) 
+LOGIN_FIMFICTION_APIKEY_TOKEN = 
index f95cbf369f9518ae96cd311bbd131d8dec0c0e7f..3d6a949528630e4733f945eb19724977788c6859 100644 (file)
@@ -7,6 +7,9 @@ import java.util.List;
 import jexer.TApplication;
 import jexer.TMessageBox;
 import jexer.TWindow;
+import be.nikiroo.fanfix.Instance;
+import be.nikiroo.fanfix.Instance.SyserrHandler;
+import be.nikiroo.fanfix.Instance.TraceHandler;
 import be.nikiroo.fanfix.data.MetaData;
 import be.nikiroo.fanfix.data.Story;
 import be.nikiroo.fanfix.library.BasicLibrary;
@@ -121,6 +124,22 @@ class TuiReaderApplication extends TApplication implements Reader {
        private void init(Reader reader) {
                this.reader = reader;
 
+               // Do not allow traces/debug to pollute the screen:
+               Instance.setSyserrHandler(new SyserrHandler() {
+                       @Override
+                       public void notify(Exception e, boolean showDetails) {
+                               // TODO
+                       }
+               });
+
+               Instance.setTraceHandler(new TraceHandler() {
+                       @Override
+                       public void trace(String message) {
+                               // TODO
+                       }
+               });
+               //
+
                // Add the menus
                addFileMenu();
                addEditMenu();
index 59b593ec7aecedea5cb24c4f91b10f6819b172d6..b2d75df98b9c06437c21bf776843f32ad75b2675 100644 (file)
@@ -160,14 +160,7 @@ class FimfictionApi extends BasicSupport {
        @Override
        protected String getDesc(URL source, InputStream in) {
                String desc = getKeyJson(json, 0, "type", "story", "description");
-
-               // TODO: if the description becomes available in html, use it
-               desc = desc.replace("\\r\\n", "<br/>");
-               desc = desc.replace("[i]", "_").replace("[/i]", "_")
-                               .replace("[b]", "*").replace("[/b]", "*");
-               desc = desc.replaceAll("\\[[^\\]]*\\]", "");
-
-               return desc;
+               return unbbcode(desc);
        }
 
        @Override
@@ -228,6 +221,24 @@ class FimfictionApi extends BasicSupport {
                                || "www.fimfiction.net".equals(url.getHost());
        }
 
+       /**
+        * Generate a new token from the client ID and secret.
+        * <p>
+        * Note that those tokens are long-lived, and it would be badly seen to
+        * create a lot of them without due cause.
+        * <p>
+        * So, please cache and re-use them.
+        * 
+        * @param clientId
+        *            the client ID offered on FimFiction
+        * @param clientSecret
+        *            the client secret that goes with it
+        * 
+        * @return a new generated token linked to that client ID
+        * 
+        * @throws IOException
+        *             in case of I/O errors
+        */
        static private String generateOAuth(String clientId, String clientSecret)
                        throws IOException {
                URL url = new URL("https://www.fimfiction.net/api/v2/token");
@@ -241,18 +252,13 @@ class FimfictionApi extends BasicSupport {
                String jsonToken = IOUtils.readSmallStream(in);
 
                // Extract token type and token from: {
-               // token_type = "bearer",
+               // token_type = "Bearer",
                // access_token = "xxxxxxxxxxxxxx"
                // }
 
                String token = getKeyText(jsonToken, "\"access_token\"", "\"", "\"");
                String tokenType = getKeyText(jsonToken, "\"token_type\"", "\"", "\"");
 
-               // TODO: remove this once the bug is fixed on the server side
-               if ("bearer".equals(tokenType)) {
-                       tokenType = "Bearer";
-               }
-
                return tokenType + " " + token;
        }
 
@@ -319,4 +325,13 @@ class FimfictionApi extends BasicSupport {
 
                return pos;
        }
+
+       // quick & dirty filter
+       static private String unbbcode(String bbcode) {
+               String text = bbcode.replace("\\r\\n", "<br/>") //
+                               .replace("[i]", "_").replace("[/i]", "_") //
+                               .replace("[b]", "*").replace("[/b]", "*") //
+                               .replaceAll("\\[[^\\]]*\\]", "");
+               return text;
+       }
 }