Fix missing response at SuperMangas. (#6180)
This commit is contained in:
parent
644e5e556d
commit
4df4d1b562
@ -5,7 +5,7 @@ ext {
|
|||||||
extName = 'Super Mangás'
|
extName = 'Super Mangás'
|
||||||
pkgNameSuffix = 'pt.supermangas'
|
pkgNameSuffix = 'pt.supermangas'
|
||||||
extClass = '.SuperMangasFactory'
|
extClass = '.SuperMangasFactory'
|
||||||
extVersionCode = 6
|
extVersionCode = 7
|
||||||
libVersion = '1.2'
|
libVersion = '1.2'
|
||||||
containsNsfw = true
|
containsNsfw = true
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import com.github.salomonbrys.kotson.obj
|
|||||||
import com.github.salomonbrys.kotson.string
|
import com.github.salomonbrys.kotson.string
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
|
import com.squareup.duktape.Duktape
|
||||||
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.Filter
|
||||||
@ -21,12 +22,15 @@ import eu.kanade.tachiyomi.util.asJsoup
|
|||||||
import okhttp3.FormBody
|
import okhttp3.FormBody
|
||||||
import okhttp3.Headers
|
import okhttp3.Headers
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.Interceptor
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
|
import okhttp3.RequestBody
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import org.jsoup.Jsoup
|
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 java.net.URLEncoder
|
||||||
|
|
||||||
typealias Content = Triple<String, String, String>
|
typealias Content = Triple<String, String, String>
|
||||||
|
|
||||||
@ -40,14 +44,16 @@ abstract class SuperMangasGeneric(
|
|||||||
|
|
||||||
override val supportsLatest = true
|
override val supportsLatest = true
|
||||||
|
|
||||||
override val client: OkHttpClient = network.cloudflareClient
|
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
|
||||||
|
.addInterceptor(::paginatorIntercept)
|
||||||
|
.build()
|
||||||
|
|
||||||
override fun headersBuilder(): Headers.Builder = Headers.Builder()
|
override fun headersBuilder(): Headers.Builder = Headers.Builder()
|
||||||
.add("User-Agent", USER_AGENT)
|
|
||||||
.add("Origin", baseUrl)
|
|
||||||
.add("Referer", baseUrl)
|
|
||||||
.add("Accept", ACCEPT_COMMON)
|
.add("Accept", ACCEPT_COMMON)
|
||||||
.add("Accept-Language", ACCEPT_LANGUAGE)
|
.add("Accept-Language", ACCEPT_LANGUAGE)
|
||||||
|
.add("Origin", baseUrl)
|
||||||
|
.add("Referer", baseUrl)
|
||||||
|
.add("User-Agent", USER_AGENT)
|
||||||
|
|
||||||
protected open val defaultFilter = mutableMapOf(
|
protected open val defaultFilter = mutableMapOf(
|
||||||
"filter_display_view" to "lista",
|
"filter_display_view" to "lista",
|
||||||
@ -77,6 +83,7 @@ abstract class SuperMangasGeneric(
|
|||||||
filterGenreDel: List<String> = emptyList(),
|
filterGenreDel: List<String> = emptyList(),
|
||||||
page: Int = 1
|
page: Int = 1
|
||||||
): Request {
|
): Request {
|
||||||
|
|
||||||
val filters = jsonObject(
|
val filters = jsonObject(
|
||||||
"filter_data" to filterData.toUrlQueryParams(),
|
"filter_data" to filterData.toUrlQueryParams(),
|
||||||
"filter_genre_add" to jsonArray(filterGenreAdd),
|
"filter_genre_add" to jsonArray(filterGenreAdd),
|
||||||
@ -95,7 +102,7 @@ abstract class SuperMangasGeneric(
|
|||||||
.add("X-Requested-With", "XMLHttpRequest")
|
.add("X-Requested-With", "XMLHttpRequest")
|
||||||
.add("Content-Type", form.contentType().toString())
|
.add("Content-Type", form.contentType().toString())
|
||||||
.add("Content-Length", form.contentLength().toString())
|
.add("Content-Length", form.contentLength().toString())
|
||||||
.add("Host", "www." + baseUrl.substringAfter("//"))
|
.set("Accept", ACCEPT_JSON)
|
||||||
.set("Referer", "$baseUrl/$typeUrl")
|
.set("Referer", "$baseUrl/$typeUrl")
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
@ -108,6 +115,24 @@ abstract class SuperMangasGeneric(
|
|||||||
setUrlWithoutDomain(element.attr("href"))
|
setUrlWithoutDomain(element.attr("href"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun paginatorTokenRequest(): Request = GET("$baseUrl/$listPath", headers)
|
||||||
|
|
||||||
|
private fun paginatorTokenParse(document: Document): String {
|
||||||
|
val script = document.select("script:containsData(ajaxSetup)").firstOrNull()
|
||||||
|
?: return ""
|
||||||
|
|
||||||
|
val scriptContent = script.data()
|
||||||
|
.substringAfter("eval")
|
||||||
|
.substringBefore("function checkSize")
|
||||||
|
.substringBefore("eval")
|
||||||
|
.substringBeforeLast(")")
|
||||||
|
.replace("return p}", "return p})")
|
||||||
|
|
||||||
|
val unpacked = Duktape.create().evaluate(scriptContent) as String
|
||||||
|
|
||||||
|
return unpacked.substringAfter("TOKEN_CSRF=\"").substringBefore("\";")
|
||||||
|
}
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int): Request = genericPaginatedRequest(listPath, page = page)
|
override fun popularMangaRequest(page: Int): Request = genericPaginatedRequest(listPath, page = page)
|
||||||
|
|
||||||
override fun popularMangaParse(response: Response): MangasPage {
|
override fun popularMangaParse(response: Response): MangasPage {
|
||||||
@ -122,9 +147,12 @@ abstract class SuperMangasGeneric(
|
|||||||
popularMangaFromElement(element)
|
popularMangaFromElement(element)
|
||||||
}
|
}
|
||||||
|
|
||||||
val requestBody = response.request().body() as FormBody
|
val requestBody = response.request().body().bodyToString()
|
||||||
val totalPage = result["total_page"].string.toInt()
|
val totalPage = result["total_page"].string.toInt()
|
||||||
val page = requestBody.value("page").toInt()
|
val page = requestBody
|
||||||
|
.substringAfter("page=")
|
||||||
|
.substringBefore("&")
|
||||||
|
.toInt()
|
||||||
val hasNextPage = page < totalPage
|
val hasNextPage = page < totalPage
|
||||||
|
|
||||||
return MangasPage(mangas, hasNextPage)
|
return MangasPage(mangas, hasNextPage)
|
||||||
@ -311,6 +339,33 @@ abstract class SuperMangasGeneric(
|
|||||||
return GET(page.imageUrl!!, newHeaders)
|
return GET(page.imageUrl!!, newHeaders)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun paginatorIntercept(chain: Interceptor.Chain): Response {
|
||||||
|
if (!chain.request().url().toString().contains("paginator.inc")) {
|
||||||
|
return chain.proceed(chain.request())
|
||||||
|
}
|
||||||
|
|
||||||
|
val csrfTokenRequest = paginatorTokenRequest()
|
||||||
|
val csrfTokenResponse = chain.proceed(csrfTokenRequest)
|
||||||
|
val csrfTokenDocument = csrfTokenResponse.asJsoup()
|
||||||
|
val csrfToken = paginatorTokenParse(csrfTokenDocument)
|
||||||
|
|
||||||
|
val totalPage = csrfTokenDocument.select("select.pageSelect option").last()
|
||||||
|
.attr("value")
|
||||||
|
|
||||||
|
val body = chain.request().body()!!
|
||||||
|
|
||||||
|
val newBody = "token=" + URLEncoder.encode(csrfToken, "utf-8") +
|
||||||
|
"&total_page=" + totalPage + "&" + body.bodyToString()
|
||||||
|
|
||||||
|
val requestBody = RequestBody.create(body.contentType(), newBody)
|
||||||
|
val newRequest = chain.request().newBuilder()
|
||||||
|
.header("Content-Length", newBody.length.toString())
|
||||||
|
.post(requestBody)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
return chain.proceed(newRequest)
|
||||||
|
}
|
||||||
|
|
||||||
protected class Tag(val id: String, name: String) : Filter.TriState(name)
|
protected class Tag(val id: String, name: String) : Filter.TriState(name)
|
||||||
|
|
||||||
protected class ContentFilter(contents: List<Content>) : Filter.Select<String>(
|
protected class ContentFilter(contents: List<Content>) : Filter.Select<String>(
|
||||||
@ -352,25 +407,34 @@ abstract class SuperMangasGeneric(
|
|||||||
else -> SManga.UNKNOWN
|
else -> SManga.UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun Response.asJsonObject(): JsonObject =
|
protected fun Response.asJsonObject(): JsonObject {
|
||||||
JSON_PARSER.parse(body()!!.string().substringAfter("</b>")).obj
|
val body = body()!!.string().substringAfter("</b>")
|
||||||
|
|
||||||
|
if (body.isEmpty()) {
|
||||||
|
throw Exception(BLOCK_MESSAGE)
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSON_PARSER.parse(body).obj
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun RequestBody?.bodyToString(): String {
|
||||||
|
if (this == null) return ""
|
||||||
|
val buffer = okio.Buffer()
|
||||||
|
writeTo(buffer)
|
||||||
|
return buffer.readUtf8()
|
||||||
|
}
|
||||||
|
|
||||||
private fun Map<String, String>.toUrlQueryParams(): String =
|
private fun Map<String, String>.toUrlQueryParams(): String =
|
||||||
map { (k, v) -> "$k=$v" }.joinToString("&")
|
map { (k, v) -> "$k=$v" }.joinToString("&")
|
||||||
|
|
||||||
private fun FormBody.value(name: String): String {
|
|
||||||
return (0 until size())
|
|
||||||
.first { name(it) == name }
|
|
||||||
.let { value(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val ACCEPT_COMMON = "text/html,application/xhtml+xml,application/xml;q=0.9," +
|
private const val ACCEPT_COMMON = "text/html,application/xhtml+xml,application/xml;q=0.9," +
|
||||||
"image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
|
"image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
|
||||||
private const val ACCEPT_JSON = "application/json, text/javascript, */*; q=0.01"
|
private const val ACCEPT_JSON = "application/json, text/javascript, */*; q=0.01"
|
||||||
private const val ACCEPT_LANGUAGE = "pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,es;q=0.6,gl;q=0.5"
|
private const val ACCEPT_LANGUAGE = "pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,es;q=0.6,gl;q=0.5"
|
||||||
private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
|
private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
|
||||||
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36"
|
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"
|
||||||
|
private const val BLOCK_MESSAGE = "O site está bloqueando o Tachiyomi. Tente novamente mais tarde ou migre para outra fonte."
|
||||||
|
|
||||||
private val JSON_PARSER by lazy { JsonParser() }
|
private val JSON_PARSER by lazy { JsonParser() }
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ import org.jsoup.Jsoup
|
|||||||
@Nsfw
|
@Nsfw
|
||||||
class SuperHentais : SuperMangasGeneric(
|
class SuperHentais : SuperMangasGeneric(
|
||||||
"Super Hentais",
|
"Super Hentais",
|
||||||
"https://superhentais.com",
|
"https://www.superhentais.com",
|
||||||
"hentai-manga"
|
"hentai-manga"
|
||||||
) {
|
) {
|
||||||
// Hardcode the id because the language wasn't specific.
|
// Hardcode the id because the language wasn't specific.
|
||||||
|
@ -13,9 +13,9 @@ import okhttp3.Response
|
|||||||
|
|
||||||
class SuperMangas : SuperMangasGeneric(
|
class SuperMangas : SuperMangasGeneric(
|
||||||
"Super Mangás",
|
"Super Mangás",
|
||||||
"https://supermangas.site"
|
"https://www.supermangas.site"
|
||||||
) {
|
) {
|
||||||
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
|
override val client: OkHttpClient = super.client.newBuilder()
|
||||||
.addInterceptor(::tempCoverImageFixIntercept)
|
.addInterceptor(::tempCoverImageFixIntercept)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user