Mangahub (ru): fix popular, latest, pages, author (#2114)

* Mangahub (ru): fix popular, latest, pages, author

* only check form in text/html responses
This commit is contained in:
Vetle Ledaal 2024-03-28 11:21:50 +00:00 committed by Draff
parent 01de950ce9
commit 937843c751
2 changed files with 55 additions and 22 deletions

View File

@ -1,7 +1,8 @@
ext { ext {
extName = 'Mangahub' extName = 'Mangahub'
extClass = '.Mangahub' extClass = '.Mangahub'
extVersionCode = 17 extVersionCode = 18
isNsfw = true
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View File

@ -7,16 +7,16 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import kotlinx.serialization.json.Json import okhttp3.FormBody
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.Headers import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Interceptor
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response
import org.jsoup.Jsoup
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import uy.kohesive.injekt.injectLazy
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
@ -33,9 +33,39 @@ open class Mangahub : ParsedHttpSource() {
override val supportsLatest = true override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient.newBuilder() override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.addInterceptor(::confirmAgeInterceptor)
.rateLimit(2) .rateLimit(2)
.build() .build()
private fun confirmAgeInterceptor(chain: Interceptor.Chain): Response {
val request = chain.request()
val response = chain.proceed(request)
if (request.method != "GET" ||
response.header("Content-Type")?.contains("text/html") != true
) {
return response
}
val document = Jsoup.parse(
response.peekBody(Long.MAX_VALUE).string(),
request.url.toString(),
)
val formElement = document.selectFirst("#confirm_age__token")
?: return response
val formBody = FormBody.Builder()
.addEncoded(formElement.attr("name"), formElement.attr("value"))
.build()
val confirmAgeRequest = request.newBuilder()
.method("POST", formBody)
.build()
return client.newCall(confirmAgeRequest).execute()
}
private val userAgentRandomizer = "${Random.nextInt().absoluteValue}" private val userAgentRandomizer = "${Random.nextInt().absoluteValue}"
override fun headersBuilder() = Headers.Builder().apply { override fun headersBuilder() = Headers.Builder().apply {
@ -43,13 +73,15 @@ open class Mangahub : ParsedHttpSource() {
add("Referer", baseUrl) add("Referer", baseUrl)
} }
private val json: Json by injectLazy() override fun popularMangaRequest(page: Int): Request {
val pageStr = if (page > 1) "?page=$page" else ""
return GET("$baseUrl/explore/sort-is-rating$pageStr", headers)
}
override fun popularMangaRequest(page: Int): Request = override fun latestUpdatesRequest(page: Int): Request {
GET("$baseUrl/explore?filter[sort]=rating&filter[dateStart][left_number]=1900&filter[dateStart][right_number]=2099&page=$page", headers) val pageStr = if (page > 1) "?page=$page" else ""
return GET("$baseUrl/explore/sort-is-update$pageStr", headers)
override fun latestUpdatesRequest(page: Int): Request = }
GET("$baseUrl/explore?filter[sort]=update&filter[dateStart][left_number]=1900&filter[dateStart][right_number]=2099&page=$page", headers)
override fun popularMangaSelector() = "div.comic-grid-col-xl" override fun popularMangaSelector() = "div.comic-grid-col-xl"
@ -71,7 +103,11 @@ open class Mangahub : ParsedHttpSource() {
override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector() override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
return GET("$baseUrl/search/manga?query=$query&sort=rating_short&page=$page") val url = "$baseUrl/search/manga".toHttpUrl().newBuilder().apply {
addQueryParameter("query", query)
if (page > 1) addQueryParameter("page", page.toString())
}
return GET(url.build(), headers)
} }
override fun searchMangaSelector() = popularMangaSelector() override fun searchMangaSelector() = popularMangaSelector()
@ -87,7 +123,7 @@ open class Mangahub : ParsedHttpSource() {
override fun mangaDetailsParse(document: Document): SManga { override fun mangaDetailsParse(document: Document): SManga {
val manga = SManga.create() val manga = SManga.create()
manga.author = document.select("div.detail-attr:contains(Автор) div:gt(0)").text() // TODO: Add "Сценарист" and "Художник" manga.author = document.select(".attr-name:contains(Автор) + .attr-value").text() // TODO: Add "Сценарист" and "Художник"
manga.genre = document.select(".tags a").joinToString { it.text() } manga.genre = document.select(".tags a").joinToString { it.text() }
manga.description = document.select("div.markdown-style").text() manga.description = document.select("div.markdown-style").text()
manga.status = parseStatus(document.select("div.detail-attr:contains(перевод):eq(0)").toString()) manga.status = parseStatus(document.select("div.detail-attr:contains(перевод):eq(0)").toString())
@ -125,14 +161,10 @@ open class Mangahub : ParsedHttpSource() {
} }
override fun pageListParse(document: Document): List<Page> { override fun pageListParse(document: Document): List<Page> {
val chapInfo = document.select("reader") val images = document.select("img.reader-viewer-img")
.attr("data-store") return images.mapIndexed { i, img ->
.replace("&quot;", "\"") val url = img.attr("data-src").let { if (it.startsWith("//")) "https:$it" else it }
.replace("\\/", "/") Page(i, document.location(), url)
val chapter = json.parseToJsonElement(chapInfo).jsonObject
return chapter["scans"]!!.jsonArray.mapIndexed { i, jsonEl ->
Page(i, "", "https:" + jsonEl.jsonObject["src"]!!.jsonPrimitive.content)
} }
} }