do not allow empty cover images
[fanfix.git] / src / be / nikiroo / fanfix / searchable / Fanfiction.java
index 362b5433d7d3fc81e163a03a08273e9f2319f03f..cbc927bcc2d981b028311be59fa2d1ba7c152542 100644 (file)
@@ -20,6 +20,7 @@ import be.nikiroo.fanfix.bundles.StringId;
 import be.nikiroo.fanfix.data.MetaData;
 import be.nikiroo.fanfix.supported.SupportType;
 import be.nikiroo.utils.Image;
+import be.nikiroo.utils.StringUtils;
 
 /**
  * A {@link BasicSearchable} for Fanfiction.NET.
@@ -76,7 +77,7 @@ class Fanfiction extends BasicSearchable {
                if (storiesName != null) {
                        SearchableTag tag = new SearchableTag(null, storiesName, false);
                        for (String id : stories.keySet()) {
-                               tag.add(new SearchableTag(id, stories.get(id), true, false));
+                               tag.add(new SearchableTag(id, stories.get(id), false, false));
                        }
                        tags.add(tag);
                }
@@ -93,7 +94,7 @@ class Fanfiction extends BasicSearchable {
        }
 
        @Override
-       protected void fillTag(SearchableTag tag) throws IOException {
+       public void fillTag(SearchableTag tag) throws IOException {
                if (tag.getId() == null || tag.isComplete()) {
                        return;
                }
@@ -126,23 +127,10 @@ class Fanfiction extends BasicSearchable {
                                                        }
                                                        nr = nr.trim();
 
-                                                       long count = 0;
-                                                       try {
-                                                               if (nr.toLowerCase().endsWith("m")) {
-                                                                       count = Long.parseLong(nr.substring(0,
-                                                                                       nr.length() - 1).trim());
-                                                                       count *= 1000000;
-                                                               } else if (nr.toLowerCase().endsWith("k")) {
-                                                                       count = Long.parseLong(nr.substring(0,
-                                                                                       nr.length() - 1).trim());
-                                                                       count *= 1000;
-                                                               } else {
-                                                                       count = Long.parseLong(nr);
-                                                               }
-                                                       } catch (NumberFormatException pe) {
-                                                       }
+                                                       // TODO: fix toNumber/fromNumber
+                                                       nr = nr.replaceAll("\\.[0-9]*", "");
 
-                                                       subtag.setCount(count);
+                                                       subtag.setCount(StringUtils.toNumber(nr));
                                                }
                                        }
                                }
@@ -153,11 +141,12 @@ class Fanfiction extends BasicSearchable {
        }
 
        @Override
-       public List<MetaData> search(String search) throws IOException {
+       public List<MetaData> search(String search, int page) throws IOException {
                String encoded = URLEncoder.encode(search.toLowerCase(), "utf-8");
-               return getStories(
-                               "http://fanfiction.net/search/?ready=1&type=story&keywords="
-                                               + encoded, null, null);
+               String url = BASE_URL + "search/?ready=1&type=story&keywords="
+                               + encoded + "&ppage=" + page;
+
+               return getStories(url, null, null);
        }
 
        @Override
@@ -180,7 +169,7 @@ class Fanfiction extends BasicSearchable {
                        Document doc = load(url, false);
 
                        // Update the pages number if needed
-                       if (tag.getPages() < 0) {
+                       if (tag.getPages() < 0 && tag.isLeaf()) {
                                tag.setPages(getPages(doc));
                        }
 
@@ -199,6 +188,25 @@ class Fanfiction extends BasicSearchable {
                return metas;
        }
 
+       @Override
+       public int searchPages(String search) throws IOException {
+               String encoded = URLEncoder.encode(search.toLowerCase(), "utf-8");
+               String url = BASE_URL + "search/?ready=1&type=story&keywords="
+                               + encoded;
+
+               return getPages(load(url, false));
+       }
+
+       @Override
+       public int searchPages(SearchableTag tag) throws IOException {
+               if (tag.isLeaf()) {
+                       String url = tag.getId();
+                       return getPages(load(url, false));
+               }
+
+               return 0;
+       }
+
        /**
         * Return the number of pages in this stories result listing.
         * 
@@ -206,11 +214,8 @@ class Fanfiction extends BasicSearchable {
         *            the document
         * 
         * @return the number of pages or -1 if unknown
-        * 
-        * @throws IOException
-        *             in case of I/O errors
         */
-       private int getPages(Document doc) throws IOException {
+       private int getPages(Document doc) {
                int pages = -1;
 
                if (doc != null) {
@@ -265,43 +270,50 @@ class Fanfiction extends BasicSearchable {
                        MetaData meta = new MetaData();
                        meta.setImageDocument(false);
                        meta.setSource(getType().getSourceName());
+                       meta.setPublisher(getType().getSourceName());
+                       meta.setType(getType().toString());
 
-                       String subject = mainSubject == null ? "" : mainSubject;
-                       List<String> tagList = new ArrayList<String>();
-
+                       // Title, URL, Cover
                        Element stitle = story.getElementsByClass("stitle").first();
                        if (stitle != null) {
                                meta.setTitle(stitle.text());
                                meta.setUrl(stitle.absUrl("href"));
+                               meta.setUuid(meta.getUrl());
                                Element cover = stitle.getElementsByTag("img").first();
                                if (cover != null) {
                                        // note: see data-original if needed?
                                        String coverUrl = cover.absUrl("src");
 
                                        try {
-                                               InputStream in = Instance.getCache().open(
-                                                               new URL(coverUrl), getSupport(), true);
+                                               InputStream in = Instance.getInstance().getCache().open(new URL(coverUrl), getSupport(), true);
                                                try {
-                                                       meta.setCover(new Image(in));
+                                                       Image img = new Image(in);
+                                                       if (img.getSize() == 0) {
+                                                               img.close();
+                                                               throw new IOException(
+                                                                               "Empty image not accepted");
+                                                       }
+                                                       meta.setCover(img);
                                                } finally {
                                                        in.close();
                                                }
                                        } catch (Exception e) {
-                                               Instance.getTraceHandler()
-                                                               .error(new Exception(
-                                                                               "Cannot download cover for Fanfiction story in search mode",
-                                                                               e));
+                                               // Should not happen on Fanfiction.net
+                                               Instance.getInstance().getTraceHandler().error(new Exception(
+                                                               "Cannot download cover for Fanfiction story in search mode: " + meta.getTitle(), e));
                                        }
                                }
                        }
 
+                       // Author
                        Elements as = story.getElementsByTag("a");
                        if (as.size() > 1) {
                                meta.setAuthor(as.get(1).text());
                        }
 
+                       // Tags (concatenated text), published date, updated date, Resume
                        String tags = "";
-
+                       List<String> tagList = new ArrayList<String>();
                        Elements divs = story.getElementsByTag("div");
                        if (divs.size() > 1 && divs.get(1).childNodeSize() > 0) {
                                String resume = divs.get(1).text();
@@ -328,33 +340,31 @@ class Fanfiction extends BasicSearchable {
                                }
 
                                meta.setResume(getSupport().makeChapter(new URL(sourceUrl), 0,
-                                               Instance.getTrans().getString(StringId.DESCRIPTION),
-                                               resume));
+                                               Instance.getInstance().getTrans().getString(StringId.DESCRIPTION), resume));
                        }
 
                        // How are the tags ordered?
                        // We have "Rated: xx", then the language, then all other tags
                        // If the subject(s) is/are present, they are before "Rated: xx"
 
-                       // /////////////
+                       // ////////////
                        // Examples: //
-                       // /////////////
+                       // ////////////
 
                        // Search (Luna) Tags: [Harry Potter, Rated: T, English, Chapters:
                        // 1, Words: 270, Reviews: 2, Published: 2/19/2013, Luna L.]
 
                        // Normal (MLP) Tags: [Rated: T, Spanish, Drama/Suspense, Chapters:
                        // 2, Words: 8,686, Reviews: 1, Favs: 1, Follows: 1, Updated: 4/7,
-                       // Published:
-                       // 4/2]
+                       // Published: 4/2]
 
                        // Crossover (MLP/Who) Tags: [Rated: K+, English, Adventure/Romance,
                        // Chapters: 8, Words: 7,788, Reviews: 2, Favs: 2, Follows: 1,
-                       // Published:
-                       // 9/1/2016]
+                       // Published: 9/1/2016]
 
                        boolean rated = false;
                        boolean isLang = false;
+                       String subject = mainSubject == null ? "" : mainSubject;
                        String[] tab = tags.split("  *-  *");
                        for (int i = 0; i < tab.length; i++) {
                                String tag = tab[i];
@@ -384,6 +394,7 @@ class Fanfiction extends BasicSearchable {
                                                        tagList.add(tag);
                                                }
                                        } else {
+                                               // Normal tags are "/"-separated
                                                for (String t : tag.split("/")) {
                                                        tagList.add(t);
                                                }