MangaHere.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. package eu.kanade.mangafeed.sources;
  2. import android.content.Context;
  3. import org.jsoup.Jsoup;
  4. import org.jsoup.nodes.Document;
  5. import org.jsoup.nodes.Element;
  6. import org.jsoup.select.Elements;
  7. import java.text.ParseException;
  8. import java.text.SimpleDateFormat;
  9. import java.util.ArrayList;
  10. import java.util.Calendar;
  11. import java.util.Date;
  12. import java.util.List;
  13. import java.util.Locale;
  14. import eu.kanade.mangafeed.data.helpers.SourceManager;
  15. import eu.kanade.mangafeed.data.models.Chapter;
  16. import eu.kanade.mangafeed.data.models.Manga;
  17. import eu.kanade.mangafeed.sources.base.Source;
  18. import rx.Observable;
  19. public class MangaHere extends Source {
  20. public static final String NAME = "MangaHere (EN)";
  21. public static final String BASE_URL = "www.mangahere.co";
  22. private static final String INITIAL_UPDATE_URL = "http://www.mangahere.co/latest/";
  23. private static final String INITIAL_SEARCH_URL = "http://www.mangahere.co/search.php?";
  24. public MangaHere(Context context) {
  25. super(context);
  26. }
  27. @Override
  28. public String getName() {
  29. return NAME;
  30. }
  31. @Override
  32. public int getSourceId() {
  33. return SourceManager.MANGAHERE;
  34. }
  35. @Override
  36. protected String getUrlFromPageNumber(int page) {
  37. return INITIAL_UPDATE_URL + page + "/";
  38. }
  39. @Override
  40. protected String getSearchUrl(String query, int page) {
  41. return INITIAL_SEARCH_URL + "name=" + query + "&page=" + page;
  42. }
  43. @Override
  44. public boolean isLoginRequired() {
  45. return false;
  46. }
  47. public Observable<List<String>> getGenres() {
  48. List<String> genres = new ArrayList<>(30);
  49. genres.add("Action");
  50. genres.add("Adventure");
  51. genres.add("Comedy");
  52. genres.add("Drama");
  53. genres.add("Ecchi");
  54. genres.add("Fantasy");
  55. genres.add("Gender Bender");
  56. genres.add("Harem");
  57. genres.add("Historical");
  58. genres.add("Horror");
  59. genres.add("Josei");
  60. genres.add("Martial Arts");
  61. genres.add("Mature");
  62. genres.add("Mecha");
  63. genres.add("Mystery");
  64. genres.add("One Shot");
  65. genres.add("Psychological");
  66. genres.add("Romance");
  67. genres.add("School Life");
  68. genres.add("Sci-fi");
  69. genres.add("Seinen");
  70. genres.add("Shoujo");
  71. genres.add("Shoujo Ai");
  72. genres.add("Shounen");
  73. genres.add("Shounen Ai");
  74. genres.add("Slice of Life");
  75. genres.add("Sports");
  76. genres.add("Supernatural");
  77. genres.add("Tragedy");
  78. genres.add("Yaoi");
  79. genres.add("Yuri");
  80. return Observable.just(genres);
  81. }
  82. @Override
  83. public List<Manga> parsePopularMangasFromHtml(String unparsedHtml) {
  84. Document parsedDocument = Jsoup.parse(unparsedHtml);
  85. List<Manga> updatedMangaList = new ArrayList<>();
  86. Elements updatedHtmlBlocks = parsedDocument.select("div.manga_updates dl");
  87. for (Element currentHtmlBlock : updatedHtmlBlocks) {
  88. Manga currentlyUpdatedManga = constructMangaFromHtmlBlock(currentHtmlBlock);
  89. updatedMangaList.add(currentlyUpdatedManga);
  90. }
  91. return updatedMangaList;
  92. }
  93. @Override
  94. protected List<Manga> parseSearchFromHtml(String unparsedHtml) {
  95. return null;
  96. }
  97. private Manga constructMangaFromHtmlBlock(Element htmlBlock) {
  98. Manga mangaFromHtmlBlock = new Manga();
  99. mangaFromHtmlBlock.source = getSourceId();
  100. Element urlElement = htmlBlock.select("a.manga_info").first();
  101. Element nameElement = htmlBlock.select("a.manga_info").first();
  102. Element updateElement = htmlBlock.select("span.time").first();
  103. if (urlElement != null) {
  104. String fieldUrl = urlElement.attr("href");
  105. mangaFromHtmlBlock.url = fieldUrl;
  106. }
  107. if (nameElement != null) {
  108. String fieldName = nameElement.text();
  109. mangaFromHtmlBlock.title = fieldName;
  110. }
  111. if (updateElement != null) {
  112. long fieldUpdate = parseUpdateFromElement(updateElement);
  113. mangaFromHtmlBlock.last_update = fieldUpdate;
  114. }
  115. return mangaFromHtmlBlock;
  116. }
  117. private long parseUpdateFromElement(Element updateElement) {
  118. String updatedDateAsString = updateElement.text();
  119. if (updatedDateAsString.contains("Today")) {
  120. Calendar today = Calendar.getInstance();
  121. today.set(Calendar.HOUR_OF_DAY, 0);
  122. today.set(Calendar.MINUTE, 0);
  123. today.set(Calendar.SECOND, 0);
  124. today.set(Calendar.MILLISECOND, 0);
  125. try {
  126. Date withoutDay = new SimpleDateFormat("MMM d, yyyy h:mma", Locale.ENGLISH).parse(updatedDateAsString.replace("Today", ""));
  127. return today.getTimeInMillis() + withoutDay.getTime();
  128. } catch (ParseException e) {
  129. return today.getTimeInMillis();
  130. }
  131. } else if (updatedDateAsString.contains("Yesterday")) {
  132. Calendar yesterday = Calendar.getInstance();
  133. yesterday.add(Calendar.DATE, -1);
  134. yesterday.set(Calendar.HOUR_OF_DAY, 0);
  135. yesterday.set(Calendar.MINUTE, 0);
  136. yesterday.set(Calendar.SECOND, 0);
  137. yesterday.set(Calendar.MILLISECOND, 0);
  138. try {
  139. Date withoutDay = new SimpleDateFormat("MMM d, yyyy h:mma", Locale.ENGLISH).parse(updatedDateAsString.replace("Yesterday", ""));
  140. return yesterday.getTimeInMillis() + withoutDay.getTime();
  141. } catch (ParseException e) {
  142. return yesterday.getTimeInMillis();
  143. }
  144. } else {
  145. try {
  146. Date specificDate = new SimpleDateFormat("MMM d, yyyy h:mma", Locale.ENGLISH).parse(updatedDateAsString);
  147. return specificDate.getTime();
  148. } catch (ParseException e) {
  149. // Do Nothing.
  150. }
  151. }
  152. return 0;
  153. }
  154. public Manga parseHtmlToManga(String mangaUrl, String unparsedHtml) {
  155. int beginIndex = unparsedHtml.indexOf("<ul class=\"detail_topText\">");
  156. int endIndex = unparsedHtml.indexOf("</ul>", beginIndex);
  157. String trimmedHtml = unparsedHtml.substring(beginIndex, endIndex);
  158. Document parsedDocument = Jsoup.parse(trimmedHtml);
  159. Elements detailElements = parsedDocument.select("ul.detail_topText li");
  160. Element artistElement = parsedDocument.select("a[href^=http://www.mangahere.co/artist/]").first();
  161. Element authorElement = parsedDocument.select("a[href^=http://www.mangahere.co/author/]").first();
  162. Element descriptionElement = detailElements.select("#show").first();
  163. Element genreElement = detailElements.get(3);
  164. Element statusElement = detailElements.get(6);
  165. Manga newManga = new Manga();
  166. newManga.url = mangaUrl;
  167. if (artistElement != null) {
  168. String fieldArtist = artistElement.text();
  169. newManga.artist = fieldArtist;
  170. }
  171. if (authorElement != null) {
  172. String fieldAuthor = authorElement.text();
  173. newManga.author = fieldAuthor;
  174. }
  175. if (descriptionElement != null) {
  176. String fieldDescription = descriptionElement.text().substring(0, descriptionElement.text().length() - "Show less".length());
  177. newManga.description = fieldDescription;
  178. }
  179. if (genreElement != null) {
  180. String fieldGenre = genreElement.text().substring("Genre(s):".length());
  181. newManga.genre = fieldGenre;
  182. }
  183. if (statusElement != null) {
  184. boolean fieldCompleted = statusElement.text().contains("Completed");
  185. newManga.status = fieldCompleted + "";
  186. }
  187. beginIndex = unparsedHtml.indexOf("<img");
  188. endIndex = unparsedHtml.indexOf("/>", beginIndex);
  189. trimmedHtml = unparsedHtml.substring(beginIndex, endIndex + 2);
  190. parsedDocument = Jsoup.parse(trimmedHtml);
  191. Element thumbnailUrlElement = parsedDocument.select("img").first();
  192. if (thumbnailUrlElement != null) {
  193. String fieldThumbnailUrl = thumbnailUrlElement.attr("src");
  194. newManga.thumbnail_url = fieldThumbnailUrl;
  195. }
  196. newManga.initialized = true;
  197. return newManga;
  198. }
  199. @Override
  200. public List<Chapter> parseHtmlToChapters(String unparsedHtml) {
  201. int beginIndex = unparsedHtml.indexOf("<ul>");
  202. int endIndex = unparsedHtml.indexOf("</ul>", beginIndex);
  203. String trimmedHtml = unparsedHtml.substring(beginIndex, endIndex);
  204. Document parsedDocument = Jsoup.parse(trimmedHtml);
  205. List<Chapter> chapterList = new ArrayList<Chapter>();
  206. Elements chapterElements = parsedDocument.getElementsByTag("li");
  207. for (Element chapterElement : chapterElements) {
  208. Chapter currentChapter = constructChapterFromHtmlBlock(chapterElement);
  209. chapterList.add(currentChapter);
  210. }
  211. return chapterList;
  212. }
  213. private Chapter constructChapterFromHtmlBlock(Element chapterElement) {
  214. Chapter newChapter = Chapter.newChapter();
  215. Element urlElement = chapterElement.select("a").first();
  216. Element nameElement = chapterElement.select("a").first();
  217. Element dateElement = chapterElement.select("span.right").first();
  218. if (urlElement != null) {
  219. String fieldUrl = urlElement.attr("href");
  220. newChapter.url = fieldUrl;
  221. }
  222. if (nameElement != null) {
  223. String fieldName = nameElement.text();
  224. newChapter.name = fieldName;
  225. }
  226. if (dateElement != null) {
  227. long fieldDate = parseDateFromElement(dateElement);
  228. newChapter.date_upload = fieldDate;
  229. }
  230. newChapter.date_fetch = new Date().getTime();
  231. return newChapter;
  232. }
  233. private long parseDateFromElement(Element dateElement) {
  234. String dateAsString = dateElement.text();
  235. if (dateAsString.contains("Today")) {
  236. Calendar today = Calendar.getInstance();
  237. today.set(Calendar.HOUR_OF_DAY, 0);
  238. today.set(Calendar.MINUTE, 0);
  239. today.set(Calendar.SECOND, 0);
  240. today.set(Calendar.MILLISECOND, 0);
  241. try {
  242. Date withoutDay = new SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(dateAsString.replace("Today", ""));
  243. return today.getTimeInMillis() + withoutDay.getTime();
  244. } catch (ParseException e) {
  245. return today.getTimeInMillis();
  246. }
  247. } else if (dateAsString.contains("Yesterday")) {
  248. Calendar yesterday = Calendar.getInstance();
  249. yesterday.add(Calendar.DATE, -1);
  250. yesterday.set(Calendar.HOUR_OF_DAY, 0);
  251. yesterday.set(Calendar.MINUTE, 0);
  252. yesterday.set(Calendar.SECOND, 0);
  253. yesterday.set(Calendar.MILLISECOND, 0);
  254. try {
  255. Date withoutDay = new SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(dateAsString.replace("Yesterday", ""));
  256. return yesterday.getTimeInMillis() + withoutDay.getTime();
  257. } catch (ParseException e) {
  258. return yesterday.getTimeInMillis();
  259. }
  260. } else {
  261. try {
  262. Date date = new SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(dateAsString);
  263. return date.getTime();
  264. } catch (ParseException e) {
  265. // Do Nothing.
  266. }
  267. }
  268. return 0;
  269. }
  270. @Override
  271. public List<String> parseHtmlToPageUrls(String unparsedHtml) {
  272. int beginIndex = unparsedHtml.indexOf("<div class=\"go_page clearfix\">");
  273. int endIndex = unparsedHtml.indexOf("</div>", beginIndex);
  274. String trimmedHtml = unparsedHtml.substring(beginIndex, endIndex);
  275. Document parsedDocument = Jsoup.parse(trimmedHtml);
  276. List<String> pageUrlList = new ArrayList<String>();
  277. Elements pageUrlElements = parsedDocument.select("select.wid60").first().getElementsByTag("option");
  278. for (Element pageUrlElement : pageUrlElements) {
  279. pageUrlList.add(pageUrlElement.attr("value"));
  280. }
  281. return pageUrlList;
  282. }
  283. @Override
  284. public String parseHtmlToImageUrl(String unparsedHtml) {
  285. int beginIndex = unparsedHtml.indexOf("<section class=\"read_img\" id=\"viewer\">");
  286. int endIndex = unparsedHtml.indexOf("</section>", beginIndex);
  287. String trimmedHtml = unparsedHtml.substring(beginIndex, endIndex);
  288. Document parsedDocument = Jsoup.parse(trimmedHtml);
  289. Element imageElement = parsedDocument.getElementById("image");
  290. return imageElement.attr("src");
  291. }
  292. }