Create an util class to write less code on sources. Save status from sources.
This commit is contained in:
parent
4d9cd6cb6e
commit
986572f6cb
@ -60,8 +60,19 @@ public class Manga implements Serializable {
|
|||||||
|
|
||||||
public int category;
|
public int category;
|
||||||
|
|
||||||
|
public static final int UNKNOWN = 0;
|
||||||
|
public static final int ONGOING = 1;
|
||||||
|
public static final int COMPLETED = 2;
|
||||||
|
public static final int LICENSED = 3;
|
||||||
|
|
||||||
public Manga() {}
|
public Manga() {}
|
||||||
|
|
||||||
|
public static Manga create(String pathUrl) {
|
||||||
|
Manga m = new Manga();
|
||||||
|
m.url = pathUrl;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
public void setUrl(String url) {
|
public void setUrl(String url) {
|
||||||
this.url = UrlUtil.getPath(url);
|
this.url = UrlUtil.getPath(url);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package eu.kanade.mangafeed.data.network;
|
|||||||
|
|
||||||
|
|
||||||
import com.squareup.okhttp.CacheControl;
|
import com.squareup.okhttp.CacheControl;
|
||||||
|
import com.squareup.okhttp.FormEncodingBuilder;
|
||||||
import com.squareup.okhttp.Headers;
|
import com.squareup.okhttp.Headers;
|
||||||
import com.squareup.okhttp.OkHttpClient;
|
import com.squareup.okhttp.OkHttpClient;
|
||||||
import com.squareup.okhttp.Request;
|
import com.squareup.okhttp.Request;
|
||||||
@ -21,6 +22,7 @@ public final class NetworkHelper {
|
|||||||
|
|
||||||
public final CacheControl NULL_CACHE_CONTROL = new CacheControl.Builder().noCache().build();
|
public final CacheControl NULL_CACHE_CONTROL = new CacheControl.Builder().noCache().build();
|
||||||
public final Headers NULL_HEADERS = new Headers.Builder().build();
|
public final Headers NULL_HEADERS = new Headers.Builder().build();
|
||||||
|
public final RequestBody NULL_REQUEST_BODY = new FormEncodingBuilder().build();
|
||||||
|
|
||||||
public NetworkHelper() {
|
public NetworkHelper() {
|
||||||
client = new OkHttpClient();
|
client = new OkHttpClient();
|
||||||
@ -65,7 +67,7 @@ public final class NetworkHelper {
|
|||||||
try {
|
try {
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody != null ? formBody : NULL_REQUEST_BODY)
|
||||||
.headers(headers != null ? headers : NULL_HEADERS)
|
.headers(headers != null ? headers : NULL_HEADERS)
|
||||||
.build();
|
.build();
|
||||||
return Observable.just(client.newCall(request).execute());
|
return Observable.just(client.newCall(request).execute());
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package eu.kanade.mangafeed.data.source.base;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
public abstract class LoginSource extends Source {
|
||||||
|
|
||||||
|
public LoginSource() {}
|
||||||
|
|
||||||
|
public LoginSource(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLoginRequired() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -42,6 +42,11 @@ public abstract class Source extends BaseSource {
|
|||||||
glideHeaders = glideHeadersBuilder().build();
|
glideHeaders = glideHeadersBuilder().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLoginRequired() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the most popular mangas from the source
|
// Get the most popular mangas from the source
|
||||||
public Observable<MangasPage> pullPopularMangasFromNetwork(MangasPage page) {
|
public Observable<MangasPage> pullPopularMangasFromNetwork(MangasPage page) {
|
||||||
if (page.page == 1)
|
if (page.page == 1)
|
||||||
@ -95,8 +100,8 @@ public abstract class Source extends BaseSource {
|
|||||||
return networkService
|
return networkService
|
||||||
.getStringResponse(getBaseUrl() + overrideChapterUrl(chapterUrl), requestHeaders, null)
|
.getStringResponse(getBaseUrl() + overrideChapterUrl(chapterUrl), requestHeaders, null)
|
||||||
.flatMap(unparsedHtml -> {
|
.flatMap(unparsedHtml -> {
|
||||||
List<String> pageUrls = parseHtmlToPageUrls(unparsedHtml);
|
List<Page> pages = convertToPages(parseHtmlToPageUrls(unparsedHtml));
|
||||||
return Observable.just(getFirstImageFromPageUrls(pageUrls, unparsedHtml));
|
return Observable.just(parseFirstPage(pages, unparsedHtml));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,8 +187,7 @@ public abstract class Source extends BaseSource {
|
|||||||
return pages;
|
return pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<Page> getFirstImageFromPageUrls(List<String> pageUrls, String unparsedHtml) {
|
protected List<Page> parseFirstPage(List<Page> pages, String unparsedHtml) {
|
||||||
List<Page> pages = convertToPages(pageUrls);
|
|
||||||
String firstImage = parseHtmlToImageUrl(unparsedHtml);
|
String firstImage = parseHtmlToImageUrl(unparsedHtml);
|
||||||
pages.get(0).setImageUrl(firstImage);
|
pages.get(0).setImageUrl(firstImage);
|
||||||
return pages;
|
return pages;
|
||||||
|
@ -2,6 +2,7 @@ package eu.kanade.mangafeed.data.source.online.english;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import com.squareup.okhttp.FormEncodingBuilder;
|
import com.squareup.okhttp.FormEncodingBuilder;
|
||||||
import com.squareup.okhttp.Headers;
|
import com.squareup.okhttp.Headers;
|
||||||
@ -30,12 +31,13 @@ import java.util.regex.Pattern;
|
|||||||
import eu.kanade.mangafeed.data.database.models.Chapter;
|
import eu.kanade.mangafeed.data.database.models.Chapter;
|
||||||
import eu.kanade.mangafeed.data.database.models.Manga;
|
import eu.kanade.mangafeed.data.database.models.Manga;
|
||||||
import eu.kanade.mangafeed.data.source.SourceManager;
|
import eu.kanade.mangafeed.data.source.SourceManager;
|
||||||
import eu.kanade.mangafeed.data.source.base.Source;
|
import eu.kanade.mangafeed.data.source.base.LoginSource;
|
||||||
import eu.kanade.mangafeed.data.source.model.MangasPage;
|
import eu.kanade.mangafeed.data.source.model.MangasPage;
|
||||||
import eu.kanade.mangafeed.data.source.model.Page;
|
import eu.kanade.mangafeed.data.source.model.Page;
|
||||||
|
import eu.kanade.mangafeed.util.Parser;
|
||||||
import rx.Observable;
|
import rx.Observable;
|
||||||
|
|
||||||
public class Batoto extends Source {
|
public class Batoto extends LoginSource {
|
||||||
|
|
||||||
public static final String NAME = "Batoto (EN)";
|
public static final String NAME = "Batoto (EN)";
|
||||||
public static final String BASE_URL = "http://bato.to";
|
public static final String BASE_URL = "http://bato.to";
|
||||||
@ -87,56 +89,6 @@ public class Batoto extends Source {
|
|||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Observable<List<String>> getGenres() {
|
|
||||||
List<String> genres = new ArrayList<>(38);
|
|
||||||
|
|
||||||
genres.add("4-Koma");
|
|
||||||
genres.add("Action");
|
|
||||||
genres.add("Adventure");
|
|
||||||
genres.add("Award Winning");
|
|
||||||
genres.add("Comedy");
|
|
||||||
genres.add("Cooking");
|
|
||||||
genres.add("Doujinshi");
|
|
||||||
genres.add("Drama");
|
|
||||||
genres.add("Ecchi");
|
|
||||||
genres.add("Fantasy");
|
|
||||||
genres.add("Gender Bender");
|
|
||||||
genres.add("Harem");
|
|
||||||
genres.add("Historical");
|
|
||||||
genres.add("Horror");
|
|
||||||
genres.add("Josei");
|
|
||||||
genres.add("Martial Arts");
|
|
||||||
genres.add("Mecha");
|
|
||||||
genres.add("Medical");
|
|
||||||
genres.add("Music");
|
|
||||||
genres.add("Mystery");
|
|
||||||
genres.add("One Shot");
|
|
||||||
genres.add("Psychological");
|
|
||||||
genres.add("Romance");
|
|
||||||
genres.add("School Life");
|
|
||||||
genres.add("Sci-fi");
|
|
||||||
genres.add("Seinen");
|
|
||||||
genres.add("Shoujo");
|
|
||||||
genres.add("Shoujo Ai");
|
|
||||||
genres.add("Shounen");
|
|
||||||
genres.add("Shounen Ai");
|
|
||||||
genres.add("Slice of Life");
|
|
||||||
genres.add("Smut");
|
|
||||||
genres.add("Sports");
|
|
||||||
genres.add("Supernatural");
|
|
||||||
genres.add("Tragedy");
|
|
||||||
genres.add("Webtoon");
|
|
||||||
genres.add("Yaoi");
|
|
||||||
genres.add("Yuri");
|
|
||||||
|
|
||||||
return Observable.just(genres);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLoginRequired() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getInitialPopularMangasUrl() {
|
public String getInitialPopularMangasUrl() {
|
||||||
return String.format(POPULAR_MANGAS_URL, 1);
|
return String.format(POPULAR_MANGAS_URL, 1);
|
||||||
@ -167,140 +119,88 @@ public class Batoto extends Source {
|
|||||||
return String.format(PAGE_URL, id, defaultPageUrl.substring(end+1));
|
return String.format(PAGE_URL, id, defaultPageUrl.substring(end+1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private List<Manga> parseMangasFromHtml(Document parsedHtml) {
|
||||||
protected List<Manga> parsePopularMangasFromHtml(Document parsedHtml) {
|
|
||||||
if (parsedHtml.text().contains("No (more) comics found!")) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Manga> mangaList = new ArrayList<>();
|
List<Manga> mangaList = new ArrayList<>();
|
||||||
|
|
||||||
Elements updatedHtmlBlocks = parsedHtml.select("tr:not([id]):not([class])");
|
if (!parsedHtml.text().contains("No (more) comics found!")) {
|
||||||
for (Element currentHtmlBlock : updatedHtmlBlocks) {
|
for (Element currentHtmlBlock : parsedHtml.select("tr:not([id]):not([class])")) {
|
||||||
Manga currentlyUpdatedManga = constructMangaFromHtmlBlock(currentHtmlBlock);
|
Manga manga = constructMangaFromHtmlBlock(currentHtmlBlock);
|
||||||
|
mangaList.add(manga);
|
||||||
mangaList.add(currentlyUpdatedManga);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return mangaList;
|
return mangaList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<Manga> parsePopularMangasFromHtml(Document parsedHtml) {
|
||||||
|
return parseMangasFromHtml(parsedHtml);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String parseNextPopularMangasUrl(Document parsedHtml, MangasPage page) {
|
protected String parseNextPopularMangasUrl(Document parsedHtml, MangasPage page) {
|
||||||
Element next = parsedHtml.select("#show_more_row").first();
|
Element next = Parser.element(parsedHtml, "#show_more_row");
|
||||||
if (next == null)
|
return next != null ? String.format(POPULAR_MANGAS_URL, page.page + 1) : null;
|
||||||
return null;
|
|
||||||
|
|
||||||
return String.format(POPULAR_MANGAS_URL, page.page + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<Manga> parseSearchFromHtml(Document parsedHtml) {
|
protected List<Manga> parseSearchFromHtml(Document parsedHtml) {
|
||||||
if (parsedHtml.text().contains("No (more) comics found!")) {
|
return parseMangasFromHtml(parsedHtml);
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Manga> mangaList = new ArrayList<>();
|
|
||||||
|
|
||||||
Elements updatedHtmlBlocks = parsedHtml.select("tr:not([id]):not([class])");
|
|
||||||
for (Element currentHtmlBlock : updatedHtmlBlocks) {
|
|
||||||
Manga currentlyUpdatedManga = constructMangaFromHtmlBlock(currentHtmlBlock);
|
|
||||||
|
|
||||||
mangaList.add(currentlyUpdatedManga);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mangaList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Manga constructMangaFromHtmlBlock(Element htmlBlock) {
|
private Manga constructMangaFromHtmlBlock(Element htmlBlock) {
|
||||||
Manga mangaFromHtmlBlock = new Manga();
|
Manga manga = new Manga();
|
||||||
|
manga.source = getId();
|
||||||
Element urlElement = htmlBlock.select("a[href^=http://bato.to]").first();
|
|
||||||
Element updateElement = htmlBlock.select("td").get(5);
|
|
||||||
|
|
||||||
mangaFromHtmlBlock.source = getId();
|
|
||||||
|
|
||||||
|
Element urlElement = Parser.element(htmlBlock, "a[href^=http://bato.to]");
|
||||||
if (urlElement != null) {
|
if (urlElement != null) {
|
||||||
mangaFromHtmlBlock.setUrl(urlElement.attr("href"));
|
manga.setUrl(urlElement.attr("href"));
|
||||||
mangaFromHtmlBlock.title = urlElement.text().trim();
|
manga.title = urlElement.text().trim();
|
||||||
}
|
}
|
||||||
if (updateElement != null) {
|
return manga;
|
||||||
mangaFromHtmlBlock.last_update = parseUpdateFromElement(updateElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mangaFromHtmlBlock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String parseNextSearchUrl(Document parsedHtml, MangasPage page, String query) {
|
protected String parseNextSearchUrl(Document parsedHtml, MangasPage page, String query) {
|
||||||
Element next = parsedHtml.select("#show_more_row").first();
|
Element next = Parser.element(parsedHtml, "#show_more_row");
|
||||||
if (next == null)
|
return next != null ? String.format(SEARCH_URL, query, page.page + 1) : null;
|
||||||
return null;
|
|
||||||
|
|
||||||
return String.format(SEARCH_URL, query, page.page + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private long parseUpdateFromElement(Element updateElement) {
|
|
||||||
String updatedDateAsString = updateElement.text();
|
|
||||||
|
|
||||||
try {
|
|
||||||
Date specificDate = new SimpleDateFormat("dd MMMMM yyyy - hh:mm a", Locale.ENGLISH).parse(updatedDateAsString);
|
|
||||||
|
|
||||||
return specificDate.getTime();
|
|
||||||
} catch (ParseException e) {
|
|
||||||
// Do Nothing.
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Manga parseHtmlToManga(String mangaUrl, String unparsedHtml) {
|
protected Manga parseHtmlToManga(String mangaUrl, String unparsedHtml) {
|
||||||
Document parsedDocument = Jsoup.parse(unparsedHtml);
|
Document parsedDocument = Jsoup.parse(unparsedHtml);
|
||||||
|
|
||||||
Elements artistElements = parsedDocument.select("a[href^=http://bato.to/search?artist_name]");
|
Element tbody = parsedDocument.select("tbody").first();
|
||||||
Element descriptionElement = parsedDocument.select("tr").get(5);
|
Element artistElement = tbody.select("tr:contains(Author/Artist:)").first();
|
||||||
Elements genreElements = parsedDocument.select("img[src=http://bato.to/forums/public/style_images/master/bullet_black.png]");
|
Elements genreElements = tbody.select("tr:contains(Genres:) img");
|
||||||
Element thumbnailUrlElement = parsedDocument.select("img[src^=http://img.bato.to/forums/uploads/]").first();
|
|
||||||
|
|
||||||
Manga newManga = new Manga();
|
Manga manga = Manga.create(mangaUrl);
|
||||||
newManga.url = mangaUrl;
|
manga.author = Parser.text(artistElement, "td:eq(1)");
|
||||||
|
manga.artist = Parser.text(artistElement, "td:eq(2)", manga.author);
|
||||||
|
manga.description = Parser.text(tbody, "tr:contains(Description:) > td:eq(1)");
|
||||||
|
manga.thumbnail_url = Parser.src(parsedDocument, "img[src^=http://img.bato.to/forums/uploads/]");
|
||||||
|
manga.status = parseStatus(Parser.text(parsedDocument, "tr:contains(Status:) > td:eq(1)"));
|
||||||
|
|
||||||
if (artistElements != null) {
|
if (!genreElements.isEmpty()) {
|
||||||
newManga.author = artistElements.get(0).text();
|
List<String> genres = new ArrayList<>();
|
||||||
if (artistElements.size() > 1) {
|
for (Element element : genreElements) {
|
||||||
newManga.artist = artistElements.get(1).text();
|
genres.add(element.attr("alt"));
|
||||||
} else {
|
|
||||||
newManga.artist = newManga.author;
|
|
||||||
}
|
}
|
||||||
}
|
manga.genre = TextUtils.join(", ", genres);
|
||||||
if (descriptionElement != null) {
|
|
||||||
newManga.description = descriptionElement.text().substring("Description:".length()).trim();
|
|
||||||
}
|
|
||||||
if (genreElements != null) {
|
|
||||||
String fieldGenres = "";
|
|
||||||
for (int index = 0; index < genreElements.size(); index++) {
|
|
||||||
String currentGenre = genreElements.get(index).attr("alt");
|
|
||||||
|
|
||||||
if (index < genreElements.size() - 1) {
|
|
||||||
fieldGenres += currentGenre + ", ";
|
|
||||||
} else {
|
|
||||||
fieldGenres += currentGenre;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newManga.genre = fieldGenres;
|
|
||||||
}
|
|
||||||
if (thumbnailUrlElement != null) {
|
|
||||||
newManga.thumbnail_url = thumbnailUrlElement.attr("src");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean fieldCompleted = unparsedHtml.contains("<td>Complete</td>");
|
manga.initialized = true;
|
||||||
//TODO fix
|
return manga;
|
||||||
newManga.status = 0;
|
}
|
||||||
|
|
||||||
newManga.initialized = true;
|
private int parseStatus(String status) {
|
||||||
|
switch (status) {
|
||||||
return newManga;
|
case "Ongoing":
|
||||||
|
return Manga.ONGOING;
|
||||||
|
case "Complete":
|
||||||
|
return Manga.COMPLETED;
|
||||||
|
default:
|
||||||
|
return Manga.UNKNOWN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -311,34 +211,30 @@ public class Batoto extends Source {
|
|||||||
|
|
||||||
Elements chapterElements = parsedDocument.select("tr.row.lang_English.chapter_row");
|
Elements chapterElements = parsedDocument.select("tr.row.lang_English.chapter_row");
|
||||||
for (Element chapterElement : chapterElements) {
|
for (Element chapterElement : chapterElements) {
|
||||||
Chapter currentChapter = constructChapterFromHtmlBlock(chapterElement);
|
Chapter chapter = constructChapterFromHtmlBlock(chapterElement);
|
||||||
chapterList.add(currentChapter);
|
chapterList.add(chapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
//saveChaptersToDatabase(chapterList, mangaUrl);
|
|
||||||
|
|
||||||
return chapterList;
|
return chapterList;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Chapter constructChapterFromHtmlBlock(Element chapterElement) {
|
private Chapter constructChapterFromHtmlBlock(Element chapterElement) {
|
||||||
Chapter newChapter = Chapter.create();
|
Chapter chapter = Chapter.create();
|
||||||
|
|
||||||
Element urlElement = chapterElement.select("a[href^=http://bato.to/reader").first();
|
Element urlElement = chapterElement.select("a[href^=http://bato.to/reader").first();
|
||||||
Element dateElement = chapterElement.select("td").get(4);
|
Element dateElement = chapterElement.select("td").get(4);
|
||||||
|
|
||||||
if (urlElement != null) {
|
if (urlElement != null) {
|
||||||
String fieldUrl = urlElement.attr("href");
|
String fieldUrl = urlElement.attr("href");
|
||||||
newChapter.setUrl(fieldUrl);
|
chapter.setUrl(fieldUrl);
|
||||||
newChapter.name = urlElement.text().trim();
|
chapter.name = urlElement.text().trim();
|
||||||
|
|
||||||
}
|
}
|
||||||
if (dateElement != null) {
|
if (dateElement != null) {
|
||||||
newChapter.date_upload = parseDateFromElement(dateElement);
|
chapter.date_upload = parseDateFromElement(dateElement);
|
||||||
}
|
}
|
||||||
newChapter.date_fetch = new Date().getTime();
|
chapter.date_fetch = new Date().getTime();
|
||||||
|
|
||||||
return newChapter;
|
return chapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long parseDateFromElement(Element dateElement) {
|
private long parseDateFromElement(Element dateElement) {
|
||||||
@ -372,8 +268,7 @@ public class Batoto extends Source {
|
|||||||
|
|
||||||
List<String> pageUrlList = new ArrayList<>();
|
List<String> pageUrlList = new ArrayList<>();
|
||||||
|
|
||||||
Element selectElement = parsedDocument.select("#page_select").first();
|
Element selectElement = Parser.element(parsedDocument, "#page_select");
|
||||||
|
|
||||||
if (selectElement != null) {
|
if (selectElement != null) {
|
||||||
for (Element pageUrlElement : selectElement.select("option")) {
|
for (Element pageUrlElement : selectElement.select("option")) {
|
||||||
pageUrlList.add(pageUrlElement.attr("value"));
|
pageUrlList.add(pageUrlElement.attr("value"));
|
||||||
@ -389,8 +284,7 @@ public class Batoto extends Source {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<Page> getFirstImageFromPageUrls(List<String> pageUrls, String unparsedHtml) {
|
protected List<Page> parseFirstPage(List<Page> pages, String unparsedHtml) {
|
||||||
List<Page> pages = convertToPages(pageUrls);
|
|
||||||
if (!unparsedHtml.contains("Want to see this chapter per page instead?")) {
|
if (!unparsedHtml.contains("Want to see this chapter per page instead?")) {
|
||||||
String firstImage = parseHtmlToImageUrl(unparsedHtml);
|
String firstImage = parseHtmlToImageUrl(unparsedHtml);
|
||||||
pages.get(0).setImageUrl(firstImage);
|
pages.get(0).setImageUrl(firstImage);
|
||||||
@ -412,9 +306,7 @@ public class Batoto extends Source {
|
|||||||
String trimmedHtml = unparsedHtml.substring(beginIndex, endIndex);
|
String trimmedHtml = unparsedHtml.substring(beginIndex, endIndex);
|
||||||
|
|
||||||
Document parsedDocument = Jsoup.parse(trimmedHtml);
|
Document parsedDocument = Jsoup.parse(trimmedHtml);
|
||||||
|
|
||||||
Element imageElement = parsedDocument.getElementById("comic_page");
|
Element imageElement = parsedDocument.getElementById("comic_page");
|
||||||
|
|
||||||
return imageElement.attr("src");
|
return imageElement.attr("src");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,7 +323,7 @@ public class Batoto extends Source {
|
|||||||
String postUrl = form.attr("action");
|
String postUrl = form.attr("action");
|
||||||
|
|
||||||
FormEncodingBuilder formBody = new FormEncodingBuilder();
|
FormEncodingBuilder formBody = new FormEncodingBuilder();
|
||||||
Element authKey = form.select("input[name=auth_key").first();
|
Element authKey = form.select("input[name=auth_key]").first();
|
||||||
|
|
||||||
formBody.add(authKey.attr("name"), authKey.attr("value"));
|
formBody.add(authKey.attr("name"), authKey.attr("value"));
|
||||||
formBody.add("ips_username", username);
|
formBody.add("ips_username", username);
|
||||||
|
@ -10,7 +10,6 @@ import com.squareup.okhttp.Response;
|
|||||||
import org.jsoup.Jsoup;
|
import org.jsoup.Jsoup;
|
||||||
import org.jsoup.nodes.Document;
|
import org.jsoup.nodes.Document;
|
||||||
import org.jsoup.nodes.Element;
|
import org.jsoup.nodes.Element;
|
||||||
import org.jsoup.select.Elements;
|
|
||||||
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
@ -27,6 +26,7 @@ import eu.kanade.mangafeed.data.source.SourceManager;
|
|||||||
import eu.kanade.mangafeed.data.source.base.Source;
|
import eu.kanade.mangafeed.data.source.base.Source;
|
||||||
import eu.kanade.mangafeed.data.source.model.MangasPage;
|
import eu.kanade.mangafeed.data.source.model.MangasPage;
|
||||||
import eu.kanade.mangafeed.data.source.model.Page;
|
import eu.kanade.mangafeed.data.source.model.Page;
|
||||||
|
import eu.kanade.mangafeed.util.Parser;
|
||||||
import rx.Observable;
|
import rx.Observable;
|
||||||
|
|
||||||
public class Kissmanga extends Source {
|
public class Kissmanga extends Source {
|
||||||
@ -64,11 +64,6 @@ public class Kissmanga extends Source {
|
|||||||
return BASE_URL;
|
return BASE_URL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLoginRequired() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getInitialPopularMangasUrl() {
|
protected String getInitialPopularMangasUrl() {
|
||||||
return String.format(POPULAR_MANGAS_URL, 1);
|
return String.format(POPULAR_MANGAS_URL, 1);
|
||||||
@ -83,36 +78,32 @@ public class Kissmanga extends Source {
|
|||||||
protected List<Manga> parsePopularMangasFromHtml(Document parsedHtml) {
|
protected List<Manga> parsePopularMangasFromHtml(Document parsedHtml) {
|
||||||
List<Manga> mangaList = new ArrayList<>();
|
List<Manga> mangaList = new ArrayList<>();
|
||||||
|
|
||||||
Elements mangaHtmlBlocks = parsedHtml.select("table.listing tr:gt(1)");
|
for (Element currentHtmlBlock : parsedHtml.select("table.listing tr:gt(1)")) {
|
||||||
for (Element currentHtmlBlock : mangaHtmlBlocks) {
|
Manga manga = constructPopularMangaFromHtml(currentHtmlBlock);
|
||||||
Manga currentManga = constructPopularMangaFromHtmlBlock(currentHtmlBlock);
|
mangaList.add(manga);
|
||||||
mangaList.add(currentManga);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mangaList;
|
return mangaList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Manga constructPopularMangaFromHtmlBlock(Element htmlBlock) {
|
private Manga constructPopularMangaFromHtml(Element htmlBlock) {
|
||||||
Manga mangaFromHtmlBlock = new Manga();
|
Manga manga = new Manga();
|
||||||
mangaFromHtmlBlock.source = getId();
|
manga.source = getId();
|
||||||
|
|
||||||
Element urlElement = htmlBlock.select("td a:eq(0)").first();
|
Element urlElement = Parser.element(htmlBlock, "td a:eq(0)");
|
||||||
|
|
||||||
if (urlElement != null) {
|
if (urlElement != null) {
|
||||||
mangaFromHtmlBlock.setUrl(urlElement.attr("href"));
|
manga.setUrl(urlElement.attr("href"));
|
||||||
mangaFromHtmlBlock.title = urlElement.text();
|
manga.title = urlElement.text();
|
||||||
}
|
}
|
||||||
|
|
||||||
return mangaFromHtmlBlock;
|
return manga;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String parseNextPopularMangasUrl(Document parsedHtml, MangasPage page) {
|
protected String parseNextPopularMangasUrl(Document parsedHtml, MangasPage page) {
|
||||||
Element next = parsedHtml.select("li > a:contains(› Next)").first();
|
String path = Parser.href(parsedHtml, "li > a:contains(› Next)");
|
||||||
if (next == null)
|
return path != null ? BASE_URL + path : null;
|
||||||
return null;
|
|
||||||
|
|
||||||
return BASE_URL + next.attr("href");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Observable<MangasPage> searchMangasFromNetwork(MangasPage page, String query) {
|
public Observable<MangasPage> searchMangasFromNetwork(MangasPage page, String query) {
|
||||||
@ -147,90 +138,75 @@ public class Kissmanga extends Source {
|
|||||||
@Override
|
@Override
|
||||||
protected Manga parseHtmlToManga(String mangaUrl, String unparsedHtml) {
|
protected Manga parseHtmlToManga(String mangaUrl, String unparsedHtml) {
|
||||||
Document parsedDocument = Jsoup.parse(unparsedHtml);
|
Document parsedDocument = Jsoup.parse(unparsedHtml);
|
||||||
|
|
||||||
Element infoElement = parsedDocument.select("div.barContent").first();
|
Element infoElement = parsedDocument.select("div.barContent").first();
|
||||||
Element titleElement = infoElement.select("a.bigChar").first();
|
|
||||||
Element authorElement = infoElement.select("p:has(span:contains(Author:)) > a").first();
|
|
||||||
Elements genreElement = infoElement.select("p:has(span:contains(Genres:)) > *:gt(0)");
|
|
||||||
Elements descriptionElement = infoElement.select("p:has(span:contains(Summary:)) ~ p");
|
|
||||||
Element thumbnailUrlElement = parsedDocument.select(".rightBox:eq(0) img").first();
|
|
||||||
|
|
||||||
Manga newManga = new Manga();
|
Manga manga = Manga.create(mangaUrl);
|
||||||
newManga.url = mangaUrl;
|
manga.title = Parser.text(infoElement, "a.bigChar");
|
||||||
|
manga.author = Parser.text(infoElement, "p:has(span:contains(Author:)) > a");
|
||||||
|
manga.genre = Parser.allText(infoElement, "p:has(span:contains(Genres:)) > *:gt(0)");
|
||||||
|
manga.description = Parser.allText(infoElement, "p:has(span:contains(Summary:)) ~ p");
|
||||||
|
manga.status = parseStatus(Parser.text(infoElement, "p:has(span:contains(Status:))"));
|
||||||
|
|
||||||
if (titleElement != null) {
|
String thumbnail = Parser.src(parsedDocument, ".rightBox:eq(0) img");
|
||||||
newManga.title = titleElement.text();
|
if (thumbnail != null) {
|
||||||
|
manga.thumbnail_url = Uri.parse(thumbnail).buildUpon().authority(IP).toString();
|
||||||
}
|
}
|
||||||
if (authorElement != null) {
|
|
||||||
newManga.author = authorElement.text();
|
|
||||||
}
|
|
||||||
if (descriptionElement != null) {
|
|
||||||
newManga.description = descriptionElement.text();
|
|
||||||
}
|
|
||||||
if (genreElement != null) {
|
|
||||||
newManga.genre = genreElement.text();
|
|
||||||
}
|
|
||||||
if (thumbnailUrlElement != null) {
|
|
||||||
newManga.thumbnail_url = Uri.parse(thumbnailUrlElement.attr("src"))
|
|
||||||
.buildUpon().authority(IP).toString();
|
|
||||||
}
|
|
||||||
// if (statusElement != null) {
|
|
||||||
// boolean fieldCompleted = statusElement.text().contains("Completed");
|
|
||||||
// newManga.status = fieldCompleted + "";
|
|
||||||
// }
|
|
||||||
|
|
||||||
newManga.initialized = true;
|
manga.initialized = true;
|
||||||
|
return manga;
|
||||||
|
}
|
||||||
|
|
||||||
return newManga;
|
private int parseStatus(String status) {
|
||||||
|
if (status.contains("Ongoing")) {
|
||||||
|
return Manga.ONGOING;
|
||||||
|
}
|
||||||
|
if (status.contains("Completed")) {
|
||||||
|
return Manga.COMPLETED;
|
||||||
|
}
|
||||||
|
return Manga.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<Chapter> parseHtmlToChapters(String unparsedHtml) {
|
protected List<Chapter> parseHtmlToChapters(String unparsedHtml) {
|
||||||
Document parsedDocument = Jsoup.parse(unparsedHtml);
|
Document parsedDocument = Jsoup.parse(unparsedHtml);
|
||||||
|
|
||||||
List<Chapter> chapterList = new ArrayList<>();
|
List<Chapter> chapterList = new ArrayList<>();
|
||||||
|
|
||||||
Elements chapterElements = parsedDocument.select("table.listing tr:gt(1)");
|
for (Element chapterElement : parsedDocument.select("table.listing tr:gt(1)")) {
|
||||||
for (Element chapterElement : chapterElements) {
|
Chapter chapter = constructChapterFromHtmlBlock(chapterElement);
|
||||||
Chapter currentChapter = constructChapterFromHtmlBlock(chapterElement);
|
chapterList.add(chapter);
|
||||||
|
|
||||||
chapterList.add(currentChapter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return chapterList;
|
return chapterList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Chapter constructChapterFromHtmlBlock(Element chapterElement) {
|
private Chapter constructChapterFromHtmlBlock(Element chapterElement) {
|
||||||
Chapter newChapter = Chapter.create();
|
Chapter chapter = Chapter.create();
|
||||||
|
|
||||||
Element urlElement = chapterElement.select("a").first();
|
Element urlElement = Parser.element(chapterElement, "a");
|
||||||
Element dateElement = chapterElement.select("td:eq(1)").first();
|
String date = Parser.text(chapterElement, "td:eq(1)");
|
||||||
|
|
||||||
if (urlElement != null) {
|
if (urlElement != null) {
|
||||||
newChapter.setUrl(urlElement.attr("href"));
|
chapter.setUrl(urlElement.attr("href"));
|
||||||
newChapter.name = urlElement.text();
|
chapter.name = urlElement.text();
|
||||||
}
|
}
|
||||||
if (dateElement != null) {
|
if (date != null) {
|
||||||
try {
|
try {
|
||||||
newChapter.date_upload = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH).parse(dateElement.text()).getTime();
|
chapter.date_upload = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH).parse(date).getTime();
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) { /* Ignore */ }
|
||||||
// Do Nothing.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
newChapter.date_fetch = new Date().getTime();
|
chapter.date_fetch = new Date().getTime();
|
||||||
|
return chapter;
|
||||||
return newChapter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Observable<List<Page>> pullPageListFromNetwork(final String chapterUrl) {
|
public Observable<List<Page>> pullPageListFromNetwork(final String chapterUrl) {
|
||||||
FormEncodingBuilder builder = new FormEncodingBuilder();
|
|
||||||
return networkService
|
return networkService
|
||||||
.postData(getBaseUrl() + overrideChapterUrl(chapterUrl), builder.build(), requestHeaders)
|
.postData(getBaseUrl() + overrideChapterUrl(chapterUrl), null, requestHeaders)
|
||||||
.flatMap(networkService::mapResponseToString)
|
.flatMap(networkService::mapResponseToString)
|
||||||
.flatMap(unparsedHtml -> {
|
.flatMap(unparsedHtml -> {
|
||||||
List<String> pageUrls = parseHtmlToPageUrls(unparsedHtml);
|
List<Page> pages = convertToPages(parseHtmlToPageUrls(unparsedHtml));
|
||||||
return Observable.just(getFirstImageFromPageUrls(pageUrls, unparsedHtml));
|
return Observable.just(parseFirstPage(pages, unparsedHtml));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,18 +224,13 @@ public class Kissmanga extends Source {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<Page> getFirstImageFromPageUrls(List<String> pageUrls, String unparsedHtml) {
|
protected List<Page> parseFirstPage(List<Page> pages, String unparsedHtml) {
|
||||||
List<Page> pages = convertToPages(pageUrls);
|
|
||||||
|
|
||||||
Pattern p = Pattern.compile("lstImages.push\\(\"(.+?)\"");
|
Pattern p = Pattern.compile("lstImages.push\\(\"(.+?)\"");
|
||||||
Matcher m = p.matcher(unparsedHtml);
|
Matcher m = p.matcher(unparsedHtml);
|
||||||
List<String> imageUrls = new ArrayList<>();
|
|
||||||
while (m.find()) {
|
|
||||||
imageUrls.add(m.group(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < pages.size(); i++) {
|
int i = 0;
|
||||||
pages.get(i).setImageUrl(imageUrls.get(i));
|
while (m.find()) {
|
||||||
|
pages.get(i++).setImageUrl(m.group(1));
|
||||||
}
|
}
|
||||||
return pages;
|
return pages;
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import eu.kanade.mangafeed.data.database.models.Manga;
|
|||||||
import eu.kanade.mangafeed.data.source.SourceManager;
|
import eu.kanade.mangafeed.data.source.SourceManager;
|
||||||
import eu.kanade.mangafeed.data.source.base.Source;
|
import eu.kanade.mangafeed.data.source.base.Source;
|
||||||
import eu.kanade.mangafeed.data.source.model.MangasPage;
|
import eu.kanade.mangafeed.data.source.model.MangasPage;
|
||||||
|
import eu.kanade.mangafeed.util.Parser;
|
||||||
|
|
||||||
public class Mangafox extends Source {
|
public class Mangafox extends Source {
|
||||||
|
|
||||||
@ -49,11 +50,6 @@ public class Mangafox extends Source {
|
|||||||
return BASE_URL;
|
return BASE_URL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLoginRequired() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getInitialPopularMangasUrl() {
|
protected String getInitialPopularMangasUrl() {
|
||||||
return String.format(POPULAR_MANGAS_URL, "");
|
return String.format(POPULAR_MANGAS_URL, "");
|
||||||
@ -68,48 +64,39 @@ public class Mangafox extends Source {
|
|||||||
protected List<Manga> parsePopularMangasFromHtml(Document parsedHtml) {
|
protected List<Manga> parsePopularMangasFromHtml(Document parsedHtml) {
|
||||||
List<Manga> mangaList = new ArrayList<>();
|
List<Manga> mangaList = new ArrayList<>();
|
||||||
|
|
||||||
Elements mangaHtmlBlocks = parsedHtml.select("div#mangalist > ul.list > li");
|
for (Element currentHtmlBlock : parsedHtml.select("div#mangalist > ul.list > li")) {
|
||||||
for (Element currentHtmlBlock : mangaHtmlBlocks) {
|
|
||||||
Manga currentManga = constructPopularMangaFromHtmlBlock(currentHtmlBlock);
|
Manga currentManga = constructPopularMangaFromHtmlBlock(currentHtmlBlock);
|
||||||
mangaList.add(currentManga);
|
mangaList.add(currentManga);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mangaList;
|
return mangaList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Manga constructPopularMangaFromHtmlBlock(Element htmlBlock) {
|
private Manga constructPopularMangaFromHtmlBlock(Element htmlBlock) {
|
||||||
Manga mangaFromHtmlBlock = new Manga();
|
Manga manga = new Manga();
|
||||||
mangaFromHtmlBlock.source = getId();
|
manga.source = getId();
|
||||||
|
|
||||||
Element urlElement = htmlBlock.select("a.title").first();
|
|
||||||
|
|
||||||
|
Element urlElement = Parser.element(htmlBlock, "a.title");
|
||||||
if (urlElement != null) {
|
if (urlElement != null) {
|
||||||
mangaFromHtmlBlock.setUrl(urlElement.attr("href"));
|
manga.setUrl(urlElement.attr("href"));
|
||||||
mangaFromHtmlBlock.title = urlElement.text();
|
manga.title = urlElement.text();
|
||||||
}
|
}
|
||||||
|
return manga;
|
||||||
return mangaFromHtmlBlock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String parseNextPopularMangasUrl(Document parsedHtml, MangasPage page) {
|
protected String parseNextPopularMangasUrl(Document parsedHtml, MangasPage page) {
|
||||||
Element next = parsedHtml.select("a:has(span.next)").first();
|
Element next = Parser.element(parsedHtml, "a:has(span.next)");
|
||||||
if (next == null)
|
return next != null ? String.format(POPULAR_MANGAS_URL, next.attr("href")) : null;
|
||||||
return null;
|
|
||||||
|
|
||||||
return String.format(POPULAR_MANGAS_URL, next.attr("href"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<Manga> parseSearchFromHtml(Document parsedHtml) {
|
protected List<Manga> parseSearchFromHtml(Document parsedHtml) {
|
||||||
List<Manga> mangaList = new ArrayList<>();
|
List<Manga> mangaList = new ArrayList<>();
|
||||||
|
|
||||||
Elements mangaHtmlBlocks = parsedHtml.select("table#listing > tbody > tr:gt(0)");
|
for (Element currentHtmlBlock : parsedHtml.select("table#listing > tbody > tr:gt(0)")) {
|
||||||
for (Element currentHtmlBlock : mangaHtmlBlocks) {
|
|
||||||
Manga currentManga = constructSearchMangaFromHtmlBlock(currentHtmlBlock);
|
Manga currentManga = constructSearchMangaFromHtmlBlock(currentHtmlBlock);
|
||||||
mangaList.add(currentManga);
|
mangaList.add(currentManga);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mangaList;
|
return mangaList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,23 +104,18 @@ public class Mangafox extends Source {
|
|||||||
Manga mangaFromHtmlBlock = new Manga();
|
Manga mangaFromHtmlBlock = new Manga();
|
||||||
mangaFromHtmlBlock.source = getId();
|
mangaFromHtmlBlock.source = getId();
|
||||||
|
|
||||||
Element urlElement = htmlBlock.select("a.series_preview").first();
|
Element urlElement = Parser.element(htmlBlock, "a.series_preview");
|
||||||
|
|
||||||
if (urlElement != null) {
|
if (urlElement != null) {
|
||||||
mangaFromHtmlBlock.setUrl(urlElement.attr("href"));
|
mangaFromHtmlBlock.setUrl(urlElement.attr("href"));
|
||||||
mangaFromHtmlBlock.title = urlElement.text();
|
mangaFromHtmlBlock.title = urlElement.text();
|
||||||
}
|
}
|
||||||
|
|
||||||
return mangaFromHtmlBlock;
|
return mangaFromHtmlBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String parseNextSearchUrl(Document parsedHtml, MangasPage page, String query) {
|
protected String parseNextSearchUrl(Document parsedHtml, MangasPage page, String query) {
|
||||||
Element next = parsedHtml.select("a:has(span.next)").first();
|
Element next = Parser.element(parsedHtml, "a:has(span.next)");
|
||||||
if (next == null)
|
return next != null ? BASE_URL + next.attr("href") : null;
|
||||||
return null;
|
|
||||||
|
|
||||||
return BASE_URL + next.attr("href");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -141,84 +123,60 @@ public class Mangafox extends Source {
|
|||||||
Document parsedDocument = Jsoup.parse(unparsedHtml);
|
Document parsedDocument = Jsoup.parse(unparsedHtml);
|
||||||
|
|
||||||
Element infoElement = parsedDocument.select("div#title").first();
|
Element infoElement = parsedDocument.select("div#title").first();
|
||||||
Element titleElement = infoElement.select("h2 > a").first();
|
|
||||||
Element rowElement = infoElement.select("table > tbody > tr:eq(1)").first();
|
Element rowElement = infoElement.select("table > tbody > tr:eq(1)").first();
|
||||||
Element authorElement = rowElement.select("td:eq(1)").first();
|
Element sideInfoElement = parsedDocument.select("#series_info").first();
|
||||||
Element artistElement = rowElement.select("td:eq(2)").first();
|
|
||||||
Element genreElement = rowElement.select("td:eq(3)").first();
|
|
||||||
Element descriptionElement = infoElement.select("p.summary").first();
|
|
||||||
Element thumbnailUrlElement = parsedDocument.select("div.cover > img").first();
|
|
||||||
|
|
||||||
Manga newManga = new Manga();
|
Manga manga = Manga.create(mangaUrl);
|
||||||
newManga.url = mangaUrl;
|
manga.author = Parser.text(rowElement, "td:eq(1)");
|
||||||
|
manga.artist = Parser.text(rowElement, "td:eq(2)");
|
||||||
|
manga.description = Parser.text(infoElement, "p.summary");
|
||||||
|
manga.genre = Parser.text(rowElement, "td:eq(3)");
|
||||||
|
manga.thumbnail_url = Parser.src(sideInfoElement, "div.cover > img");
|
||||||
|
manga.status = parseStatus(Parser.text(sideInfoElement, ".data"));
|
||||||
|
|
||||||
if (titleElement != null) {
|
manga.initialized = true;
|
||||||
String title = titleElement.text();
|
return manga;
|
||||||
// Strip the last word
|
}
|
||||||
title = title.substring(0, title.lastIndexOf(" "));
|
|
||||||
newManga.title = title;
|
|
||||||
}
|
|
||||||
if (artistElement != null) {
|
|
||||||
newManga.artist = artistElement.text();
|
|
||||||
}
|
|
||||||
if (authorElement != null) {
|
|
||||||
newManga.author = authorElement.text();
|
|
||||||
}
|
|
||||||
if (descriptionElement != null) {
|
|
||||||
newManga.description = descriptionElement.text();
|
|
||||||
}
|
|
||||||
if (genreElement != null) {
|
|
||||||
newManga.genre = genreElement.text();
|
|
||||||
}
|
|
||||||
if (thumbnailUrlElement != null) {
|
|
||||||
newManga.thumbnail_url = thumbnailUrlElement.attr("src");
|
|
||||||
}
|
|
||||||
// if (statusElement != null) {
|
|
||||||
// boolean fieldCompleted = statusElement.text().contains("Completed");
|
|
||||||
// newManga.status = fieldCompleted + "";
|
|
||||||
// }
|
|
||||||
|
|
||||||
newManga.initialized = true;
|
private int parseStatus(String status) {
|
||||||
|
if (status.contains("Ongoing")) {
|
||||||
return newManga;
|
return Manga.ONGOING;
|
||||||
|
}
|
||||||
|
if (status.contains("Completed")) {
|
||||||
|
return Manga.COMPLETED;
|
||||||
|
}
|
||||||
|
return Manga.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<Chapter> parseHtmlToChapters(String unparsedHtml) {
|
protected List<Chapter> parseHtmlToChapters(String unparsedHtml) {
|
||||||
Document parsedDocument = Jsoup.parse(unparsedHtml);
|
Document parsedDocument = Jsoup.parse(unparsedHtml);
|
||||||
|
|
||||||
List<Chapter> chapterList = new ArrayList<Chapter>();
|
List<Chapter> chapterList = new ArrayList<>();
|
||||||
|
|
||||||
Elements chapterElements = parsedDocument.select("div#chapters li div");
|
for (Element chapterElement : parsedDocument.select("div#chapters li div")) {
|
||||||
for (Element chapterElement : chapterElements) {
|
|
||||||
Chapter currentChapter = constructChapterFromHtmlBlock(chapterElement);
|
Chapter currentChapter = constructChapterFromHtmlBlock(chapterElement);
|
||||||
|
|
||||||
chapterList.add(currentChapter);
|
chapterList.add(currentChapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
return chapterList;
|
return chapterList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Chapter constructChapterFromHtmlBlock(Element chapterElement) {
|
private Chapter constructChapterFromHtmlBlock(Element chapterElement) {
|
||||||
Chapter newChapter = Chapter.create();
|
Chapter chapter = Chapter.create();
|
||||||
|
|
||||||
Element urlElement = chapterElement.select("a.tips").first();
|
Element urlElement = chapterElement.select("a.tips").first();
|
||||||
Element nameElement = chapterElement.select("a.tips").first();
|
|
||||||
Element dateElement = chapterElement.select("span.date").first();
|
Element dateElement = chapterElement.select("span.date").first();
|
||||||
|
|
||||||
if (urlElement != null) {
|
if (urlElement != null) {
|
||||||
newChapter.setUrl(urlElement.attr("href"));
|
chapter.setUrl(urlElement.attr("href"));
|
||||||
}
|
chapter.name = urlElement.text();
|
||||||
if (nameElement != null) {
|
|
||||||
newChapter.name = nameElement.text();
|
|
||||||
}
|
}
|
||||||
if (dateElement != null) {
|
if (dateElement != null) {
|
||||||
newChapter.date_upload = parseUpdateFromElement(dateElement);
|
chapter.date_upload = parseUpdateFromElement(dateElement);
|
||||||
}
|
}
|
||||||
|
chapter.date_fetch = new Date().getTime();
|
||||||
|
|
||||||
newChapter.date_fetch = new Date().getTime();
|
return chapter;
|
||||||
|
|
||||||
return newChapter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private long parseUpdateFromElement(Element updateElement) {
|
private long parseUpdateFromElement(Element updateElement) {
|
||||||
|
@ -21,7 +21,7 @@ import eu.kanade.mangafeed.data.database.models.Manga;
|
|||||||
import eu.kanade.mangafeed.data.source.SourceManager;
|
import eu.kanade.mangafeed.data.source.SourceManager;
|
||||||
import eu.kanade.mangafeed.data.source.base.Source;
|
import eu.kanade.mangafeed.data.source.base.Source;
|
||||||
import eu.kanade.mangafeed.data.source.model.MangasPage;
|
import eu.kanade.mangafeed.data.source.model.MangasPage;
|
||||||
import rx.Observable;
|
import eu.kanade.mangafeed.util.Parser;
|
||||||
|
|
||||||
public class Mangahere extends Source {
|
public class Mangahere extends Source {
|
||||||
|
|
||||||
@ -49,11 +49,6 @@ public class Mangahere extends Source {
|
|||||||
return BASE_URL;
|
return BASE_URL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLoginRequired() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getInitialPopularMangasUrl() {
|
protected String getInitialPopularMangasUrl() {
|
||||||
return String.format(POPULAR_MANGAS_URL, "");
|
return String.format(POPULAR_MANGAS_URL, "");
|
||||||
@ -64,78 +59,33 @@ public class Mangahere extends Source {
|
|||||||
return String.format(SEARCH_URL, Uri.encode(query), 1);
|
return String.format(SEARCH_URL, Uri.encode(query), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Observable<List<String>> getGenres() {
|
|
||||||
List<String> genres = new ArrayList<>(30);
|
|
||||||
|
|
||||||
genres.add("Action");
|
|
||||||
genres.add("Adventure");
|
|
||||||
genres.add("Comedy");
|
|
||||||
genres.add("Drama");
|
|
||||||
genres.add("Ecchi");
|
|
||||||
genres.add("Fantasy");
|
|
||||||
genres.add("Gender Bender");
|
|
||||||
genres.add("Harem");
|
|
||||||
genres.add("Historical");
|
|
||||||
genres.add("Horror");
|
|
||||||
genres.add("Josei");
|
|
||||||
genres.add("Martial Arts");
|
|
||||||
genres.add("Mature");
|
|
||||||
genres.add("Mecha");
|
|
||||||
genres.add("Mystery");
|
|
||||||
genres.add("One Shot");
|
|
||||||
genres.add("Psychological");
|
|
||||||
genres.add("Romance");
|
|
||||||
genres.add("School Life");
|
|
||||||
genres.add("Sci-fi");
|
|
||||||
genres.add("Seinen");
|
|
||||||
genres.add("Shoujo");
|
|
||||||
genres.add("Shoujo Ai");
|
|
||||||
genres.add("Shounen");
|
|
||||||
genres.add("Shounen Ai");
|
|
||||||
genres.add("Slice of Life");
|
|
||||||
genres.add("Sports");
|
|
||||||
genres.add("Supernatural");
|
|
||||||
genres.add("Tragedy");
|
|
||||||
genres.add("Yaoi");
|
|
||||||
genres.add("Yuri");
|
|
||||||
|
|
||||||
return Observable.just(genres);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Manga> parsePopularMangasFromHtml(Document parsedHtml) {
|
public List<Manga> parsePopularMangasFromHtml(Document parsedHtml) {
|
||||||
List<Manga> mangaList = new ArrayList<>();
|
List<Manga> mangaList = new ArrayList<>();
|
||||||
|
|
||||||
Elements mangaHtmlBlocks = parsedHtml.select("div.directory_list > ul > li");
|
for (Element currentHtmlBlock : parsedHtml.select("div.directory_list > ul > li")) {
|
||||||
for (Element currentHtmlBlock : mangaHtmlBlocks) {
|
|
||||||
Manga currentManga = constructPopularMangaFromHtmlBlock(currentHtmlBlock);
|
Manga currentManga = constructPopularMangaFromHtmlBlock(currentHtmlBlock);
|
||||||
mangaList.add(currentManga);
|
mangaList.add(currentManga);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mangaList;
|
return mangaList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Manga constructPopularMangaFromHtmlBlock(Element htmlBlock) {
|
private Manga constructPopularMangaFromHtmlBlock(Element htmlBlock) {
|
||||||
Manga mangaFromHtmlBlock = new Manga();
|
Manga manga = new Manga();
|
||||||
mangaFromHtmlBlock.source = getId();
|
manga.source = getId();
|
||||||
|
|
||||||
Element urlElement = htmlBlock.select("div.title > a").first();
|
|
||||||
|
|
||||||
|
Element urlElement = Parser.element(htmlBlock, "div.title > a");
|
||||||
if (urlElement != null) {
|
if (urlElement != null) {
|
||||||
mangaFromHtmlBlock.setUrl(urlElement.attr("href"));
|
manga.setUrl(urlElement.attr("href"));
|
||||||
mangaFromHtmlBlock.title = urlElement.attr("title");
|
manga.title = urlElement.attr("title");
|
||||||
}
|
}
|
||||||
|
return manga;
|
||||||
return mangaFromHtmlBlock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String parseNextPopularMangasUrl(Document parsedHtml, MangasPage page) {
|
protected String parseNextPopularMangasUrl(Document parsedHtml, MangasPage page) {
|
||||||
Element next = parsedHtml.select("div.next-page > a.next").first();
|
Element next = Parser.element(parsedHtml, "div.next-page > a.next");
|
||||||
if (next == null)
|
return next != null ? String.format(POPULAR_MANGAS_URL, next.attr("href")) : null;
|
||||||
return null;
|
|
||||||
|
|
||||||
return String.format(POPULAR_MANGAS_URL, next.attr("href"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -147,31 +97,25 @@ public class Mangahere extends Source {
|
|||||||
Manga currentManga = constructSearchMangaFromHtmlBlock(currentHtmlBlock);
|
Manga currentManga = constructSearchMangaFromHtmlBlock(currentHtmlBlock);
|
||||||
mangaList.add(currentManga);
|
mangaList.add(currentManga);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mangaList;
|
return mangaList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Manga constructSearchMangaFromHtmlBlock(Element htmlBlock) {
|
private Manga constructSearchMangaFromHtmlBlock(Element htmlBlock) {
|
||||||
Manga mangaFromHtmlBlock = new Manga();
|
Manga manga = new Manga();
|
||||||
mangaFromHtmlBlock.source = getId();
|
manga.source = getId();
|
||||||
|
|
||||||
Element urlElement = htmlBlock.select("a.manga_info").first();
|
|
||||||
|
|
||||||
|
Element urlElement = Parser.element(htmlBlock, "a.manga_info");
|
||||||
if (urlElement != null) {
|
if (urlElement != null) {
|
||||||
mangaFromHtmlBlock.setUrl(urlElement.attr("href"));
|
manga.setUrl(urlElement.attr("href"));
|
||||||
mangaFromHtmlBlock.title = urlElement.text();
|
manga.title = urlElement.text();
|
||||||
}
|
}
|
||||||
|
return manga;
|
||||||
return mangaFromHtmlBlock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String parseNextSearchUrl(Document parsedHtml, MangasPage page, String query) {
|
protected String parseNextSearchUrl(Document parsedHtml, MangasPage page, String query) {
|
||||||
Element next = parsedHtml.select("div.next-page > a.next").first();
|
Element next = Parser.element(parsedHtml, "div.next-page > a.next");
|
||||||
if (next == null)
|
return next != null ? BASE_URL + next.attr("href") : null;
|
||||||
return null;
|
|
||||||
|
|
||||||
return BASE_URL + next.attr("href");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private long parseUpdateFromElement(Element updateElement) {
|
private long parseUpdateFromElement(Element updateElement) {
|
||||||
@ -223,49 +167,41 @@ public class Mangahere extends Source {
|
|||||||
String trimmedHtml = unparsedHtml.substring(beginIndex, endIndex);
|
String trimmedHtml = unparsedHtml.substring(beginIndex, endIndex);
|
||||||
|
|
||||||
Document parsedDocument = Jsoup.parse(trimmedHtml);
|
Document parsedDocument = Jsoup.parse(trimmedHtml);
|
||||||
|
Element detailElement = parsedDocument.select("ul.detail_topText").first();
|
||||||
|
|
||||||
Elements detailElements = parsedDocument.select("ul.detail_topText li");
|
Manga manga = Manga.create(mangaUrl);
|
||||||
|
manga.author = Parser.text(parsedDocument, "a[href^=http://www.mangahere.co/author/]");
|
||||||
|
manga.artist = Parser.text(parsedDocument, "a[href^=http://www.mangahere.co/artist/]");
|
||||||
|
|
||||||
Element artistElement = parsedDocument.select("a[href^=http://www.mangahere.co/artist/]").first();
|
String description = Parser.text(detailElement, "#show");
|
||||||
Element authorElement = parsedDocument.select("a[href^=http://www.mangahere.co/author/]").first();
|
if (description != null) {
|
||||||
Element descriptionElement = detailElements.select("#show").first();
|
manga.description = description.substring(0, description.length() - "Show less".length());
|
||||||
Element genreElement = detailElements.get(3);
|
|
||||||
Element statusElement = detailElements.get(6);
|
|
||||||
|
|
||||||
Manga newManga = new Manga();
|
|
||||||
newManga.url = mangaUrl;
|
|
||||||
|
|
||||||
if (artistElement != null) {
|
|
||||||
newManga.artist = artistElement.text();
|
|
||||||
}
|
}
|
||||||
if (authorElement != null) {
|
String genres = Parser.text(detailElement, "li:eq(3)");
|
||||||
newManga.author = authorElement.text();
|
if (genres != null) {
|
||||||
}
|
manga.genre = genres.substring("Genre(s):".length());
|
||||||
if (descriptionElement != null) {
|
|
||||||
newManga.description = descriptionElement.text().substring(0, descriptionElement.text().length() - "Show less".length());
|
|
||||||
}
|
|
||||||
if (genreElement != null) {
|
|
||||||
newManga.genre = genreElement.text().substring("Genre(s):".length());
|
|
||||||
}
|
|
||||||
if (statusElement != null) {
|
|
||||||
boolean fieldCompleted = statusElement.text().contains("Completed");
|
|
||||||
// TODO fix status
|
|
||||||
// newManga.status = fieldCompleted + "";
|
|
||||||
}
|
}
|
||||||
|
manga.status = parseStatus(Parser.text(detailElement, "li:eq(6)"));
|
||||||
|
|
||||||
beginIndex = unparsedHtml.indexOf("<img");
|
beginIndex = unparsedHtml.indexOf("<img");
|
||||||
endIndex = unparsedHtml.indexOf("/>", beginIndex);
|
endIndex = unparsedHtml.indexOf("/>", beginIndex);
|
||||||
trimmedHtml = unparsedHtml.substring(beginIndex, endIndex + 2);
|
trimmedHtml = unparsedHtml.substring(beginIndex, endIndex + 2);
|
||||||
|
|
||||||
parsedDocument = Jsoup.parse(trimmedHtml);
|
parsedDocument = Jsoup.parse(trimmedHtml);
|
||||||
Element thumbnailUrlElement = parsedDocument.select("img").first();
|
manga.thumbnail_url = Parser.src(parsedDocument, "img");
|
||||||
|
|
||||||
if (thumbnailUrlElement != null) {
|
manga.initialized = true;
|
||||||
newManga.thumbnail_url = thumbnailUrlElement.attr("src");
|
return manga;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int parseStatus(String status) {
|
||||||
|
if (status.contains("Ongoing")) {
|
||||||
|
return Manga.ONGOING;
|
||||||
}
|
}
|
||||||
|
if (status.contains("Completed")) {
|
||||||
newManga.initialized = true;
|
return Manga.COMPLETED;
|
||||||
|
}
|
||||||
return newManga;
|
return Manga.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -276,37 +212,31 @@ public class Mangahere extends Source {
|
|||||||
|
|
||||||
Document parsedDocument = Jsoup.parse(trimmedHtml);
|
Document parsedDocument = Jsoup.parse(trimmedHtml);
|
||||||
|
|
||||||
List<Chapter> chapterList = new ArrayList<Chapter>();
|
List<Chapter> chapterList = new ArrayList<>();
|
||||||
|
|
||||||
Elements chapterElements = parsedDocument.getElementsByTag("li");
|
for (Element chapterElement : parsedDocument.getElementsByTag("li")) {
|
||||||
for (Element chapterElement : chapterElements) {
|
|
||||||
Chapter currentChapter = constructChapterFromHtmlBlock(chapterElement);
|
Chapter currentChapter = constructChapterFromHtmlBlock(chapterElement);
|
||||||
|
|
||||||
chapterList.add(currentChapter);
|
chapterList.add(currentChapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
return chapterList;
|
return chapterList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Chapter constructChapterFromHtmlBlock(Element chapterElement) {
|
private Chapter constructChapterFromHtmlBlock(Element chapterElement) {
|
||||||
Chapter newChapter = Chapter.create();
|
Chapter chapter = Chapter.create();
|
||||||
|
|
||||||
Element urlElement = chapterElement.select("a").first();
|
Element urlElement = chapterElement.select("a").first();
|
||||||
Element nameElement = chapterElement.select("a").first();
|
|
||||||
Element dateElement = chapterElement.select("span.right").first();
|
Element dateElement = chapterElement.select("span.right").first();
|
||||||
|
|
||||||
if (urlElement != null) {
|
if (urlElement != null) {
|
||||||
newChapter.setUrl(urlElement.attr("href"));
|
chapter.setUrl(urlElement.attr("href"));
|
||||||
}
|
chapter.name = urlElement.text();
|
||||||
if (nameElement != null) {
|
|
||||||
newChapter.name = nameElement.text();
|
|
||||||
}
|
}
|
||||||
if (dateElement != null) {
|
if (dateElement != null) {
|
||||||
newChapter.date_upload = parseDateFromElement(dateElement);
|
chapter.date_upload = parseDateFromElement(dateElement);
|
||||||
}
|
}
|
||||||
newChapter.date_fetch = new Date().getTime();
|
chapter.date_fetch = new Date().getTime();
|
||||||
|
|
||||||
return newChapter;
|
return chapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long parseDateFromElement(Element dateElement) {
|
private long parseDateFromElement(Element dateElement) {
|
||||||
@ -348,7 +278,6 @@ public class Mangahere extends Source {
|
|||||||
// Do Nothing.
|
// Do Nothing.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,7 +289,7 @@ public class Mangahere extends Source {
|
|||||||
|
|
||||||
Document parsedDocument = Jsoup.parse(trimmedHtml);
|
Document parsedDocument = Jsoup.parse(trimmedHtml);
|
||||||
|
|
||||||
List<String> pageUrlList = new ArrayList<String>();
|
List<String> pageUrlList = new ArrayList<>();
|
||||||
|
|
||||||
Elements pageUrlElements = parsedDocument.select("select.wid60").first().getElementsByTag("option");
|
Elements pageUrlElements = parsedDocument.select("select.wid60").first().getElementsByTag("option");
|
||||||
for (Element pageUrlElement : pageUrlElements) {
|
for (Element pageUrlElement : pageUrlElements) {
|
||||||
|
@ -69,6 +69,7 @@ public class MyAnimeListPresenter extends BasePresenter<MyAnimeListFragment> {
|
|||||||
for (MangaSync myManga : myList) {
|
for (MangaSync myManga : myList) {
|
||||||
if (myManga.remote_id == mangaSync.remote_id) {
|
if (myManga.remote_id == mangaSync.remote_id) {
|
||||||
mangaSync.copyPersonalFrom(myManga);
|
mangaSync.copyPersonalFrom(myManga);
|
||||||
|
mangaSync.total_chapters = myManga.total_chapters;
|
||||||
return Observable.just(mangaSync);
|
return Observable.just(mangaSync);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
48
app/src/main/java/eu/kanade/mangafeed/util/Parser.java
Normal file
48
app/src/main/java/eu/kanade/mangafeed/util/Parser.java
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package eu.kanade.mangafeed.util;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.jsoup.nodes.Element;
|
||||||
|
import org.jsoup.select.Elements;
|
||||||
|
|
||||||
|
public class Parser {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static Element element(Element container, String pattern) {
|
||||||
|
return container.select(pattern).first();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static String text(Element container, String pattern) {
|
||||||
|
return text(container, pattern, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static String text(Element container, String pattern, String defValue) {
|
||||||
|
Element element = container.select(pattern).first();
|
||||||
|
return element != null ? element.text() : defValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static String allText(Element container, String pattern) {
|
||||||
|
Elements elements = container.select(pattern);
|
||||||
|
return !elements.isEmpty() ? elements.text() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static String attr(Element container, String pattern, String attr) {
|
||||||
|
Element element = container.select(pattern).first();
|
||||||
|
return element != null ? element.attr(attr) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static String href(Element container, String pattern) {
|
||||||
|
return attr(container, pattern, "href");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static String src(Element container, String pattern) {
|
||||||
|
return attr(container, pattern, "src");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user