MangaOni: Fix global search (#15688)

* Added new filter and removed DTO

* Fix status

* Minor changes
This commit is contained in:
seew3l 2023-03-13 09:37:45 -05:00 committed by GitHub
parent be9525d989
commit 7c5fd399b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 59 additions and 107 deletions

View File

@ -6,7 +6,7 @@ ext {
extName = 'MangaOni'
pkgNameSuffix = 'es.mangamx'
extClass = '.MangaOni'
extVersionCode = 14
extVersionCode = 15
isNsfw = true
}

View File

@ -5,7 +5,6 @@ import android.content.SharedPreferences
import android.net.Uri
import android.util.Base64
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
@ -15,16 +14,12 @@ 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 kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import okhttp3.FormBody
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.nio.charset.Charset
import java.text.SimpleDateFormat
import java.util.Locale
@ -43,16 +38,12 @@ open class MangaOni : ConfigurableSource, ParsedHttpSource() {
override val client = network.cloudflareClient
private var csrfToken = ""
private val json: Json by injectLazy()
override fun popularMangaRequest(page: Int) = GET(
url = "$baseUrl/directorio?genero=false&estado=false&filtro=visitas&tipo=false&adulto=${if (hideNSFWContent()) "0" else "false"}&orden=desc&p=$page",
headers = headers,
)
override fun popularMangaNextPageSelector() = ".page-item a[rel=next]"
override fun popularMangaNextPageSelector() = "ul.pagination a[rel=next]"
override fun popularMangaSelector() = "#article-div a"
@ -64,7 +55,6 @@ open class MangaOni : ConfigurableSource, ParsedHttpSource() {
override fun popularMangaParse(response: Response): MangasPage {
val document = response.asJsoup()
csrfToken = document.select("meta[name=csrf-token]").attr("content")
val mangas = document.select(popularMangaSelector()).map { element ->
popularMangaFromElement(element)
@ -92,18 +82,12 @@ open class MangaOni : ConfigurableSource, ParsedHttpSource() {
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val uri = Uri.parse("$baseUrl/${if (query.isNotBlank()) "buscar" else "directorio"}").buildUpon()
if (query.isNotBlank()) {
val formBody = FormBody.Builder()
.add("buscar", query)
.add("_token", csrfToken)
.build()
val searchHeaders = headers.newBuilder()
.add("X-Requested-With", "XMLHttpRequest")
.add("Referer", baseUrl).build()
return POST(url = "$baseUrl/buscar", headers = searchHeaders, body = formBody)
uri.appendQueryParameter("q", query)
} else {
val uri = Uri.parse("$baseUrl/directorio").buildUpon()
uri.appendQueryParameter("adulto", if (hideNSFWContent()) { "0" } else { "1" })
uri.appendQueryParameter("adulto", if (hideNSFWContent()) { "0" } else { "false" })
for (filter in filters) {
when (filter) {
@ -126,52 +110,46 @@ open class MangaOni : ConfigurableSource, ParsedHttpSource() {
"genero",
genresArray[filter.state].second,
)
is AdultContentFilter -> uri.appendQueryParameter(
"adulto",
adultContentArray[filter.state].second,
)
else -> {}
}
}
uri.appendQueryParameter("p", page.toString())
return GET(uri.toString(), headers)
}
uri.appendQueryParameter("p", page.toString())
return GET(uri.toString(), headers)
}
override fun searchMangaNextPageSelector(): String? = popularMangaNextPageSelector()
override fun searchMangaSelector(): String = popularMangaSelector()
override fun searchMangaSelector(): String = "#article-div > div"
override fun searchMangaFromElement(element: Element): SManga = popularMangaFromElement(element)
override fun searchMangaFromElement(element: Element): SManga = SManga.create().apply {
thumbnail_url = element.select("img").attr("src")
element.select("div a").apply {
title = this.text().trim()
setUrlWithoutDomain(this.attr("href"))
}
}
override fun searchMangaParse(response: Response): MangasPage {
if (!response.isSuccessful) throw Exception("Búsqueda fallida ${response.code}")
if ("directorio" in response.request.url.toString()) {
val document = response.asJsoup()
val mangas = document.select(searchMangaSelector()).map { element ->
searchMangaFromElement(element)
}
val document = response.asJsoup()
val hasNextPage = searchMangaNextPageSelector()?.let { selector ->
document.select(selector).first()
} != null
return MangasPage(mangas, hasNextPage)
val mangas = if (document.location().startsWith("$baseUrl/directorio")) {
document.select(popularMangaSelector()).map { popularMangaFromElement(it) }
} else {
val jsonString = response.body.string()
val result = json.decodeFromString<ResponseDto>(jsonString)
if (result.mangaList.isEmpty()) {
return MangasPage(emptyList(), hasNextPage = false)
}
val mangaList = result.mangaList
.map(::searchMangaFromObject)
return MangasPage(mangaList, hasNextPage = false)
document.select(searchMangaSelector()).map { searchMangaFromElement(it) }
}
}
private fun searchMangaFromObject(manga: MangaDto): SManga = SManga.create().apply {
title = manga.name
thumbnail_url = manga.img.replace("/thumb", "/cover")
setUrlWithoutDomain(manga.url)
val hasNextPage = searchMangaNextPageSelector()?.let { selector ->
document.select(selector).first()
} != null
return MangasPage(mangas, hasNextPage)
}
override fun mangaDetailsParse(document: Document): SManga {
@ -187,9 +165,9 @@ open class MangaOni : ConfigurableSource, ParsedHttpSource() {
}
manga.artist = manga.author
manga.genre = document.select("div#categ a").joinToString(", ") { it.text() }
manga.status = when (document.select("span#desarrollo").first()?.text()) {
manga.status = when (document.select("strong:contains(Estado) + span").first()?.text()) {
"En desarrollo" -> SManga.ONGOING
// "Completed" -> SManga.COMPLETED
"Finalizado" -> SManga.COMPLETED
else -> SManga.UNKNOWN
}
return manga
@ -222,14 +200,23 @@ open class MangaOni : ConfigurableSource, ParsedHttpSource() {
override fun imageUrlParse(document: Document) = throw Exception("Not Used")
override fun getFilterList() = FilterList(
Filter.Header("NOTA: Se ignoran si se usa el buscador"),
Filter.Separator(),
SortBy("Ordenar por", sortables),
StatusFilter("Estado", statusArray),
TypeFilter("Tipo", typedArray),
GenreFilter("Géneros", genresArray),
)
override fun getFilterList(): FilterList {
val filterList = mutableListOf(
Filter.Header("NOTA: Se ignoran si se usa el buscador"),
Filter.Separator(),
SortBy("Ordenar por", sortables),
StatusFilter("Estado", statusArray),
TypeFilter("Tipo", typedArray),
GenreFilter("Géneros", genresArray),
)
if (!hideNSFWContent()) {
filterList.add(
AdultContentFilter("Contenido +18", adultContentArray),
)
}
return FilterList(filterList)
}
private class StatusFilter(name: String, values: Array<Pair<String, String>>) :
Filter.Select<String>(name, values.map { it.first }.toTypedArray())
@ -240,6 +227,9 @@ open class MangaOni : ConfigurableSource, ParsedHttpSource() {
private class GenreFilter(name: String, values: Array<Pair<String, String>>) :
Filter.Select<String>(name, values.map { it.first }.toTypedArray())
private class AdultContentFilter(name: String, values: Array<Pair<String, String>>) :
Filter.Select<String>(name, values.map { it.first }.toTypedArray())
class SortBy(name: String, values: Array<Pair<String, String>>) : Filter.Sort(
name,
values.map { it.first }.toTypedArray(),
@ -267,9 +257,15 @@ open class MangaOni : ConfigurableSource, ParsedHttpSource() {
Pair("Alfabético", "nombre"),
)
private val adultContentArray = arrayOf(
Pair("Mostrar todo", "false"),
Pair("Mostrar solo +18", "1"),
Pair("No mostrar +18", "0"),
)
/**
* Url: https://manga-mx.com/directorio/
* Last check: 27/03/2021
* Last check: 12/03/2023
* JS script: Array.from(document.querySelectorAll('select[name="genero"] option'))
* .map(a => `Pair("${a.innerText}", "${a.value}")`).join(',\n')
*/
@ -339,7 +335,7 @@ open class MangaOni : ConfigurableSource, ParsedHttpSource() {
companion object {
private const val CONTENT_PREF = "showNSFWContent"
private const val CONTENT_PREF_TITLE = "Ocultar contenido +18"
private const val CONTENT_PREF_SUMMARY = "Ocultar el contenido erótico en explorar y buscar, no funciona en los mangas recientes."
private const val CONTENT_PREF_SUMMARY = "Ocultar el contenido erótico en mangas populares y filtros, no funciona en los mangas recientes ni búsquedas textuales."
private const val CONTENT_PREF_DEFAULT_VALUE = false
}
}

View File

@ -1,44 +0,0 @@
package eu.kanade.tachiyomi.extension.es.mangamx
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class ResponseDto(
@SerialName("mangas") val mangaList: List<MangaDto> = emptyList(),
@SerialName("usuarios") val usersList: List<UserDto>? = emptyList(),
@SerialName("grupos") val groupsList: List<GroupDto>? = emptyList(),
)
@Serializable
data class MangaDto(
@SerialName("nombre") val name: String = "",
@SerialName("alterno") val alternative: String? = "",
@SerialName("tipo") val type: Int = 0,
@SerialName("lanzamiento") val releaseYear: Int = 0,
@SerialName("autor") val author: String? = "",
val visible: Int = 0,
val cover: String? = "",
val slug: String = "",
val url: String = "",
val img: String = "",
)
@Serializable
data class UserDto(
@SerialName("usuario") val username: String = "",
@SerialName("perfil") val profile: String? = "",
@SerialName("genero") val gender: String? = "",
val id: Int? = 0,
val url: String = "",
val img: String = "",
)
@Serializable
data class GroupDto(
@SerialName("nombre") val name: String = "",
val id: Int? = 0,
val cover: String? = "",
val url: String = "",
val img: String = "",
)