[RU]ComX new HTML view (#10283)

* [RU]ComX new HTML view

* saveFromResponse Cookie

* saveFromResponse Cookie 2

* Exception antibot string
This commit is contained in:
e-shl 2021-12-30 22:28:28 +05:00 committed by GitHub
parent 8e2aa23cb4
commit 599b2a6c81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 151 additions and 141 deletions

View File

@ -6,7 +6,7 @@ ext {
extName = 'ComX' extName = 'ComX'
pkgNameSuffix = 'ru.comx' pkgNameSuffix = 'ru.comx'
extClass = '.ComX' extClass = '.ComX'
extVersionCode = 12 extVersionCode = 13
} }
dependencies { dependencies {

View File

@ -1,9 +1,9 @@
package eu.kanade.tachiyomi.extension.ru.comx package eu.kanade.tachiyomi.extension.ru.comx
import android.webkit.CookieManager
import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
@ -17,9 +17,11 @@ import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonArray import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.jsonPrimitive
import okhttp3.Cookie
import okhttp3.CookieJar
import okhttp3.FormBody import okhttp3.FormBody
import okhttp3.Headers import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import okhttp3.HttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
@ -42,22 +44,30 @@ class ComX : ParsedHttpSource() {
override val lang = "ru" override val lang = "ru"
override val supportsLatest = true override val supportsLatest = true
private val cookieManager by lazy { CookieManager.getInstance() }
private val userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:72.0) Gecko/20100101 Firefox/72.0"
override val client: OkHttpClient = network.cloudflareClient.newBuilder() override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.connectTimeout(10, TimeUnit.SECONDS) .connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS)
.addNetworkInterceptor(RateLimitInterceptor(3)) .addNetworkInterceptor(RateLimitInterceptor(3))
.cookieJar(object : CookieJar {
override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) =
cookies.filter { it.matches(url) }.forEach {
cookieManager.setCookie(url.toString(), it.toString())
}
override fun loadForRequest(url: HttpUrl) =
cookieManager.getCookie(url.toString())?.split("; ")
?.mapNotNull { Cookie.parse(url, it) } ?: emptyList()
})
.build() .build()
override fun headersBuilder(): Headers.Builder = Headers.Builder() override fun headersBuilder(): Headers.Builder = Headers.Builder()
.add("User-Agent", userAgent) .add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/78.0")
.add("Referer", baseUrl) .add("Referer", baseUrl + "/comix-read/")
override fun popularMangaSelector() = "div.shortstory1" override fun popularMangaSelector() = "div.short"
override fun latestUpdatesSelector() = "ul.last-comix li" override fun latestUpdatesSelector() = "ul#content-load li.latest"
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/comix-read/page/$page/", headers) override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/comix-read/page/$page/", headers)
@ -69,43 +79,49 @@ class ComX : ParsedHttpSource() {
val mangas = document.select(popularMangaSelector()).map { element -> val mangas = document.select(popularMangaSelector()).map { element ->
popularMangaFromElement(element) popularMangaFromElement(element)
} }
if (mangas.isEmpty()) throw UnsupportedOperationException("Error: Open in WebView and solve the Antirobot!") if (document.html().contains("Sorry, your request has been denied.")) throw UnsupportedOperationException("Error: Open in WebView and solve the Antirobot!")
val hasNextPage = popularMangaNextPageSelector().let { selector -> return MangasPage(mangas, document.select(".pagination__pages span").first().text().toInt() <= document.select(".pagination__pages a:last-child").first().text().toInt())
document.select(selector).first()
} != null
return MangasPage(mangas, hasNextPage)
} }
override fun popularMangaFromElement(element: Element): SManga { override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create() val manga = SManga.create()
manga.thumbnail_url = baseUrl + element.select("img").first().attr("src") manga.thumbnail_url = baseUrl + element.select("img").first().attr("src")
element.select("div.info-poster1 a").first().let { element.select(".readed__title a").first().let {
manga.setUrlWithoutDomain(it.attr("href")) manga.setUrlWithoutDomain(it.attr("href"))
manga.title = it.text() manga.title = it.text()
} }
return manga return manga
} }
override fun latestUpdatesParse(response: Response): MangasPage {
val document = response.asJsoup()
val mangas = document.select(latestUpdatesSelector()).map { element ->
latestUpdatesFromElement(element)
}
if (document.html().contains("Sorry, your request has been denied.")) throw UnsupportedOperationException("Error: Open in WebView and solve the Antirobot!")
return MangasPage(mangas, false)
}
override fun latestUpdatesFromElement(element: Element): SManga { override fun latestUpdatesFromElement(element: Element): SManga {
val manga = SManga.create() val manga = SManga.create()
manga.thumbnail_url = baseUrl + element.select("img").first().attr("src") manga.thumbnail_url = baseUrl + element.select("img").first().attr("src")
element.select("a.comix-last-title").first().let { element.select("a.latest__title").first().let {
manga.setUrlWithoutDomain(it.attr("href")) manga.setUrlWithoutDomain(it.attr("href"))
manga.title = it.text() manga.title = it.text()
} }
return manga return manga
} }
override fun popularMangaNextPageSelector() = ".pnext:last-child" override fun popularMangaNextPageSelector(): Nothing? = null
override fun latestUpdatesNextPageSelector(): Nothing? = null override fun latestUpdatesNextPageSelector(): Nothing? = null
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector() override fun searchMangaNextPageSelector(): Nothing? = null
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = "$baseUrl/index.php?do=xsearch&searchCat=comix-read&page=$page".toHttpUrlOrNull()!!.newBuilder() /** val url = "$baseUrl/index.php?do=xsearch&searchCat=comix-read&page=$page".toHttpUrlOrNull()!!.newBuilder()
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter -> (if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
when (filter) { when (filter) {
is TypeList -> filter.state.forEach { type -> is TypeList -> filter.state.forEach { type ->
@ -124,19 +140,19 @@ class ComX : ParsedHttpSource() {
} }
} }
} }
} }**/
if (query.isNotEmpty()) { if (query.isNotEmpty()) {
return POST( return POST(
"$baseUrl/comix-read/", "$baseUrl/index.php?do=search&search_start=$page",
body = FormBody.Builder() body = FormBody.Builder()
.add("do", "search") .add("do", "search")
.add("story", query)
.add("subaction", "search") .add("subaction", "search")
.add("story", query)
.build(), .build(),
headers = headers headers = headers
) )
} }
return GET(url.toString(), headers) return GET("$baseUrl/comix-read/", headers)
} }
override fun searchMangaSelector() = popularMangaSelector() override fun searchMangaSelector() = popularMangaSelector()
@ -144,26 +160,19 @@ class ComX : ParsedHttpSource() {
override fun searchMangaFromElement(element: Element): SManga = popularMangaFromElement(element) override fun searchMangaFromElement(element: Element): SManga = popularMangaFromElement(element)
override fun mangaDetailsParse(document: Document): SManga { override fun mangaDetailsParse(document: Document): SManga {
val infoElement = document.select("div.maincont").first() if (document.html().contains("Sorry, your request has been denied.")) throw UnsupportedOperationException("Error: Open in WebView and solve the Antirobot!")
val infoElement = document.select("div.page__grid").first()
val manga = SManga.create() val manga = SManga.create()
manga.author = infoElement.select(".fullstory__infoSection:eq(1) > .fullstory__infoSectionContent").text() manga.author = infoElement.select(".page__list li:eq(1)").text()
manga.genre = infoElement.select(".fullstory__infoSection:eq(2) > .fullstory__infoSectionContent").text() manga.genre = infoElement.select(".page__tags a").joinToString { it.text() }
.split(",").plusElement("Комикс").joinToString { it.trim() } manga.status = parseStatus(infoElement.select(".page__list li:eq(2)").text())
manga.status = parseStatus(infoElement.select(".fullstory__infoSection:eq(3) > .fullstory__infoSectionContent").text()) manga.description = infoElement.select(".page__text ").text()
val text = infoElement.select("*").text() val src = infoElement.select(".img-wide img").attr("src")
if (!text.contains("Добавить описание на комикс")) { if (src.contains(baseUrl.substringAfter("://"))) {
val fromRemove = "Отслеживать" manga.thumbnail_url = "http:" + src
val toRemove = "Читать комикс"
val desc = text.removeRange(0, text.indexOf(fromRemove) + fromRemove.length)
manga.description = desc.removeRange(desc.indexOf(toRemove) + toRemove.length, desc.length)
}
val src = infoElement.select("img").attr("src")
if (src.contains(baseUrl)) {
manga.thumbnail_url = src
} else { } else {
manga.thumbnail_url = baseUrl + src manga.thumbnail_url = baseUrl + src
} }
@ -172,7 +181,8 @@ class ComX : ParsedHttpSource() {
private fun parseStatus(element: String): Int = when { private fun parseStatus(element: String): Int = when {
element.contains("Продолжается") || element.contains("Продолжается") ||
element.contains(" из ") -> SManga.ONGOING element.contains(" из ") ||
element.contains("Онгоинг") -> SManga.ONGOING
element.contains("Заверш") || element.contains("Заверш") ||
element.contains("Лимитка") || element.contains("Лимитка") ||
element.contains("Ван шот") || element.contains("Ван шот") ||
@ -184,8 +194,8 @@ class ComX : ParsedHttpSource() {
override fun chapterListSelector() = throw NotImplementedError("Unused") override fun chapterListSelector() = throw NotImplementedError("Unused")
override fun chapterListParse(response: Response): List<SChapter> { override fun chapterListParse(response: Response): List<SChapter> {
val document = response.asJsoup() val document = response.asJsoup()
if (document.html().contains("Sorry, your request has been denied.")) throw UnsupportedOperationException("Error: Open in WebView and solve the Antirobot!")
val dataStr = document val dataStr = document
.toString() .toString()
.substringAfter("window.__DATA__ = ") .substringAfter("window.__DATA__ = ")
@ -248,7 +258,7 @@ class ComX : ParsedHttpSource() {
override fun imageRequest(page: Page): Request { override fun imageRequest(page: Page): Request {
return GET(page.imageUrl!!, headers) return GET(page.imageUrl!!, headers)
} }
/**
private class CheckFilter(name: String, val id: String) : Filter.CheckBox(name) private class CheckFilter(name: String, val id: String) : Filter.CheckBox(name)
private class TypeList(types: List<CheckFilter>) : Filter.Group<CheckFilter>("Тип выпуска", types) private class TypeList(types: List<CheckFilter>) : Filter.Group<CheckFilter>("Тип выпуска", types)
@ -346,5 +356,5 @@ class ComX : ParsedHttpSource() {
CheckFilter("этти", "76"), CheckFilter("этти", "76"),
CheckFilter("яой", "77"), CheckFilter("яой", "77"),
) )**/
} }