GalleryAdults & Fox additions (#6686)
* Expand tag search to 5 pages as 3 are not enough for HentaiFox * Make launchIO protected instead of private * Add Top Rated, Most Faved, Most Fapped, Most Downloaded search * Update versioning * Address comments * Move sidebar categories to a map * Fetch csrf token from tags page * Move launchIO back to private as it is no longer needed * Clean position of csrf functions * Use map with key lookup for popular categories
This commit is contained in:
parent
5588f4d762
commit
003545ac44
|
@ -2,4 +2,4 @@ plugins {
|
|||
id("lib-multisrc")
|
||||
}
|
||||
|
||||
baseVersionCode = 3
|
||||
baseVersionCode = 4
|
||||
|
|
|
@ -814,8 +814,8 @@ abstract class GalleryAdults(
|
|||
val tags = mutableListOf<Genre>()
|
||||
runBlocking {
|
||||
val jobsPool = mutableListOf<Job>()
|
||||
// Get first 3 pages
|
||||
(1..3).forEach { page ->
|
||||
// Get first 5 pages
|
||||
(1..5).forEach { page ->
|
||||
jobsPool.add(
|
||||
launchIO {
|
||||
runCatching {
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
package eu.kanade.tachiyomi.extension.all.hentaifox
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.galleryadults.GalleryAdults
|
||||
import eu.kanade.tachiyomi.multisrc.galleryadults.Genre
|
||||
import eu.kanade.tachiyomi.multisrc.galleryadults.SortOrderFilter
|
||||
import eu.kanade.tachiyomi.multisrc.galleryadults.imgAttr
|
||||
import eu.kanade.tachiyomi.multisrc.galleryadults.toDate
|
||||
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.SManga
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class HentaiFox(
|
||||
|
@ -100,4 +112,103 @@ class HentaiFox(
|
|||
Filter.Header("HINT: Use double quote (\") for exact match"),
|
||||
) + super.getFilterList().list,
|
||||
)
|
||||
|
||||
private val sidebarPath = "includes/sidebar.php"
|
||||
|
||||
private fun sidebarMangaSelector() = "div.item"
|
||||
|
||||
private fun Element.sidebarMangaTitle() =
|
||||
selectFirst("img")?.attr("alt")
|
||||
|
||||
private fun Element.sidebarMangaUrl() =
|
||||
selectFirst("a")?.attr("abs:href")
|
||||
|
||||
private fun Element.sidebarMangaThumbnail() =
|
||||
selectFirst("img")?.imgAttr()
|
||||
|
||||
private var csrfToken: String? = null
|
||||
|
||||
override fun tagsParser(document: Document): List<Genre> {
|
||||
csrfToken = csrfParser(document)
|
||||
return super.tagsParser(document)
|
||||
}
|
||||
|
||||
private fun csrfParser(document: Document): String {
|
||||
return document.select("[name=csrf-token]").attr("content")
|
||||
}
|
||||
|
||||
private fun setSidebarHeaders(csrfToken: String?): Headers {
|
||||
if (csrfToken == null) {
|
||||
return xhrHeaders
|
||||
}
|
||||
return xhrHeaders.newBuilder()
|
||||
.add("X-Csrf-Token", csrfToken)
|
||||
.build()
|
||||
}
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
// Sidebar mangas should always override any other search, so they should appear first
|
||||
// and only propagate to super when a "normal" search is issued
|
||||
val sortOrderFilter = filters.filterIsInstance<SortOrderFilter>().firstOrNull()
|
||||
|
||||
sortOrderFilter?.let {
|
||||
val selectedCategory = sortOrderFilter.values.get(sortOrderFilter.state)
|
||||
if (sidebarCategoriesFilterStateMap.containsKey(selectedCategory)) {
|
||||
return sidebarRequest(
|
||||
sidebarCategoriesFilterStateMap.getValue(selectedCategory),
|
||||
)
|
||||
}
|
||||
}
|
||||
return super.searchMangaRequest(page, query, filters)
|
||||
}
|
||||
|
||||
private fun sidebarRequest(category: String): Request {
|
||||
val url = "$baseUrl/$sidebarPath"
|
||||
return POST(
|
||||
url,
|
||||
setSidebarHeaders(csrfToken),
|
||||
FormBody.Builder()
|
||||
.add("type", category)
|
||||
.build(),
|
||||
)
|
||||
}
|
||||
|
||||
override fun searchMangaParse(response: Response): MangasPage {
|
||||
if (response.request.url.encodedPath.endsWith(sidebarPath)) {
|
||||
val document = response.asJsoup()
|
||||
val mangas = document.select(sidebarMangaSelector())
|
||||
.map {
|
||||
SMangaDto(
|
||||
title = it.sidebarMangaTitle()!!,
|
||||
url = it.sidebarMangaUrl()!!,
|
||||
thumbnail = it.sidebarMangaThumbnail(),
|
||||
lang = LANGUAGE_MULTI,
|
||||
)
|
||||
}
|
||||
.map {
|
||||
SManga.create().apply {
|
||||
title = it.title
|
||||
setUrlWithoutDomain(it.url)
|
||||
thumbnail_url = it.thumbnail
|
||||
}
|
||||
}
|
||||
|
||||
return MangasPage(mangas, false)
|
||||
} else {
|
||||
return super.searchMangaParse(response)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSortOrderURIs(): List<Pair<String, String>> {
|
||||
return super.getSortOrderURIs() + sidebarCategoriesFilterStateMap.toList()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val sidebarCategoriesFilterStateMap = mapOf(
|
||||
"Top Rated" to "top_rated",
|
||||
"Most Faved" to "top_faved",
|
||||
"Most Fapped" to "top_fapped",
|
||||
"Most Downloaded" to "top_downloaded",
|
||||
).withDefault { "top_rated" }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue