LeerCapitulo: Add filters (#1679)

* Add filters

* Bump
This commit is contained in:
bapeey 2024-03-04 05:33:33 -05:00 committed by Draff
parent 8e7c8da40e
commit 99f355d65b
3 changed files with 182 additions and 9 deletions

View File

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

View File

@ -4,6 +4,7 @@ import android.util.Base64
import eu.kanade.tachiyomi.lib.synchrony.Deobfuscator import eu.kanade.tachiyomi.lib.synchrony.Deobfuscator
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.interceptor.rateLimitHost import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
@ -52,13 +53,54 @@ class LeerCapitulo : ParsedHttpSource() {
override fun popularMangaNextPageSelector(): String? = null override fun popularMangaNextPageSelector(): String? = null
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = "$baseUrl/search-autocomplete".toHttpUrl().newBuilder() val urlBuilder = baseUrl.toHttpUrl().newBuilder()
.addQueryParameter("term", query)
return GET(url.build(), headers) if (query.isNotBlank()) {
urlBuilder.addPathSegment("search-autocomplete")
urlBuilder.addQueryParameter("term", query)
return GET(urlBuilder.build(), headers)
} else {
for (filter in filters) {
when (filter) {
is GenreFilter -> {
if (filter.state != 0) {
urlBuilder.addPathSegment("genre")
urlBuilder.addPathSegment(filter.toUriPart())
break
}
}
is AlphabeticFilter -> {
if (filter.state != 0) {
urlBuilder.addPathSegment("initial")
urlBuilder.addPathSegment(filter.toUriPart())
break
}
}
is StatusFilter -> {
if (filter.state != 0) {
urlBuilder.addPathSegment("status")
urlBuilder.addPathSegment(filter.toUriPart())
break
}
}
else -> {}
}
}
urlBuilder.addPathSegment("") // Empty path segment to avoid 404
urlBuilder.addQueryParameter("page", page.toString())
}
val url = urlBuilder.build()
if (url.pathSegments.size <= 1) throw Exception("Debe seleccionar un filtro o realizar una búsqueda por texto.")
return GET(url, headers)
} }
override fun searchMangaParse(response: Response): MangasPage { override fun searchMangaParse(response: Response): MangasPage {
if (!response.request.url.pathSegments.contains("search-autocomplete")) {
return super.searchMangaParse(response)
}
val mangas = json.decodeFromString<List<MangaDto>>(response.body.string()).map { val mangas = json.decodeFromString<List<MangaDto>>(response.body.string()).map {
SManga.create().apply { SManga.create().apply {
setUrlWithoutDomain(it.link) setUrlWithoutDomain(it.link)
@ -70,11 +112,25 @@ class LeerCapitulo : ParsedHttpSource() {
return MangasPage(mangas, hasNextPage = false) return MangasPage(mangas, hasNextPage = false)
} }
override fun searchMangaSelector(): String = throw UnsupportedOperationException() override fun searchMangaSelector(): String = "div.cate-manga div.mainpage-manga"
override fun searchMangaFromElement(element: Element): SManga = throw UnsupportedOperationException() override fun searchMangaFromElement(element: Element) = SManga.create().apply {
setUrlWithoutDomain(element.selectFirst("div.media-body a")!!.attr("href"))
title = element.selectFirst("div.media-body a")!!.text()
thumbnail_url = element.selectFirst("img")!!.imgAttr()
}
override fun searchMangaNextPageSelector(): String? = null override fun searchMangaNextPageSelector(): String = "ul.pagination > li.active + li"
override fun getFilterList(): FilterList {
return FilterList(
Filter.Header("Los filtros serán ignorados si se realiza una búsqueda por texto."),
Filter.Header("Los filtros no se pueden combinar entre ellos."),
GenreFilter(),
AlphabeticFilter(),
StatusFilter(),
)
}
override fun latestUpdatesRequest(page: Int): Request = popularMangaRequest(page) override fun latestUpdatesRequest(page: Int): Request = popularMangaRequest(page)
@ -167,10 +223,9 @@ class LeerCapitulo : ParsedHttpSource() {
} }
@Serializable @Serializable
data class MangaDto( class MangaDto(
val label: String, val label: String,
val link: String, val link: String,
val thumbnail: String, val thumbnail: String,
val value: String,
) )
} }

View File

@ -0,0 +1,118 @@
package eu.kanade.tachiyomi.extension.es.leercapitulo
import eu.kanade.tachiyomi.source.model.Filter
class GenreFilter : UriPartFilter(
"Género",
arrayOf(
Pair("<Seleccionar>", ""),
Pair("Acción", "accion"),
Pair("Animación", "animacion"),
Pair("Apocalíptico", "apocaliptico"),
Pair("Artes Marciales", "artes-marciales"),
Pair("Aventura", "aventura"),
Pair("Boys Love", "boys-love"),
Pair("Ciberpunk", "ciberpunk"),
Pair("Ciencia Ficción", "ciencia-ficcion"),
Pair("Comedia", "comedia"),
Pair("Crimen", "crimen"),
Pair("Demonios", "demonios"),
Pair("Deporte", "deporte"),
Pair("Drama", "drama"),
Pair("Ecchi", "ecchi"),
Pair("Extranjero", "extranjero"),
Pair("Familia", "familia"),
Pair("Fantasia", "fantasia"),
Pair("Género Bender", "genero-bender"),
Pair("Girls Love", "girls-love"),
Pair("Gore", "gore"),
Pair("Guerra", "guerra"),
Pair("Harem", "harem"),
Pair("Historia", "historia"),
Pair("Horror", "horror"),
Pair("Magia", "magia"),
Pair("Mecha", "mecha"),
Pair("Militar", "militar"),
Pair("Misterio", "misterio"),
Pair("Musica", "musica"),
Pair("Niños", "ninos"),
Pair("Oeste", "oeste"),
Pair("Parodia", "parodia"),
Pair("Policiaco", "policiaco"),
Pair("Psicológico", "psicologico"),
Pair("Realidad", "realidad"),
Pair("Realidad Virtual", "realidad-virtual"),
Pair("Recuentos de la vida", "recuentos-de-la-vida"),
Pair("Reencarnación", "reencarnacion"),
Pair("Romance", "romance"),
Pair("Samurái", "samurai"),
Pair("Sobrenatural", "sobrenatural"),
Pair("Superpoderes", "superpoderes"),
Pair("Supervivencia", "supervivencia"),
Pair("Telenovela", "telenovela"),
Pair("Thriller", "thriller"),
Pair("Tragedia", "tragedia"),
Pair("Traps", "traps"),
Pair("Vampiros", "vampiros"),
Pair("Vida Escolar", "vida-escolar"),
),
)
class AlphabeticFilter : UriPartFilter(
"Alfabético",
arrayOf(
Pair("<Seleccionar>", ""),
Pair("0", "0"),
Pair("1", "1"),
Pair("2", "2"),
Pair("3", "3"),
Pair("4", "4"),
Pair("5", "5"),
Pair("6", "6"),
Pair("7", "7"),
Pair("8", "8"),
Pair("9", "9"),
Pair("A", "A"),
Pair("B", "B"),
Pair("C", "C"),
Pair("D", "D"),
Pair("E", "E"),
Pair("F", "F"),
Pair("G", "G"),
Pair("H", "H"),
Pair("I", "I"),
Pair("J", "J"),
Pair("K", "K"),
Pair("L", "L"),
Pair("M", "M"),
Pair("N", "N"),
Pair("O", "O"),
Pair("P", "P"),
Pair("Q", "Q"),
Pair("R", "R"),
Pair("S", "S"),
Pair("T", "T"),
Pair("U", "U"),
Pair("V", "V"),
Pair("W", "W"),
Pair("X", "X"),
Pair("Y", "Y"),
Pair("Z", "Z"),
),
)
class StatusFilter : UriPartFilter(
"Estado",
arrayOf(
Pair("<Seleccionar>", ""),
Pair("Completed", "completed"),
Pair("Ongoing", "ongoing"),
Pair("Paused", "paused"),
Pair("Cancelled", "cancelled"),
),
)
open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
fun toUriPart() = vals[state].second
}