Initial commit (working)
[fanfix.git] / src / be / nikiroo / fanfix / supported / MangaFox.java
diff --git a/src/be/nikiroo/fanfix/supported/MangaFox.java b/src/be/nikiroo/fanfix/supported/MangaFox.java
new file mode 100644 (file)
index 0000000..fb72bf5
--- /dev/null
@@ -0,0 +1,409 @@
+package be.nikiroo.fanfix.supported;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Scanner;
+
+import be.nikiroo.fanfix.Instance;
+import be.nikiroo.utils.StringUtils;
+
+class MangaFox extends BasicSupport {
+       @Override
+       protected boolean isHtml() {
+               return true;
+       }
+
+       @Override
+       public String getSourceName() {
+               return "MangaFox.met";
+       }
+
+       @Override
+       protected String getSubject(URL source, InputStream in) {
+               return "manga";
+       }
+
+       @Override
+       public boolean isImageDocument(URL source, InputStream in)
+                       throws IOException {
+               return true;
+       }
+
+       @Override
+       protected List<String> getTags(URL source, InputStream in) {
+               List<String> tags = new ArrayList<String>();
+
+               String line = getLine(in, "/genres/", 0);
+               if (line != null) {
+                       line = StringUtils.unhtml(line);
+                       String[] tab = line.split(",");
+                       if (tab != null) {
+                               for (String tag : tab) {
+                                       tags.add(tag.trim());
+                               }
+                       }
+               }
+
+               return tags;
+       }
+
+       @Override
+       protected String getTitle(URL source, InputStream in) {
+               String line = getLine(in, " property=\"og:title\"", 0);
+               if (line != null) {
+                       int pos = -1;
+                       for (int i = 0; i < 3; i++) {
+                               pos = line.indexOf('"', pos + 1);
+                       }
+
+                       if (pos >= 0) {
+                               line = line.substring(pos + 1);
+                               pos = line.indexOf('"');
+                               if (pos >= 0) {
+                                       return line.substring(0, pos);
+                               }
+                       }
+               }
+
+               return null;
+       }
+
+       @Override
+       protected String getAuthor(URL source, InputStream in) {
+               List<String> authors = new ArrayList<String>();
+
+               String line = getLine(in, "/author/", 0, false);
+               if (line != null) {
+                       for (String ln : StringUtils.unhtml(line).split(",")) {
+                               if (ln != null && !ln.trim().isEmpty()
+                                               && !authors.contains(ln.trim())) {
+                                       authors.add(ln.trim());
+                               }
+                       }
+               }
+
+               try {
+                       in.reset();
+               } catch (IOException e) {
+                       Instance.syserr(e);
+               }
+
+               line = getLine(in, "/artist/", 0, false);
+               if (line != null) {
+                       for (String ln : StringUtils.unhtml(line).split(",")) {
+                               if (ln != null && !ln.trim().isEmpty()
+                                               && !authors.contains(ln.trim())) {
+                                       authors.add(ln.trim());
+                               }
+                       }
+               }
+
+               if (authors.isEmpty()) {
+                       return null;
+               } else {
+                       StringBuilder builder = new StringBuilder();
+                       for (String author : authors) {
+                               if (builder.length() > 0) {
+                                       builder.append(", ");
+                               }
+
+                               builder.append(author);
+                       }
+
+                       return builder.toString();
+               }
+       }
+
+       @Override
+       protected String getDate(URL source, InputStream in) {
+               String line = getLine(in, "/released/", 0);
+               if (line != null) {
+                       line = StringUtils.unhtml(line);
+                       return line.trim();
+               }
+
+               return null;
+       }
+
+       @Override
+       protected String getDesc(URL source, InputStream in) {
+               String line = getLine(in, " property=\"og:description\"", 0);
+               if (line != null) {
+                       int pos = -1;
+                       for (int i = 0; i < 3; i++) {
+                               pos = line.indexOf('"', pos + 1);
+                       }
+
+                       if (pos >= 0) {
+                               line = line.substring(pos + 1);
+                               pos = line.indexOf('"');
+                               if (pos >= 0) {
+                                       return line.substring(0, pos);
+                               }
+                       }
+               }
+
+               return null;
+       }
+
+       @Override
+       protected URL getCover(URL url, InputStream in) {
+               String line = getLine(in, " property=\"og:image\"", 0);
+               String cover = null;
+               if (line != null) {
+                       int pos = -1;
+                       for (int i = 0; i < 3; i++) {
+                               pos = line.indexOf('"', pos + 1);
+                       }
+
+                       if (pos >= 0) {
+                               line = line.substring(pos + 1);
+                               pos = line.indexOf('"');
+                               if (pos >= 0) {
+                                       cover = line.substring(0, pos);
+                               }
+                       }
+               }
+
+               if (cover != null) {
+                       try {
+                               return new URL(cover);
+                       } catch (MalformedURLException e) {
+                               Instance.syserr(e);
+                       }
+               }
+
+               return null;
+       }
+
+       @Override
+       protected List<Entry<String, URL>> getChapters(URL source, InputStream in) {
+               List<Entry<String, URL>> urls = new ArrayList<Entry<String, URL>>();
+
+               String volumeAt = "<h3 class=\"volume\">";
+               String linkAt = "href=\"http://mangafox.me/";
+               String endAt = "<script type=\"text/javascript\">";
+
+               boolean started = false;
+
+               @SuppressWarnings("resource")
+               Scanner scan = new Scanner(in, "UTF-8");
+               scan.useDelimiter("\\n");
+               while (scan.hasNext()) {
+                       String line = scan.next();
+
+                       if (started && line.contains(endAt)) {
+                               break;
+                       } else if (!started && line.contains(volumeAt)) {
+                               started = true;
+                       }
+
+                       if (started && line.contains(linkAt)) {
+                               // Chapter content url
+                               String url = null;
+                               int pos = line.indexOf("href=\"");
+                               if (pos >= 0) {
+                                       line = line.substring(pos + "href=\"".length());
+                                       pos = line.indexOf('\"');
+                                       if (pos >= 0) {
+                                               url = line.substring(0, pos);
+                                       }
+                               }
+
+                               // Chapter name
+                               String name = null;
+                               if (scan.hasNext()) {
+                                       name = StringUtils.unhtml(scan.next()).trim();
+                                       // Remove the "new" tag if present
+                                       if (name.endsWith("new")) {
+                                               name = name.substring(0, name.length() - 3).trim();
+                                       }
+                               }
+
+                               // to help with the retry and the originalUrl
+                               refresh(url);
+
+                               try {
+                                       final String key = name;
+                                       final URL value = new URL(url);
+                                       urls.add(new Entry<String, URL>() {
+                                               public URL setValue(URL value) {
+                                                       return null;
+                                               }
+
+                                               public String getKey() {
+                                                       return key;
+                                               }
+
+                                               public URL getValue() {
+                                                       return value;
+                                               }
+                                       });
+                               } catch (MalformedURLException e) {
+                                       Instance.syserr(e);
+                               }
+                       }
+               }
+
+               // the chapters are in reversed order
+               Collections.reverse(urls);
+
+               return urls;
+       }
+
+       @Override
+       protected String getChapterContent(URL source, InputStream in, int number) {
+               StringBuilder builder = new StringBuilder();
+               String base = getCurrentReferer().toString();
+               int pos = base.lastIndexOf('/');
+               base = base.substring(0, pos + 1); // including the '/' at the end
+
+               boolean close = false;
+               while (in != null) {
+                       String linkNextLine = getLine(in, "return enlarge()", 0);
+                       try {
+                               in.reset();
+                       } catch (IOException e) {
+                               Instance.syserr(e);
+                       }
+
+                       String linkImageLine = getLine(in, "return enlarge()", 1);
+                       String linkNext = null;
+                       String linkImage = null;
+                       pos = linkNextLine.indexOf("href=\"");
+                       if (pos >= 0) {
+                               linkNextLine = linkNextLine.substring(pos + "href=\"".length());
+                               pos = linkNextLine.indexOf('\"');
+                               if (pos >= 0) {
+                                       linkNext = linkNextLine.substring(0, pos);
+                               }
+                       }
+                       pos = linkImageLine.indexOf("src=\"");
+                       if (pos >= 0) {
+                               linkImageLine = linkImageLine
+                                               .substring(pos + "src=\"".length());
+                               pos = linkImageLine.indexOf('\"');
+                               if (pos >= 0) {
+                                       linkImage = linkImageLine.substring(0, pos);
+                               }
+                       }
+
+                       if (linkImage != null) {
+                               builder.append("[");
+                               // to help with the retry and the originalUrl, part 1
+                               builder.append(withoutQuery(linkImage));
+                               builder.append("]\n");
+                       }
+
+                       // to help with the retry and the originalUrl, part 2
+                       refresh(linkImage);
+
+                       if (close) {
+                               try {
+                                       in.close();
+                               } catch (IOException e) {
+                                       Instance.syserr(e);
+                               }
+                       }
+
+                       in = null;
+                       if (linkNext != null && !"javascript:void(0);".equals(linkNext)) {
+                               URL url;
+                               try {
+                                       url = new URL(base + linkNext);
+                                       in = openEx(base + linkNext);
+                                       setCurrentReferer(url);
+                               } catch (IOException e) {
+                                       Instance.syserr(new IOException(
+                                                       "Cannot get the next manga page which is: "
+                                                                       + linkNext, e));
+                               }
+                       }
+
+                       close = true;
+               }
+
+               setCurrentReferer(source);
+               return builder.toString();
+       }
+
+       @Override
+       protected boolean supports(URL url) {
+               return "mangafox.me".equals(url.getHost())
+                               || "www.mangafox.me".equals(url.getHost());
+       }
+
+       /**
+        * Refresh the {@link URL} by calling {@link MangaFox#openEx(String)}.
+        * 
+        * @param url
+        *            the URL to refresh
+        * 
+        * @return TRUE if it was refreshed
+        */
+       private boolean refresh(String url) {
+               try {
+                       openEx(url).close();
+                       return true;
+               } catch (Exception e) {
+                       return false;
+               }
+       }
+
+       /**
+        * Open the URL through the cache, but: retry a second time after 100ms if
+        * it fails, remove the query part of the {@link URL} before saving it to
+        * the cache (so it can be recalled later).
+        * 
+        * @param url
+        *            the {@link URL}
+        * 
+        * @return the resource
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        */
+       private InputStream openEx(String url) throws IOException {
+               try {
+                       return Instance.getCache().open(new URL(url), this, true,
+                                       withoutQuery(url));
+               } catch (Exception e) {
+                       // second chance
+                       try {
+                               Thread.sleep(100);
+                       } catch (InterruptedException ee) {
+                       }
+
+                       return Instance.getCache().open(new URL(url), this, true,
+                                       withoutQuery(url));
+               }
+       }
+
+       /**
+        * Return the same input {@link URL} but without the query part.
+        * 
+        * @param url
+        *            the inpiut {@link URL} as a {@link String}
+        * 
+        * @return the input {@link URL} without query
+        */
+       private URL withoutQuery(String url) {
+               URL o = null;
+               try {
+                       // Remove the query from o (originalUrl), so it can be cached
+                       // correctly
+                       o = new URL(url);
+                       o = new URL(o.getProtocol() + "://" + o.getHost() + o.getPath());
+
+                       return o;
+               } catch (MalformedURLException e) {
+                       return null;
+               }
+       }
+}