package ar.rulosoft.mimanganu.servers; import android.content.Context; import com.squareup.duktape.Duktape; import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; import ar.rulosoft.mimanganu.R; import ar.rulosoft.mimanganu.componentes.Chapter; import ar.rulosoft.mimanganu.componentes.Manga; import ar.rulosoft.mimanganu.componentes.ServerFilter; import ar.rulosoft.mimanganu.utils.Util; import ar.rulosoft.navegadores.Navigator; class KissManga extends ServerBase { private static final String PATTERN_CHAPTER = "<td>[\\s]*<a[\\s]*href=\"(/Manga/[^\"]+)\"[\\s]*title=\"[^\"]+\">([^\"]+)</a>[\\s]*</td>"; private static final String PATTERN_SEARCH = "href=\"(/Manga/.*?)\">([^<]+)</a>[^<]+<p>[^<]+<span class=\"info\""; private static final String IP = "93.174.95.110"; private static final String HOST = "kissmanga.com"; private static final String PAGE_BASE = "http://kissmanga.com/"; private static final String[] genre = new String[]{ "Action", "Adult", "Adventure", "Comedy", "Comic", "Cooking", "Doujinshi", "Drama", "Ecchi", "Fantasy", "Gender Bender", "Harem", "Historical", "Horror", "Josei", "Lolicon", "Manga", "Manhua", "Manhwa", "Martial Arts", "Mature", "Mecha", "Medical", "Music", "Mystery", "One shot", "Psychological", "Romance", "School Life", "Sci-fi", "Seinen", "Shotacon", "Shoujo", "Shoujo Ai", "Shounen", "Shounen Ai", "Slice of Life", "Smut", "Sports", "Supernatural", "Tragedy", "Webtoon", "Yaoi", "Yuri" }; private static String genreVV = "/Genre/"; private static String[] order = {"Popularity", "Latest Update", "New Manga", "a-z"}; private static String[] orderV = new String[]{"/MostPopular", "/LatestUpdate", "/Newest", ""}; KissManga(Context context) { super(context); this.setFlag(R.drawable.flag_en); this.setIcon(R.drawable.kissmanga_icon); this.setServerName("KissManga"); setServerID(ServerBase.KISSMANGA); } @Override public ArrayList<Manga> getMangas() throws Exception { return null; } @Override public ArrayList<Manga> search(String term) throws Exception { // make use of AdvanceSearch, more data is then needed Navigator nav = getNavigatorAndFlushParameters(); nav.addPost("authorArtist", ""); nav.addPost("mangaName", term); nav.addPost("status", ""); nav.addPost("genres", ""); String source = nav.post(PAGE_BASE + "/AdvanceSearch"); ArrayList<Manga> searchList; Pattern p = Pattern.compile(PATTERN_SEARCH); Matcher m = p.matcher(source); if (m.find()) { searchList = new ArrayList<>(); boolean status = getFirstMatchDefault("Status:</span> ([\\S]+)", m.group(), "Ongoing").length() == 9; searchList.add(new Manga(KISSMANGA, m.group(2), m.group(1), status)); } else { searchList = getMangasSource(source); } return searchList; } @Override public void loadChapters(Manga manga, boolean forceReload) throws Exception { if (manga.getChapters() == null || manga.getChapters().size() == 0 || forceReload) loadMangaInformation(manga, forceReload); } @Override public void loadMangaInformation(Manga manga, boolean forceReload) throws Exception { String source = getNavigatorAndFlushParameters().get(PAGE_BASE + manga.getPath()); // Summary manga.setSynopsis(Util.getInstance().fromHtml(getFirstMatchDefault( "<span " + "class=\"info\">Summary:</span>(.+?)</div>", source, defaultSynopsis)).toString()); // Title String pictures = getFirstMatchDefault( "rel=\"image_src\" href=\"(.+?)" + "\"", source, null); if (pictures != null) { manga.setImages(pictures); } // Author manga.setAuthor(Util.getInstance().fromHtml(getFirstMatchDefault("Author:(.+?)</p>", source, "")).toString().replaceAll("^\\s+", "").trim()); // Genre manga.setGenre(Util.getInstance().fromHtml(getFirstMatchDefault("Genres:(.+?)</p>", source, "")).toString().replaceAll("^\\s+", "").trim()); manga.setFinished(getFirstMatchDefault("Status:</span> ([\\S]+)", source, "Ongoing").length() == 9); // Chapter Pattern p = Pattern.compile(PATTERN_CHAPTER); Matcher matcher = p.matcher(source); ArrayList<Chapter> chapters = new ArrayList<>(); while (matcher.find()) { chapters.add(0, new Chapter(matcher.group(2).replace(" Read Online", ""), matcher.group(1))); } manga.setChapters(chapters); } @Override public String getPagesNumber(Chapter chapter, int page) { return chapter.getPath(); } @Override public String getImageFrom(Chapter chapter, int page) throws Exception { if (chapter.getExtra() == null || chapter.getExtra().length() < 2) { String source = getNavigatorAndFlushParameters().post(PAGE_BASE + chapter.getPath()); Pattern p = Pattern.compile("lstImages.push\\(\"(.+?)\""); Matcher m = p.matcher(source); String images = ""; while (m.find()) { images = images + "|" + m.group(1); } chapter.setExtra(images); } return chapter.getExtra().split("\\|")[page]; } @Override public void chapterInit(Chapter chapter) throws Exception { int pages = 0; if (chapter.getExtra() == null || chapter.getExtra().length() < 2) { String source = getNavigatorAndFlushParameters().get(PAGE_BASE + chapter.getPath().replaceAll("[^!-z]+", "")); String ca = getNavigatorAndFlushParameters().get(PAGE_BASE + "/Scripts/ca.js"); String lo = getNavigatorAndFlushParameters().get(PAGE_BASE + "/Scripts/lo.js"); Duktape duktape = Duktape.create(); try { duktape.evaluate(ca); duktape.evaluate(lo); Pattern p = Pattern.compile("javascript\">(.+?)<"); Matcher m = p.matcher(source); while (m.find()) { if (m.group(1).contains("CryptoJS")) { duktape.evaluate(m.group(1)); } } p = Pattern.compile("lstImages.push\\((.+?\\))\\)"); m = p.matcher(source); String images = ""; String image; while (m.find()) { pages++; image = (String) duktape.evaluate(m.group(1) + ".toString()"); images = images + "|" + image; } chapter.setExtra(images); } finally { duktape.close(); } } chapter.setPages(pages); } private ArrayList<Manga> getMangasSource(String source) { ArrayList<Manga> mangas = new ArrayList<>(); Pattern p = Pattern.compile("src=\"([^\"]+)\" style=\"float.+?href=\"(.+?)\">(.+?)<"); Matcher m = p.matcher(source); while (m.find()) { Manga manga = new Manga(KISSMANGA, m.group(3), m.group(2), false); manga.setImages(m.group(1)); mangas.add(manga); } return mangas; } @Override public boolean hasList() { return false; } @Override public ServerFilter[] getServerFilters() { return new ServerFilter[]{new ServerFilter("Included Genre(s) (multiple no order)", genre, ServerFilter.FilterType.MULTI), new ServerFilter("Excluded Genre(s) (multiple no order)", genre, ServerFilter.FilterType.MULTI), new ServerFilter("Order (only applied on single genre selection)", order, ServerFilter.FilterType.SINGLE)}; } @Override public ArrayList<Manga> getMangasFiltered(int[][] filters, int pageNumber) throws Exception { if (filters[0].length == 0 && filters[1].length == 0) { // on first load return getMangasFiltered(0, 0, pageNumber); } else if (filters[0].length == 1) { // single genre selection String web = genreVV + genre[0].replaceAll(" ", "-") + orderV[0]; for (int i = 0; i < genre.length; i++) { if (contains(filters[0], i)) { web = genreVV + genre[i].replaceAll(" ", "-") + orderV[filters[2][0]]; if (pageNumber > 1) { web = web + "?page=" + pageNumber; } } } String source = getNavigatorAndFlushParameters().post(PAGE_BASE + web); return getMangasSource(source); } else { // multiple genre selection if (pageNumber > 1) { return new ArrayList<>(); } else { Navigator nav = getNavigatorAndFlushParameters(); nav.addPost("mangaName", ""); nav.addPost("authorArtist", ""); for (int i = 0; i < genre.length; i++) { if (contains(filters[0], i)) { nav.addPost("genres", "1"); } else if (contains(filters[1], i)) { nav.addPost("genres", "2"); } else { nav.addPost("genres", "0"); } } nav.addPost("status", ""); //stateV[filters[1][0]]) String source = nav.post(PAGE_BASE + "/AdvanceSearch"); return getMangasSource(source); } } } public ArrayList<Manga> getMangasFiltered(int category, int order, int pageNumber) throws Exception { String web = genreVV + genre[category].replaceAll(" ", "-") + orderV[order]; if (pageNumber > 1) { web = web + "?page=" + pageNumber; } String source = getNavigatorAndFlushParameters().post(PAGE_BASE + web); return getMangasSource(source); } }