package be.nikiroo.fanfix.supported; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Scanner; import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.utils.Progress; import be.nikiroo.utils.StringUtils; /** * Support class for FimFiction.net * stories, a website dedicated to My Little Pony. * * @author niki */ class Fimfiction extends BasicSupport { @Override protected boolean isHtml() { return true; } @Override public String getSourceName() { return "FimFiction.net"; } @Override protected MetaData getMeta(URL source, InputStream in) throws IOException { MetaData meta = new MetaData(); meta.setTitle(getTitle(reset(in))); meta.setAuthor(getAuthor(reset(in))); meta.setDate(getDate(reset(in))); meta.setTags(getTags(reset(in))); meta.setSource(getSourceName()); meta.setUrl(source.toString()); meta.setPublisher(getSourceName()); meta.setUuid(source.toString()); meta.setLuid(""); meta.setLang("EN"); meta.setSubject("MLP"); meta.setType(getType().toString()); meta.setImageDocument(false); meta.setCover(getCover(reset(in))); return meta; } @Override public Map getCookies() { Map cookies = new HashMap(); cookies.put("view_mature", "true"); return cookies; } private List getTags(InputStream in) { List tags = new ArrayList(); tags.add("MLP"); @SuppressWarnings("resource") Scanner scan = new Scanner(in, "UTF-8"); scan.useDelimiter("\\n"); boolean started = false; while (scan.hasNext()) { String line = scan.next(); if (!started) { started = line.contains("\"story_container\""); } if (started && line.contains("class=\"tag-")) { if (line.contains("index.php")) { break; // end of *this story* tags } String keyword = "title=\""; Scanner tagScanner = new Scanner(line); tagScanner.useDelimiter(keyword); if (tagScanner.hasNext()) { tagScanner.next();// Ignore first one } while (tagScanner.hasNext()) { String tag = tagScanner.next(); if (tag.contains("\"")) { tag = tag.split("\"")[0]; tag = StringUtils.unhtml(tag).trim(); if (!tag.isEmpty() && !tags.contains(tag)) { tags.add(tag); } } } tagScanner.close(); } } return tags; } private String getTitle(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 StringUtils.unhtml(line.substring(0, pos)).trim(); } } } return null; } private String getAuthor(InputStream in) { String line = getLine(in, " href=\"/user/", 0); if (line != null) { int pos = line.indexOf('"'); if (pos >= 0) { line = line.substring(pos + 1); pos = line.indexOf('"'); if (pos >= 0) { line = line.substring(0, pos); pos = line.lastIndexOf('/'); if (pos >= 0) { line = line.substring(pos + 1); return line.replace('+', ' '); } } } } return null; } private String getDate(InputStream in) { String line = getLine(in, "", 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).trim(); } } } return null; } @Override protected String getDesc(URL source, InputStream in) { // the og: meta version is the SHORT resume, this is the LONG resume return getLine(in, "class=\"description-text bbcode\"", 1); } private BufferedImage getCover(InputStream in) { // Note: the 'og:image' is the SMALL cover, not the full version String cover = getLine(in, "class=\"story_container__story_image\"", 1); if (cover != null) { int pos = cover.indexOf('"'); if (pos >= 0) { cover = cover.substring(pos + 1); pos = cover.indexOf('"'); if (pos >= 0) { cover = cover.substring(0, pos); } } } return getImage(this, null, cover); } @Override protected List> getChapters(URL source, InputStream in, Progress pg) { List> urls = new ArrayList>(); @SuppressWarnings("resource") Scanner scan = new Scanner(in, "UTF-8"); scan.useDelimiter("\\n"); boolean started = false; while (scan.hasNext()) { String line = scan.next().trim(); if (!started) { started = line.equals(""); } else { if (line.equals("")) { break; } if (line.startsWith("'); if (pos >= 0) { name = name.substring(pos + 1); pos = name.indexOf('<'); if (pos >= 0) { name = name.substring(0, pos); } } // Chapter content pos = line.indexOf('/'); if (pos >= 0) { line = line.substring(pos); // we take the /, not +1 pos = line.indexOf('"'); if (pos >= 0) { line = line.substring(0, pos); } } try { final String key = name; final URL value = new URL("http://www.fimfiction.net" + line); urls.add(new Entry() { public URL setValue(URL value) { return null; } public String getKey() { return key; } public URL getValue() { return value; } }); } catch (MalformedURLException e) { Instance.syserr(e); } } } } return urls; } @Override protected String getChapterContent(URL source, InputStream in, int number, Progress pg) { return getLine(in, "
", 1); } @Override protected boolean supports(URL url) { return "fimfiction.net".equals(url.getHost()) || "www.fimfiction.net".equals(url.getHost()); } }