mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-22 23:41:50 +01:00
Merge pull request #201 from na-ji/master
Implement parser for readmanga.today
This commit is contained in:
commit
71783657af
@ -9,6 +9,7 @@ import eu.kanade.tachiyomi.data.source.online.english.Mangahere
|
|||||||
import eu.kanade.tachiyomi.data.source.online.russian.Mangachan;
|
import eu.kanade.tachiyomi.data.source.online.russian.Mangachan;
|
||||||
import eu.kanade.tachiyomi.data.source.online.russian.Mintmanga;
|
import eu.kanade.tachiyomi.data.source.online.russian.Mintmanga;
|
||||||
import eu.kanade.tachiyomi.data.source.online.russian.Readmanga;
|
import eu.kanade.tachiyomi.data.source.online.russian.Readmanga;
|
||||||
|
import eu.kanade.tachiyomi.data.source.online.english.ReadMangaToday
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
open class SourceManager(private val context: Context) {
|
open class SourceManager(private val context: Context) {
|
||||||
@ -22,8 +23,9 @@ open class SourceManager(private val context: Context) {
|
|||||||
val READMANGA = 5
|
val READMANGA = 5
|
||||||
val MINTMANGA = 6
|
val MINTMANGA = 6
|
||||||
val MANGACHAN = 7
|
val MANGACHAN = 7
|
||||||
|
val READMANGATODAY = 8
|
||||||
|
|
||||||
val LAST_SOURCE = 7
|
val LAST_SOURCE = 8
|
||||||
|
|
||||||
init {
|
init {
|
||||||
sourcesMap = createSourcesMap()
|
sourcesMap = createSourcesMap()
|
||||||
@ -41,6 +43,7 @@ open class SourceManager(private val context: Context) {
|
|||||||
READMANGA -> Readmanga(context)
|
READMANGA -> Readmanga(context)
|
||||||
MINTMANGA -> Mintmanga(context)
|
MINTMANGA -> Mintmanga(context)
|
||||||
MANGACHAN -> Mangachan(context)
|
MANGACHAN -> Mangachan(context)
|
||||||
|
READMANGATODAY -> ReadMangaToday(context)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,278 @@
|
|||||||
|
package eu.kanade.tachiyomi.data.source.online.english;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import org.jsoup.Jsoup;
|
||||||
|
import org.jsoup.nodes.Document;
|
||||||
|
import org.jsoup.nodes.Element;
|
||||||
|
import org.jsoup.select.Elements;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Chapter;
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Manga;
|
||||||
|
import eu.kanade.tachiyomi.data.source.Language;
|
||||||
|
import eu.kanade.tachiyomi.data.source.LanguageKt;
|
||||||
|
import eu.kanade.tachiyomi.data.source.base.Source;
|
||||||
|
import eu.kanade.tachiyomi.data.source.model.MangasPage;
|
||||||
|
import eu.kanade.tachiyomi.util.Parser;
|
||||||
|
import okhttp3.Headers;
|
||||||
|
import rx.Observable;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
|
||||||
|
public class ReadMangaToday extends Source {
|
||||||
|
public static final String NAME = "ReadMangaToday";
|
||||||
|
public static final String BASE_URL = "http://www.readmanga.today";
|
||||||
|
public static final String POPULAR_MANGAS_URL = BASE_URL + "/hot-manga/%s";
|
||||||
|
public static final String SEARCH_URL = BASE_URL + "/service/search?q=%s";
|
||||||
|
|
||||||
|
private static JsonParser parser = new JsonParser();
|
||||||
|
private static Gson gson = new Gson();
|
||||||
|
|
||||||
|
public ReadMangaToday(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getBaseUrl() {
|
||||||
|
return BASE_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getInitialPopularMangasUrl() {
|
||||||
|
return String.format(POPULAR_MANGAS_URL, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getInitialSearchUrl(String query) {
|
||||||
|
return String.format(SEARCH_URL, Uri.encode(query), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Language getLang() {
|
||||||
|
return LanguageKt.getEN();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Manga> parsePopularMangasFromHtml(Document parsedHtml) {
|
||||||
|
List<Manga> mangaList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Element currentHtmlBlock : parsedHtml.select("div.hot-manga > div.style-list > div.box")) {
|
||||||
|
Manga currentManga = constructPopularMangaFromHtmlBlock(currentHtmlBlock);
|
||||||
|
mangaList.add(currentManga);
|
||||||
|
}
|
||||||
|
return mangaList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Manga constructPopularMangaFromHtmlBlock(Element htmlBlock) {
|
||||||
|
Manga manga = new Manga();
|
||||||
|
manga.source = getId();
|
||||||
|
|
||||||
|
Element urlElement = Parser.element(htmlBlock, "div.title > h2 > a");
|
||||||
|
if (urlElement != null) {
|
||||||
|
manga.setUrl(urlElement.attr("href"));
|
||||||
|
manga.title = urlElement.attr("title");
|
||||||
|
}
|
||||||
|
return manga;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String parseNextPopularMangasUrl(Document parsedHtml, MangasPage page) {
|
||||||
|
Element next = Parser.element(parsedHtml, "div.hot-manga > ul.pagination > li > a:contains(»)");
|
||||||
|
return next != null ? next.attr("href") : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Observable<MangasPage> searchMangasFromNetwork(MangasPage page, String query) {
|
||||||
|
return networkService
|
||||||
|
.requestBody(searchMangaRequest(page, query), true)
|
||||||
|
.doOnNext(doc -> page.mangas = parseSearchFromJson(doc))
|
||||||
|
.map(response -> page);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Headers.Builder headersBuilder() {
|
||||||
|
return super.headersBuilder().add("X-Requested-With", "XMLHttpRequest");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<Manga> parseSearchFromJson(String unparsedJson) {
|
||||||
|
List<Manga> mangaList = new ArrayList<>();
|
||||||
|
|
||||||
|
JsonArray mangasArray = parser.parse(unparsedJson).getAsJsonArray();
|
||||||
|
|
||||||
|
for (JsonElement mangaElement : mangasArray) {
|
||||||
|
Manga currentManga = constructSearchMangaFromJsonObject(mangaElement.getAsJsonObject());
|
||||||
|
mangaList.add(currentManga);
|
||||||
|
}
|
||||||
|
return mangaList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Manga constructSearchMangaFromJsonObject(JsonObject jsonObject) {
|
||||||
|
Manga manga = new Manga();
|
||||||
|
manga.source = getId();
|
||||||
|
|
||||||
|
manga.setUrl(gson.fromJson(jsonObject.get("url"), String.class));
|
||||||
|
manga.title = gson.fromJson(jsonObject.get("title"), String.class);
|
||||||
|
|
||||||
|
return manga;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<Manga> parseSearchFromHtml(Document parsedHtml) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String parseNextSearchUrl(Document parsedHtml, MangasPage page, String query) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Manga parseHtmlToManga(String mangaUrl, String unparsedHtml) {
|
||||||
|
int beginIndex = unparsedHtml.indexOf("<!-- content start -->");
|
||||||
|
int endIndex = unparsedHtml.indexOf("<!-- /content-end -->", beginIndex);
|
||||||
|
String trimmedHtml = unparsedHtml.substring(beginIndex, endIndex);
|
||||||
|
|
||||||
|
Document parsedDocument = Jsoup.parse(trimmedHtml);
|
||||||
|
Element detailElement = parsedDocument.select("div.movie-meta").first();
|
||||||
|
|
||||||
|
Manga manga = Manga.create(mangaUrl);
|
||||||
|
for (Element castHtmlBlock : parsedDocument.select("div.cast ul.cast-list > li")) {
|
||||||
|
String name = Parser.text(castHtmlBlock, "ul > li > a");
|
||||||
|
String role = Parser.text(castHtmlBlock, "ul > li:eq(1)");
|
||||||
|
if (role.equals("Author")) {
|
||||||
|
manga.author = name;
|
||||||
|
} else if (role.equals("Artist")) {
|
||||||
|
manga.artist = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String description = Parser.text(detailElement, "li.movie-detail");
|
||||||
|
if (description != null) {
|
||||||
|
manga.description = description;
|
||||||
|
}
|
||||||
|
String genres = Parser.text(detailElement, "dl.dl-horizontal > dd:eq(5)");
|
||||||
|
if (genres != null) {
|
||||||
|
manga.genre = genres;
|
||||||
|
}
|
||||||
|
manga.status = parseStatus(Parser.text(detailElement, "dl.dl-horizontal > dd:eq(3)"));
|
||||||
|
manga.thumbnail_url = Parser.src(detailElement, "img.img-responsive");
|
||||||
|
|
||||||
|
manga.initialized = true;
|
||||||
|
return manga;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int parseStatus(String status) {
|
||||||
|
if (status.contains("Ongoing")) {
|
||||||
|
return Manga.ONGOING;
|
||||||
|
} else if (status.contains("Completed")) {
|
||||||
|
return Manga.COMPLETED;
|
||||||
|
}
|
||||||
|
return Manga.UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Chapter> parseHtmlToChapters(String unparsedHtml) {
|
||||||
|
int beginIndex = unparsedHtml.indexOf("<!-- content start -->");
|
||||||
|
int endIndex = unparsedHtml.indexOf("<!-- /content-end -->", beginIndex);
|
||||||
|
String trimmedHtml = unparsedHtml.substring(beginIndex, endIndex);
|
||||||
|
|
||||||
|
Document parsedDocument = Jsoup.parse(trimmedHtml);
|
||||||
|
|
||||||
|
List<Chapter> chapterList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Element chapterElement : parsedDocument.select("ul.chp_lst > li")) {
|
||||||
|
Chapter currentChapter = constructChapterFromHtmlBlock(chapterElement);
|
||||||
|
chapterList.add(currentChapter);
|
||||||
|
}
|
||||||
|
return chapterList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Chapter constructChapterFromHtmlBlock(Element chapterElement) {
|
||||||
|
Chapter chapter = Chapter.create();
|
||||||
|
|
||||||
|
Element urlElement = chapterElement.select("a").first();
|
||||||
|
Element dateElement = chapterElement.select("span.dte").first();
|
||||||
|
|
||||||
|
if (urlElement != null) {
|
||||||
|
chapter.setUrl(urlElement.attr("href"));
|
||||||
|
chapter.name = urlElement.select("span.val").text();
|
||||||
|
}
|
||||||
|
if (dateElement != null) {
|
||||||
|
chapter.date_upload = parseDateFromElement(dateElement);
|
||||||
|
}
|
||||||
|
return chapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long parseDateFromElement(Element dateElement) {
|
||||||
|
String dateAsString = dateElement.text();
|
||||||
|
String[] dateWords = dateAsString.split(" ");
|
||||||
|
|
||||||
|
if (dateWords.length == 3) {
|
||||||
|
int timeAgo = Integer.parseInt(dateWords[0]);
|
||||||
|
Calendar date = Calendar.getInstance();
|
||||||
|
|
||||||
|
if (dateWords[1].contains("Minute")) {
|
||||||
|
date.add(Calendar.MINUTE, - timeAgo);
|
||||||
|
} else if (dateWords[1].contains("Hour")) {
|
||||||
|
date.add(Calendar.HOUR_OF_DAY, - timeAgo);
|
||||||
|
} else if (dateWords[1].contains("Day")) {
|
||||||
|
date.add(Calendar.DAY_OF_YEAR, -timeAgo);
|
||||||
|
} else if (dateWords[1].contains("Week")) {
|
||||||
|
date.add(Calendar.WEEK_OF_YEAR, -timeAgo);
|
||||||
|
} else if (dateWords[1].contains("Month")) {
|
||||||
|
date.add(Calendar.MONTH, -timeAgo);
|
||||||
|
} else if (dateWords[1].contains("Year")) {
|
||||||
|
date.add(Calendar.YEAR, -timeAgo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return date.getTimeInMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> parseHtmlToPageUrls(String unparsedHtml) {
|
||||||
|
int beginIndex = unparsedHtml.indexOf("<!-- content start -->");
|
||||||
|
int endIndex = unparsedHtml.indexOf("<!-- /content-end -->", beginIndex);
|
||||||
|
String trimmedHtml = unparsedHtml.substring(beginIndex, endIndex);
|
||||||
|
|
||||||
|
Document parsedDocument = Jsoup.parse(trimmedHtml);
|
||||||
|
|
||||||
|
List<String> pageUrlList = new ArrayList<>();
|
||||||
|
|
||||||
|
Elements pageUrlElements = parsedDocument.select("ul.list-switcher-2 > li > select.jump-menu").first().getElementsByTag("option");
|
||||||
|
for (Element pageUrlElement : pageUrlElements) {
|
||||||
|
pageUrlList.add(pageUrlElement.attr("value"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return pageUrlList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String parseHtmlToImageUrl(String unparsedHtml) {
|
||||||
|
int beginIndex = unparsedHtml.indexOf("<!-- content start -->");
|
||||||
|
int endIndex = unparsedHtml.indexOf("<!-- /content-end -->", beginIndex);
|
||||||
|
String trimmedHtml = unparsedHtml.substring(beginIndex, endIndex);
|
||||||
|
|
||||||
|
Document parsedDocument = Jsoup.parse(trimmedHtml);
|
||||||
|
|
||||||
|
Element imageElement = Parser.element(parsedDocument, "img.img-responsive-2");
|
||||||
|
|
||||||
|
return imageElement.attr("src");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user