From c87be4188ffe418ce2c460d8bfb00bb3f8feea7f Mon Sep 17 00:00:00 2001 From: Alessandro Jean Date: Mon, 14 Oct 2019 02:00:15 -0300 Subject: [PATCH] Update CentralDeMangas url and refactor the code. (#1644) Update CentralDeMangas url and refactor the code --- src/pt/centraldemangas/build.gradle | 2 +- .../pt/centraldemangas/CentralDeMangas.kt | 174 +++++++++--------- 2 files changed, 90 insertions(+), 86 deletions(-) diff --git a/src/pt/centraldemangas/build.gradle b/src/pt/centraldemangas/build.gradle index 596b8cf59..5604a90d4 100644 --- a/src/pt/centraldemangas/build.gradle +++ b/src/pt/centraldemangas/build.gradle @@ -5,7 +5,7 @@ ext { appName = 'Tachiyomi: Central de Mangás' pkgNameSuffix = 'pt.centraldemangas' extClass = '.CentralDeMangas' - extVersionCode = 1 + extVersionCode = 2 libVersion = '1.2' } diff --git a/src/pt/centraldemangas/src/eu/kanade/tachiyomi/extension/pt/centraldemangas/CentralDeMangas.kt b/src/pt/centraldemangas/src/eu/kanade/tachiyomi/extension/pt/centraldemangas/CentralDeMangas.kt index 958c4db03..1aa5b10cb 100644 --- a/src/pt/centraldemangas/src/eu/kanade/tachiyomi/extension/pt/centraldemangas/CentralDeMangas.kt +++ b/src/pt/centraldemangas/src/eu/kanade/tachiyomi/extension/pt/centraldemangas/CentralDeMangas.kt @@ -2,12 +2,15 @@ package eu.kanade.tachiyomi.extension.pt.centraldemangas import com.github.salomonbrys.kotson.array import com.github.salomonbrys.kotson.get +import com.github.salomonbrys.kotson.string +import com.google.gson.JsonArray import com.google.gson.JsonParser import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.source.model.* import eu.kanade.tachiyomi.source.online.ParsedHttpSource import okhttp3.Headers +import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response import org.jsoup.nodes.Document @@ -22,63 +25,50 @@ class CentralDeMangas : ParsedHttpSource() { override val name = "Central de Mangás" - override val baseUrl = "http://cdmnet.com.br" + override val baseUrl = "http://centraldemangas.online" override val lang = "pt" override val supportsLatest = true // Sometimes the site is very slow. - override val client = - network.client.newBuilder() - .connectTimeout(3, TimeUnit.MINUTES) - .readTimeout(3, TimeUnit.MINUTES) - .writeTimeout(3, TimeUnit.MINUTES) - .build() + override val client: OkHttpClient = + network.client.newBuilder() + .connectTimeout(3, TimeUnit.MINUTES) + .readTimeout(3, TimeUnit.MINUTES) + .writeTimeout(3, TimeUnit.MINUTES) + .build() - private val catalogHeaders = Headers.Builder().apply { - add("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64)") - add("Host", "cdmnet.com.br") - add("Referer", baseUrl) - }.build() + override fun headersBuilder(): Headers.Builder = Headers.Builder() + .add("User-Agent", USER_AGENT) + .add("Origin", baseUrl) + .add("Referer", baseUrl) - override fun popularMangaRequest(page: Int): Request = GET(baseUrl, catalogHeaders) + override fun popularMangaRequest(page: Int): Request = GET(baseUrl, headers) override fun popularMangaSelector(): String = "div.ui.eight.doubling.stackable.cards div.card" - override fun popularMangaFromElement(element: Element): SManga { - val manga = SManga.create() - - manga.thumbnail_url = element.select("div.ui.image a img") - .first()?.attr("src")?.replace("60x80", "150x200") - element.select("div.content a").last().let { - manga.url = it.attr("href") - manga.title = it.text() - } - - return manga + override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply { + title = element.select("div.content a").last().text() + url = element.select("div.content a").last().attr("href") + thumbnail_url = element.select("div.ui.image a img").first()?.attr("src") } - override fun popularMangaNextPageSelector() = null + override fun popularMangaNextPageSelector(): String? = null - override fun latestUpdatesRequest(page: Int): Request = GET(baseUrl, catalogHeaders) + override fun latestUpdatesRequest(page: Int): Request = GET(baseUrl, headers) override fun latestUpdatesSelector() = "div.ui.black.segment div.ui.divided.celled.list div.item" - override fun latestUpdatesFromElement(element: Element): SManga { - val manga = SManga.create() - - manga.thumbnail_url = element.select("div.ui.tiny.bordered.image a img") - .first()?.attr("src")?.replace("60x80", "150x200") - element.select("div.content div.header a.popar").last().let { - manga.url = it.attr("href") - manga.title = it.text() - } - - return manga + override fun latestUpdatesFromElement(element: Element): SManga = SManga.create().apply { + title = element.select("div.content div.header a.popar").last().text() + url = element.select("div.content div.header a.popar").last().attr("href") + thumbnail_url = element.select("div.ui.tiny.bordered.image a img").first() + ?.attr("src") + ?.replace("60x80", "150x200") } - override fun latestUpdatesNextPageSelector() = null + override fun latestUpdatesNextPageSelector(): String? = null override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable { return client.newCall(searchMangaRequest(page, query, filters)) @@ -88,48 +78,46 @@ class CentralDeMangas : ParsedHttpSource() { } } - override fun searchMangaParse(response: Response): MangasPage = searchMangaParse(response, "") + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { + val newHeaders = headers.newBuilder() + .set("X-Requested-With", "XMLHttpRequest") + .build() - private fun searchMangaParse(response: Response, query: String?): MangasPage { - val result = jsonParser.parse(response.body()!!.string()).array + return GET("$baseUrl/api/titulos", newHeaders) + } + + private fun searchMangaParse(response: Response, query: String): MangasPage { + val result = response.asJsonArray() val resultFiltered = result - .filter { it["title"].asString.contains(query ?: "", true) } - .map { - SManga.create().apply { - title = it["title"].asString - url = it["url"].asString - } + .filter { it["title"].string.contains(query, true) } + .map { + SManga.create().apply { + title = it["title"].string + url = it["url"].string + thumbnail_url = getCoverUrl(it["url"].string.substringAfterLast("/")) } + } return MangasPage(resultFiltered, false) } - override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { - return GET("$baseUrl/api/titulos", headers) - } + override fun searchMangaNextPageSelector(): String? = null - override fun searchMangaSelector() = throw Exception("This method should not be called!") - - override fun searchMangaFromElement(element: Element): SManga = throw Exception("This method should not be called!") - - override fun searchMangaNextPageSelector() = "" - - override fun mangaDetailsParse(document: Document): SManga { + override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply { val elementList = document.select("div.ui.black.segment div.ui.relaxed.list").first() - return SManga.create().apply { - author = elementList.select("div.item:eq(3) div.content div.description").text() - artist = elementList.select("div.item:eq(2) div.content div.description").text() - genre = elementList.select("div.item:eq(4) div.content div.description a") - .joinToString { it.text() } + author = elementList.select("div.item:eq(3) div.content div.description").text() + artist = elementList.select("div.item:eq(2) div.content div.description").text() + genre = elementList.select("div.item:eq(4) div.content div.description a") + .joinToString { it.text() } - status = elementList.select("div.item:eq(6) div.content div.description") - .text().orEmpty().let { parseStatus(it) } + status = elementList.select("div.item:eq(6) div.content div.description") + .text().orEmpty().let { parseStatus(it) } - description = elementList.select("div.item:eq(0) div.content div.description").text() - thumbnail_url = elementList.select("div.item:eq(0) div.content div.description img").attr("src") - } + description = elementList.select("div.item:eq(0) div.content div.description").text() + thumbnail_url = elementList.select("div.item:eq(0) div.content div.description img") + .attr("src") } private fun parseStatus(status: String) = when { @@ -140,20 +128,20 @@ class CentralDeMangas : ParsedHttpSource() { override fun chapterListParse(response: Response): List { // Filter only manga chapters. - return super.chapterListParse(response).filter { !it.url.contains("/novel/") } + return super.chapterListParse(response) + .filter { !it.url.contains("/novel/") } } override fun chapterListSelector() = "table.ui.small.compact.very.basic.table tbody tr:not(.active)" - override fun chapterFromElement(element: Element): SChapter { + override fun chapterFromElement(element: Element): SChapter = SChapter.create().apply { val firstColumn = element.select("td:eq(0)") val secondColumn = element.select("td:eq(1)") - return SChapter.create().apply { - url = firstColumn.select("a").first().attr("href") - name = firstColumn.select("a").first().text() - date_upload = secondColumn.select("small").first()?.text()?.let { parseChapterDate(it) } ?: 0 - } + url = firstColumn.select("a").first().attr("href") + name = firstColumn.select("a").first().text() + date_upload = secondColumn.select("small").first()?.text() + ?.let { parseChapterDate(it) } ?: 0 } private fun parseChapterDate(date: String) : Long { @@ -166,32 +154,48 @@ class CentralDeMangas : ParsedHttpSource() { override fun pageListParse(document: Document): List { val script = document.select("script").last().data() - val urlSuffix = script.substringAfter(SCRIPT_URL_BEGIN).substringBefore(SCRIPT_URL_END) - val pages = script.substringAfter(SCRIPT_PAGES_BEGIN).substringBefore(SCRIPT_PAGES_END) - .replace("'", "").split(",") + val urlSuffix = script + .substringAfter(SCRIPT_URL_BEGIN) + .substringBefore(SCRIPT_URL_END) + val pages = script + .substringAfter(SCRIPT_PAGES_BEGIN) + .substringBefore(SCRIPT_PAGES_END) + .replace("'", "") + .split(",") + + val chapterUrl = document.select("meta[property='og:url']").attr("content") return pages - .mapIndexed { i, page -> Page(i, "", "$urlSuffix$page.jpg")} + .mapIndexed { i, page -> Page(i, chapterUrl, "$urlSuffix$page.jpg") } } override fun imageRequest(page: Page): Request { - var imageHeaders = Headers.Builder().apply { - add("Referer", baseUrl) - } + val imageHeaders = Headers.Builder() + .add("Referer", page.url) + .build() - return GET(page.imageUrl!!, imageHeaders.build()) + return GET(page.imageUrl!!, imageHeaders) } override fun imageUrlParse(document: Document) = "" + override fun searchMangaSelector() = throw Exception("This method should not be called!") + + override fun searchMangaFromElement(element: Element): SManga = throw Exception("This method should not be called!") + + private fun getCoverUrl(slug: String): String = "$COVER_CDN/150x200/$slug.jpg" + + private fun Response.asJsonArray(): JsonArray = JSON_PARSER.parse(body()!!.string()).array + companion object { + private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36" + private const val COVER_CDN = "http://capas.centraldemangas.com.br" + private const val SCRIPT_URL_BEGIN = "var urlSulfix = '" private const val SCRIPT_URL_END = "';" private const val SCRIPT_PAGES_BEGIN = "var pages = [" private const val SCRIPT_PAGES_END = ",];" - val jsonParser by lazy { - JsonParser() - } + val JSON_PARSER by lazy { JsonParser() } } }