[RU]ComX new HTML view (#10283)
* [RU]ComX new HTML view * saveFromResponse Cookie * saveFromResponse Cookie 2 * Exception antibot string
This commit is contained in:
parent
8e2aa23cb4
commit
599b2a6c81
|
@ -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 {
|
||||||
|
|
|
@ -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"),
|
||||||
|
|
||||||
)
|
)**/
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue