Update 'HD' selectors and add blocking message. (#6638)

This commit is contained in:
Alessandro Jean 2021-04-20 17:37:12 -03:00 committed by GitHub
parent 91ad434ffa
commit e297c5fde1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 114 additions and 76 deletions

View File

@ -5,7 +5,7 @@ ext {
extName = 'HQ Dragon'
pkgNameSuffix = 'pt.hqdragon'
extClass = '.HQDragon'
extVersionCode = 3
extVersionCode = 4
libVersion = '1.2'
}

View File

@ -9,13 +9,15 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.FormBody
import okhttp3.Headers
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
import java.util.concurrent.TimeUnit
class HQDragon : ParsedHttpSource() {
@ -29,9 +31,14 @@ class HQDragon : ParsedHttpSource() {
override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.addInterceptor(RateLimitInterceptor(1, 1, TimeUnit.SECONDS))
.addInterceptor(RateLimitInterceptor(1, 2, TimeUnit.SECONDS))
.build()
override fun headersBuilder(): Headers.Builder = Headers.Builder()
.add("Accept", ACCEPT)
.add("Accept-Language", ACCEPT_LANGUAGE)
.add("Referer", "$baseUrl/")
// Popular
// Top 10
@ -39,130 +46,161 @@ class HQDragon : ParsedHttpSource() {
return GET(baseUrl, headers)
}
override fun popularMangaSelector() = "ol.list-unstyled.mb-0 li a"
override fun popularMangaParse(response: Response): MangasPage {
val results = super.popularMangaParse(response)
override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create()
manga.setUrlWithoutDomain(element.attr("href"))
manga.title = element.text()
return manga
if (results.mangas.isEmpty()) {
throw Exception(BLOCK_MESSAGE)
}
override fun popularMangaNextPageSelector() = "Not needed"
return results
}
override fun popularMangaSelector() = "h4:contains(Top 10) + ol.mb-0 li a"
override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply {
title = element.text()
setUrlWithoutDomain(element.attr("href"))
}
override fun popularMangaNextPageSelector(): String? = null
// Latest
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> {
return super.fetchLatestUpdates(page)
.map { results -> results.copy(hasNextPage = page < 5) }
}
override fun latestUpdatesRequest(page: Int): Request {
val body = FormBody.Builder()
val formBody = FormBody.Builder()
.add("pagina", page.toString())
.build()
val headers = headersBuilder()
.add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
.add("Content-Length", formBody.contentLength().toString())
.add("Content-Type", formBody.contentType().toString())
.add("Origin", baseUrl)
.add("X-Requested-With", "XMLHttpRequest")
.set("Accept", "*/*")
.build()
return POST("$baseUrl/assets/php/index_paginar.php", headers, body)
return POST("$baseUrl/assets/php/index_paginar.php", headers, formBody)
}
override fun latestUpdatesSelector() = "body a:has(img)"
override fun latestUpdatesParse(response: Response): MangasPage {
val document = response.asJsoup()
val mangas = mutableListOf<SManga>()
val results = super.latestUpdatesParse(response)
document.select(latestUpdatesSelector())
.forEach { mangas.add(latestUpdatesFromElements(it, it.nextElementSibling())) }
return MangasPage(mangas, document.select("a[href\$=5693-x-force-2018]").isEmpty())
if (results.mangas.isEmpty()) {
throw Exception(BLOCK_MESSAGE)
}
private fun latestUpdatesFromElements(imageElement: Element, titleElement: Element): SManga {
val manga = SManga.create()
manga.thumbnail_url = imageElement.select("img").attr("src")
manga.setUrlWithoutDomain(titleElement.attr("href"))
manga.title = titleElement.ownText()
return manga
return results
}
override fun latestUpdatesFromElement(element: Element): SManga = throw UnsupportedOperationException("Not used")
override fun latestUpdatesSelector() = "a:has(img)"
override fun latestUpdatesNextPageSelector() = "not using"
override fun latestUpdatesFromElement(element: Element): SManga = SManga.create().apply {
val image = element.select("img").first()
title = image.attr("alt")
thumbnail_url = image.attr("abs:src")
setUrlWithoutDomain(element.attr("href"))
}
override fun latestUpdatesNextPageSelector(): String? = null
// Search
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
return GET("$baseUrl/pesquisa?pesquisa=$query", headers)
val url = HttpUrl.parse("$baseUrl/pesquisa")!!.newBuilder()
.addQueryParameter("titulo", query)
return GET(url.toString(), headers)
}
override fun searchMangaSelector() = "div.col-6"
override fun searchMangaParse(response: Response): MangasPage {
val results = super.searchMangaParse(response)
override fun searchMangaFromElement(element: Element): SManga {
val manga = SManga.create()
element.select("a + a").let {
manga.setUrlWithoutDomain(it.attr("href"))
manga.title = it.text()
}
manga.thumbnail_url = element.select("img").attr("abs:src")
return manga
if (results.mangas.isEmpty()) {
throw Exception(BLOCK_MESSAGE)
}
override fun searchMangaNextPageSelector() = "Not needed"
return results
}
override fun searchMangaSelector() = "div.col-sm-6.col-md-3:has(img.img-thumbnail)"
override fun searchMangaFromElement(element: Element): SManga = SManga.create().apply {
val link = element.select("a + a").first()
title = link.text()
thumbnail_url = element.select("img").first().attr("abs:src")
setUrlWithoutDomain(link.attr("href"))
}
override fun searchMangaNextPageSelector(): String? = null
// Manga summary page
override fun mangaDetailsParse(document: Document): SManga {
val infoElement = document.select("div.blog-post div.row").first()
override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply {
val infoElement = document.select("div.blog-post div.row").firstOrNull()
?: throw Exception(BLOCK_MESSAGE)
val manga = SManga.create()
manga.title = infoElement.select("h3").first().text()
manga.author = infoElement.select("p:contains(editora)").first().ownText()
val status = infoElement.select("p:contains(status) span").text()
manga.status = parseStatus(status)
manga.description = infoElement.select("p:contains(sinopse)").first().ownText()
manga.thumbnail_url = infoElement.select("img").attr("abs:src")
return manga
}
private fun parseStatus(status: String?) = when {
status == null -> SManga.UNKNOWN
status.contains("Ativo") -> SManga.ONGOING
status.contains("Completo") -> SManga.COMPLETED
else -> SManga.UNKNOWN
title = infoElement.select("h3").first().text()
author = infoElement.select("p:contains(Editora:)").first().textWithoutLabel()
status = infoElement.select("p:contains(Status:) span").first().text().toStatus()
description = infoElement.select("p:contains(Sinopse:)").first().ownText()
thumbnail_url = infoElement.select("div.col-md-4 .img-fluid").first().attr("src")
}
// Chapters
override fun chapterListSelector() = "tr a"
override fun chapterListSelector() = "table.table tr a"
override fun chapterFromElement(element: Element): SChapter {
val chapter = SChapter.create()
chapter.setUrlWithoutDomain(element.attr("href"))
chapter.name = element.text()
return chapter
override fun chapterFromElement(element: Element): SChapter = SChapter.create().apply {
name = element.text().replace("Ler ", "")
setUrlWithoutDomain(element.attr("href"))
}
// Pages
override fun pageListParse(document: Document): List<Page> {
val pages = mutableListOf<Page>()
document.select("img.img-responsive").forEachIndexed { i, img ->
pages.add(Page(i, "", img.attr("abs:src")))
return document.select("img.img-responsive.img-manga")
.filter { it.attr("src").contains("/leitor/") }
.mapIndexed { i, element ->
Page(i, document.location(), element.absUrl("src"))
}
}
return pages
override fun imageUrlParse(document: Document) = ""
override fun imageRequest(page: Page): Request {
val newHeaders = headersBuilder()
.set("Accept", ACCEPT_IMAGE)
.set("Referer", page.url)
.build()
return GET(page.imageUrl!!, newHeaders)
}
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
private fun Element.textWithoutLabel(): String = text()!!.substringAfter(":").trim()
override fun getFilterList() = FilterList()
private fun String.toStatus(): Int = when {
contains("Ativo") -> SManga.ONGOING
contains("Completo") -> SManga.COMPLETED
else -> SManga.UNKNOWN
}
companion object {
private const val ACCEPT = "text/html,application/xhtml+xml,application/xml;q=0.9," +
"image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
private const val ACCEPT_IMAGE = "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8"
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) " +
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36"
private const val BLOCK_MESSAGE = "O site está bloqueando o Tachiyomi. " +
"Migre para outra fonte caso o problema persistir."
}
}