[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'
pkgNameSuffix = 'ru.comx'
extClass = '.ComX'
extVersionCode = 12
extVersionCode = 13
}
dependencies {

View File

@ -1,9 +1,9 @@
package eu.kanade.tachiyomi.extension.ru.comx
import android.webkit.CookieManager
import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
import eu.kanade.tachiyomi.network.GET
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.MangasPage
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.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.Cookie
import okhttp3.CookieJar
import okhttp3.FormBody
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
@ -42,22 +44,30 @@ class ComX : ParsedHttpSource() {
override val lang = "ru"
override val supportsLatest = true
private val userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:72.0) Gecko/20100101 Firefox/72.0"
private val cookieManager by lazy { CookieManager.getInstance() }
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.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()
override fun headersBuilder(): Headers.Builder = Headers.Builder()
.add("User-Agent", userAgent)
.add("Referer", baseUrl)
.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/78.0")
.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)
@ -69,74 +79,80 @@ class ComX : ParsedHttpSource() {
val mangas = document.select(popularMangaSelector()).map { 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 ->
document.select(selector).first()
} != null
return MangasPage(mangas, hasNextPage)
return MangasPage(mangas, document.select(".pagination__pages span").first().text().toInt() <= document.select(".pagination__pages a:last-child").first().text().toInt())
}
override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create()
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.title = it.text()
}
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 {
val manga = SManga.create()
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.title = it.text()
}
return manga
}
override fun popularMangaNextPageSelector() = ".pnext:last-child"
override fun popularMangaNextPageSelector(): 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 {
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 ->
when (filter) {
is TypeList -> filter.state.forEach { type ->
if (type.state) {
url.addQueryParameter("field[type][${type.id}]", 1.toString())
}
}
is PubList -> filter.state.forEach { publisher ->
if (publisher.state) {
url.addQueryParameter("subCat[]", publisher.id)
}
}
is GenreList -> filter.state.forEach { genre ->
if (genre.state) {
url.addQueryParameter("field[genre][${genre.id}]", 1.toString())
}
}
}
when (filter) {
is TypeList -> filter.state.forEach { type ->
if (type.state) {
url.addQueryParameter("field[type][${type.id}]", 1.toString())
}
}
is PubList -> filter.state.forEach { publisher ->
if (publisher.state) {
url.addQueryParameter("subCat[]", publisher.id)
}
}
is GenreList -> filter.state.forEach { genre ->
if (genre.state) {
url.addQueryParameter("field[genre][${genre.id}]", 1.toString())
}
}
}
}**/
if (query.isNotEmpty()) {
return POST(
"$baseUrl/comix-read/",
"$baseUrl/index.php?do=search&search_start=$page",
body = FormBody.Builder()
.add("do", "search")
.add("story", query)
.add("subaction", "search")
.add("story", query)
.build(),
headers = headers
)
}
return GET(url.toString(), headers)
return GET("$baseUrl/comix-read/", headers)
}
override fun searchMangaSelector() = popularMangaSelector()
@ -144,26 +160,19 @@ class ComX : ParsedHttpSource() {
override fun searchMangaFromElement(element: Element): SManga = popularMangaFromElement(element)
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()
manga.author = infoElement.select(".fullstory__infoSection:eq(1) > .fullstory__infoSectionContent").text()
manga.genre = infoElement.select(".fullstory__infoSection:eq(2) > .fullstory__infoSectionContent").text()
.split(",").plusElement("Комикс").joinToString { it.trim() }
manga.author = infoElement.select(".page__list li:eq(1)").text()
manga.genre = infoElement.select(".page__tags a").joinToString { it.text() }
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()
if (!text.contains("Добавить описание на комикс")) {
val fromRemove = "Отслеживать"
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
val src = infoElement.select(".img-wide img").attr("src")
if (src.contains(baseUrl.substringAfter("://"))) {
manga.thumbnail_url = "http:" + src
} else {
manga.thumbnail_url = baseUrl + src
}
@ -172,7 +181,8 @@ class ComX : ParsedHttpSource() {
private fun parseStatus(element: String): Int = when {
element.contains("Продолжается") ||
element.contains(" из ") -> SManga.ONGOING
element.contains(" из ") ||
element.contains("Онгоинг") -> SManga.ONGOING
element.contains("Заверш") ||
element.contains("Лимитка") ||
element.contains("Ван шот") ||
@ -184,8 +194,8 @@ class ComX : ParsedHttpSource() {
override fun chapterListSelector() = throw NotImplementedError("Unused")
override fun chapterListParse(response: Response): List<SChapter> {
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
.toString()
.substringAfter("window.__DATA__ = ")
@ -248,7 +258,7 @@ class ComX : ParsedHttpSource() {
override fun imageRequest(page: Page): Request {
return GET(page.imageUrl!!, headers)
}
/**
private class CheckFilter(name: String, val id: String) : Filter.CheckBox(name)
private class TypeList(types: List<CheckFilter>) : Filter.Group<CheckFilter>("Тип выпуска", types)
@ -256,95 +266,95 @@ class ComX : ParsedHttpSource() {
private class GenreList(genres: List<CheckFilter>) : Filter.Group<CheckFilter>("Жанры", genres)
override fun getFilterList() = FilterList(
TypeList(getTypeList()),
PubList(getPubList()),
GenreList(getGenreList()),
TypeList(getTypeList()),
PubList(getPubList()),
GenreList(getGenreList()),
)
private fun getTypeList() = listOf(
CheckFilter("Лимитка", "1"),
CheckFilter("Ван шот", "2"),
CheckFilter("Графический Роман", "3"),
CheckFilter("Онгоинг", "4"),
CheckFilter("Лимитка", "1"),
CheckFilter("Ван шот", "2"),
CheckFilter("Графический Роман", "3"),
CheckFilter("Онгоинг", "4"),
)
private fun getPubList() = listOf(
CheckFilter("Marvel", "2"),
CheckFilter("DC Comics", "14"),
CheckFilter("Dark Horse", "7"),
CheckFilter("IDW Publishing", "6"),
CheckFilter("Image", "4"),
CheckFilter("Vertigo", "8"),
CheckFilter("Dynamite Entertainment", "10"),
CheckFilter("Wildstorm", "5"),
CheckFilter("Avatar Press", "11"),
CheckFilter("Boom! Studios", "12"),
CheckFilter("Top Cow", "9"),
CheckFilter("Oni Press", "13"),
CheckFilter("Valiant", "15"),
CheckFilter("Icon Comics", "16"),
CheckFilter("Manga", "3"),
CheckFilter("Manhua", "45"),
CheckFilter("Manhwa", "44"),
CheckFilter("Разные комиксы", "18")
CheckFilter("Marvel", "2"),
CheckFilter("DC Comics", "14"),
CheckFilter("Dark Horse", "7"),
CheckFilter("IDW Publishing", "6"),
CheckFilter("Image", "4"),
CheckFilter("Vertigo", "8"),
CheckFilter("Dynamite Entertainment", "10"),
CheckFilter("Wildstorm", "5"),
CheckFilter("Avatar Press", "11"),
CheckFilter("Boom! Studios", "12"),
CheckFilter("Top Cow", "9"),
CheckFilter("Oni Press", "13"),
CheckFilter("Valiant", "15"),
CheckFilter("Icon Comics", "16"),
CheckFilter("Manga", "3"),
CheckFilter("Manhua", "45"),
CheckFilter("Manhwa", "44"),
CheckFilter("Разные комиксы", "18")
)
private fun getGenreList() = listOf(
CheckFilter("Sci-Fi", "2"),
CheckFilter("Антиутопия", "3"),
CheckFilter("Апокалипсис", "4"),
CheckFilter("Боевик", "5"),
CheckFilter("Боевые искусства", "6"),
CheckFilter("Вампиры", "7"),
CheckFilter("Вестерн", "8"),
CheckFilter("Военный", "9"),
CheckFilter("Детектив", "10"),
CheckFilter("Драма", "11"),
CheckFilter("Зомби", "12"),
CheckFilter("Игры", "13"),
CheckFilter("Исекай", "14"),
CheckFilter("Исторический", "15"),
CheckFilter("Киберпанк", "16"),
CheckFilter("Комедия", "17"),
CheckFilter("Космоопера", "18"),
CheckFilter("Космос", "19"),
CheckFilter("Криминал", "20"),
CheckFilter("МелоДрама", "21"),
CheckFilter("Мистика", "22"),
CheckFilter("Научная Фантастика", "23"),
CheckFilter("Неотвратимость", "24"),
CheckFilter("Нуар", "25"),
CheckFilter("Паника", "26"),
CheckFilter("Пародия", "27"),
CheckFilter("Повседневность", "28"),
CheckFilter("Постапокалиптика", "29"),
CheckFilter("ПредательСредиНас", "30"),
CheckFilter("Приключения", "31"),
CheckFilter("Путешествия во времени", "32"),
CheckFilter("Сверхъестественное", "33"),
CheckFilter("Слэшер", "34"),
CheckFilter("Смерть", "35"),
CheckFilter("Супергерои", "36"),
CheckFilter("Супергероика", "37"),
CheckFilter("Сёнен", "38"),
CheckFilter("Тревога", "39"),
CheckFilter("Триллер", "40"),
CheckFilter("Ужасы", "41"),
CheckFilter("Фантасмагория", "42"),
CheckFilter("Фантастика", "43"),
CheckFilter("Фэнтези", "44"),
CheckFilter("Экшен", "45"),
CheckFilter("Экшн", "46"),
CheckFilter("Эротика", "47"),
CheckFilter("сэйнэн", "66"),
CheckFilter("сёдзё", "67"),
CheckFilter("сёнэн", "68"),
CheckFilter("сёнэн-ай", "69"),
CheckFilter("трагедия", "70"),
CheckFilter("фэнтези", "73"),
CheckFilter("школа", "74"),
CheckFilter("этти", "76"),
CheckFilter("яой", "77"),
CheckFilter("Sci-Fi", "2"),
CheckFilter("Антиутопия", "3"),
CheckFilter("Апокалипсис", "4"),
CheckFilter("Боевик", "5"),
CheckFilter("Боевые искусства", "6"),
CheckFilter("Вампиры", "7"),
CheckFilter("Вестерн", "8"),
CheckFilter("Военный", "9"),
CheckFilter("Детектив", "10"),
CheckFilter("Драма", "11"),
CheckFilter("Зомби", "12"),
CheckFilter("Игры", "13"),
CheckFilter("Исекай", "14"),
CheckFilter("Исторический", "15"),
CheckFilter("Киберпанк", "16"),
CheckFilter("Комедия", "17"),
CheckFilter("Космоопера", "18"),
CheckFilter("Космос", "19"),
CheckFilter("Криминал", "20"),
CheckFilter("МелоДрама", "21"),
CheckFilter("Мистика", "22"),
CheckFilter("Научная Фантастика", "23"),
CheckFilter("Неотвратимость", "24"),
CheckFilter("Нуар", "25"),
CheckFilter("Паника", "26"),
CheckFilter("Пародия", "27"),
CheckFilter("Повседневность", "28"),
CheckFilter("Постапокалиптика", "29"),
CheckFilter("ПредательСредиНас", "30"),
CheckFilter("Приключения", "31"),
CheckFilter("Путешествия во времени", "32"),
CheckFilter("Сверхъестественное", "33"),
CheckFilter("Слэшер", "34"),
CheckFilter("Смерть", "35"),
CheckFilter("Супергерои", "36"),
CheckFilter("Супергероика", "37"),
CheckFilter("Сёнен", "38"),
CheckFilter("Тревога", "39"),
CheckFilter("Триллер", "40"),
CheckFilter("Ужасы", "41"),
CheckFilter("Фантасмагория", "42"),
CheckFilter("Фантастика", "43"),
CheckFilter("Фэнтези", "44"),
CheckFilter("Экшен", "45"),
CheckFilter("Экшн", "46"),
CheckFilter("Эротика", "47"),
CheckFilter("сэйнэн", "66"),
CheckFilter("сёдзё", "67"),
CheckFilter("сёнэн", "68"),
CheckFilter("сёнэн-ай", "69"),
CheckFilter("трагедия", "70"),
CheckFilter("фэнтези", "73"),
CheckFilter("школа", "74"),
CheckFilter("этти", "76"),
CheckFilter("яой", "77"),
)
)**/
}