diff --git a/src/vi/medoctruyentranh/build.gradle b/src/vi/medoctruyentranh/build.gradle index 1742a6a86..931a5206d 100644 --- a/src/vi/medoctruyentranh/build.gradle +++ b/src/vi/medoctruyentranh/build.gradle @@ -5,7 +5,7 @@ ext { appName = 'Tachiyomi: MeDocTruyenTranh' pkgNameSuffix = 'vi.medoctruyentranh' extClass = '.MeDocTruyenTranh' - extVersionCode = 2 + extVersionCode = 3 libVersion = '1.2' } diff --git a/src/vi/medoctruyentranh/src/eu/kanade/tachiyomi/extension/vi/medoctruyentranh/MeDocTruyenTranh.kt b/src/vi/medoctruyentranh/src/eu/kanade/tachiyomi/extension/vi/medoctruyentranh/MeDocTruyenTranh.kt index 95eedd96b..fb88b8837 100644 --- a/src/vi/medoctruyentranh/src/eu/kanade/tachiyomi/extension/vi/medoctruyentranh/MeDocTruyenTranh.kt +++ b/src/vi/medoctruyentranh/src/eu/kanade/tachiyomi/extension/vi/medoctruyentranh/MeDocTruyenTranh.kt @@ -2,14 +2,17 @@ package eu.kanade.tachiyomi.extension.vi.medoctruyentranh import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.source.model.FilterList +import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.ParsedHttpSource +import eu.kanade.tachiyomi.util.asJsoup import java.text.SimpleDateFormat import java.util.Locale import okhttp3.Request import okhttp3.Response +import org.json.JSONArray import org.json.JSONObject import org.jsoup.nodes.Document import org.jsoup.nodes.Element @@ -26,31 +29,58 @@ class MeDocTruyenTranh : ParsedHttpSource() { override val client = network.cloudflareClient - override fun popularMangaSelector() = ".morelistCon a" + override fun popularMangaSelector() = "div.classifyList a" override fun searchMangaSelector() = ".listCon a" override fun popularMangaRequest(page: Int): Request { - return GET("$baseUrl/more/${page + 1}", headers) + return GET("$baseUrl/tim-truyen/toan-bo" + if (page > 1) "/$page" else "", headers) + } + + private inline fun JSONArray.mapJSONArray(transform: (Int, T) -> R): List { + val list = mutableListOf() + for (i in 0 until this.length()) { + list.add(transform(i, this[i] as T)) + } + return list + } + + override fun popularMangaParse(response: Response): MangasPage { + val document = response.asJsoup() + + // trying to build URLs from this JSONObject could cause issues but we need it to get thumbnails + val titleCoverMap = JSONObject(document.select("script#__NEXT_DATA__").first().data()) + .getJSONObject("props") + .getJSONObject("pageProps") + .getJSONObject("initialState") + .getJSONObject("classify") + .getJSONArray("comics") + .mapJSONArray { _, jsonObject: JSONObject -> + Pair(jsonObject.getString("title"), jsonObject.getString("coverimg")) + } + .toMap() + + val mangas = document.select(popularMangaSelector()).map { + popularMangaFromElement(it).apply { + thumbnail_url = titleCoverMap[this.title] + } + } + + return MangasPage(mangas, document.select(popularMangaNextPageSelector()) != null) } override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { return GET("$baseUrl/search/$query", headers) } override fun popularMangaFromElement(element: Element): SManga { - val manga = SManga.create() - val jsonData = element.ownerDocument().select("#__NEXT_DATA__").first()!!.data() - - manga.setUrlWithoutDomain(baseUrl + element.attr("href")) - manga.title = element.attr("title").trim() - - val indexOfManga = jsonData.indexOf(manga.title) - val startIndex = jsonData.indexOf("coverimg", indexOfManga) + 11 - val endIndex = jsonData.indexOf("}", startIndex) - 1 - manga.thumbnail_url = jsonData.substring(startIndex, endIndex) - return manga + return SManga.create().apply { + title = element.select("div.storytitle").text() + setUrlWithoutDomain(element.attr("href")) + } } + override fun popularMangaNextPageSelector() = "div.page_floor a.focus + a + a" + override fun searchMangaFromElement(element: Element): SManga { val manga = SManga.create() val jsonData = element.ownerDocument().select("#__NEXT_DATA__").first()!!.data() @@ -98,32 +128,21 @@ class MeDocTruyenTranh : ParsedHttpSource() { override fun chapterListSelector() = "div.chapters a" override fun chapterListParse(response: Response): List { - val body = response.body()!!.string() - val jsonStringStartIndex = body.indexOf("{\"props\"") - val jsonStringEndIndex = body.indexOf("", jsonStringStartIndex) - val jsonString = body.substring(jsonStringStartIndex, jsonStringEndIndex) - val chapters = mutableListOf() - val jsonData = JSONObject(jsonString) - val chaptersArray = jsonData - .getJSONObject("props") - .getJSONObject("pageProps") - .getJSONObject("initialState") - .getJSONObject("detail") - .getJSONArray("story_chapters") - .getJSONArray(0) - val mangaID = jsonData - .getJSONObject("query") - .getString("story_id") - for (i in 0 until chaptersArray.length()) { - val chapter = SChapter.create() - val chapterJson = chaptersArray.getJSONObject(i) - val chapterIndex = chapterJson.getString("chapter_index") - chapter.setUrlWithoutDomain("$baseUrl/readingPage/$mangaID/$chapterIndex") - chapter.name = chapterJson.getString("title") - chapter.date_upload = parseChapterDate(chapterJson.getString("time")) - chapters.add(chapter) - } - return chapters.asReversed() + return JSONObject(response.asJsoup().select("script#__NEXT_DATA__").first().data()) + .getJSONObject("props") + .getJSONObject("pageProps") + .getJSONObject("initialState") + .getJSONObject("detail") + .getJSONArray("story_chapters") + .getJSONArray(0) + .mapJSONArray { _, jsonObject: JSONObject -> + SChapter.create().apply { + name = jsonObject.getString("title") + setUrlWithoutDomain("${response.request().url()}/${jsonObject.getString("chapter_index")}") + date_upload = parseChapterDate(jsonObject.getString("time")) + } + } + .reversed() } private fun parseChapterDate(date: String): Long { @@ -135,24 +154,19 @@ class MeDocTruyenTranh : ParsedHttpSource() { } override fun pageListParse(document: Document): List { - val pages = mutableListOf() - val jsonData = JSONObject(document.select("#__NEXT_DATA__").first()?.data() ?: "{}") - val pagesArray = jsonData - .getJSONObject("props") - .getJSONObject("pageProps") - .getJSONObject("initialState") - .getJSONObject("read") - .getJSONObject("detail_item") - .getJSONArray("elements") - for (i in 0 until pagesArray.length()) { - pages.add(Page(pages.size, "", pagesArray.getJSONObject(i).getString("content"))) - } - return pages + return JSONObject(document.select("#__NEXT_DATA__").first()?.data() ?: "{}") + .getJSONObject("props") + .getJSONObject("pageProps") + .getJSONObject("initialState") + .getJSONObject("read") + .getJSONObject("detail_item") + .getJSONArray("elements") + .mapJSONArray { i, jsonObject: JSONObject -> + Page(i, "", jsonObject.getString("content")) + } } - override fun imageUrlParse(document: Document) = "" - - override fun popularMangaNextPageSelector(): String? = null + override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("This method should not be called!") override fun latestUpdatesSelector() = throw UnsupportedOperationException("This method should not be called!")