Manhwaxxl: Fix source (#7066)

* fix

* fix comment

* fix comment

* add all genre and remove import
This commit is contained in:
dngonz 2025-01-09 15:30:55 +01:00 committed by Draff
parent 677d9d17c0
commit c9b85253ed
No known key found for this signature in database
GPG Key ID: E8A89F3211677653
2 changed files with 62 additions and 43 deletions

View File

@ -1,7 +1,7 @@
ext {
extName = "Manhwa XXL"
extClass = ".ManhwaXXL"
extVersionCode = 2
extVersionCode = 3
isNsfw = true
}

View File

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.extension.en.manhwaxxl
import eu.kanade.tachiyomi.network.GET
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.Page
@ -8,11 +9,20 @@ 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 kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.FormBody
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.injectLazy
class ManhwaXXL : ParsedHttpSource() {
@ -20,25 +30,26 @@ class ManhwaXXL : ParsedHttpSource() {
override val lang = "en"
override val baseUrl = "https://manhwaxxl.com"
override val baseUrl = "https://hentaitnt.net"
override val supportsLatest = true
// Site changed from BakaManga
override val versionId = 2
override fun headersBuilder() = super.headersBuilder()
.add("Referer", "$baseUrl/")
private val json: Json by injectLazy()
override fun headersBuilder() = super.headersBuilder().add("Referer", "$baseUrl/")
override fun popularMangaRequest(page: Int) =
GET("$baseUrl/popular" + (if (page > 1) "/page/$page" else ""))
GET("$baseUrl/hot-releases" + (if (page > 1) "/page/$page" else ""))
override fun popularMangaSelector() = "section#page ul.row li"
override fun popularMangaSelector() = "a.comic-tmb"
override fun popularMangaFromElement(element: Element) = SManga.create().apply {
setUrlWithoutDomain(element.selectFirst("span.manga-name a")!!.attr("href"))
title = element.selectFirst("span.manga-name h2")!!.text()
thumbnail_url = element.selectFirst("img")?.absUrl("src")
setUrlWithoutDomain(element.attr("href"))
title = element.attr("title")
thumbnail_url = element.selectFirst("img")?.absUrl("data-src")
}
override fun popularMangaNextPageSelector() = "ul.pagination li.active:not(:last-child)"
@ -57,18 +68,11 @@ class ManhwaXXL : ParsedHttpSource() {
if (query.isNotEmpty()) {
addQueryParameter("s", query)
} else {
val filterList = if (filters.isEmpty()) getFilterList() else filters
val genreFilter = filterList.find { it is GenreFilter } as GenreFilter
val genreFilter = filters.find { it is GenreFilter } as GenreFilter
val genreId = genreFilter.genres[genreFilter.state].id
if (genreId.isEmpty()) {
addPathSegment("popular")
} else {
addPathSegment("category")
addPathSegment(genreId)
}
addPathSegment("genre")
addPathSegment(genreId)
}
if (page > 1) {
addPathSegment("page")
addPathSegment(page.toString())
@ -85,42 +89,56 @@ class ManhwaXXL : ParsedHttpSource() {
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
override fun mangaDetailsParse(document: Document) = SManga.create().apply {
val statusBadge = document.selectFirst("span.card-title i")?.classNames() ?: emptySet()
title = document.selectFirst("span.card-title h1")!!.text()
author = document.selectFirst("div:has(> i.fa-user)")?.ownText()
description = document.selectFirst("div.manga-info")?.text()
genre = document.select("ul.post-categories li").joinToString { it.text() }
status = when {
statusBadge.contains("fa-circle-check") -> SManga.COMPLETED
statusBadge.contains("fa-rotate") -> SManga.ONGOING
author = document.selectFirst("div.comic-details__item_links span")?.ownText()
description = document.selectFirst("section#post-decription h2 + p")?.text()
genre = document.select("div.comic-details__item a[href*=genre]").joinToString { it.text() }
status = when (document.selectFirst("div.card h5")?.text()) {
"Completed" -> SManga.ONGOING
"Ongoing" -> SManga.COMPLETED
else -> SManga.UNKNOWN
}
thumbnail_url = document.selectFirst("div.card div.manga-avatar img")?.absUrl("src")
}
// Manga details page have paginated chapter list. We sacrifice `date_upload`
// but we save a bunch of calls, since each page is like 12 chapters.
override fun chapterListParse(response: Response): List<SChapter> {
val detailsDocument = response.asJsoup()
val firstChapter = detailsDocument.selectFirst("ul.chapters-list li.item-chapter a")?.absUrl("href")
?: return emptyList()
val document = client.newCall(GET(firstChapter, headers)).execute().asJsoup()
val script = detailsDocument.selectFirst("script:containsData(post_id)")?.data()
?: throw Exception("Failed to get chapter id")
val data = script.substringAfter("viewsCacheL10n = ").substringBefore(";")
.let { json.parseToJsonElement(it).jsonObject }
return document.select(chapterListSelector()).map { chapterFromElement(it) }.reversed()
val form = FormBody.Builder().add("action", "baka_ajax").add("type", "get_chapters_list")
.add("id", data.getContent("post_id"))
.add("chapters_list_nonce", data.getContent("nonce")).build()
val ajaxResponse = client.newCall(
POST("$baseUrl/wp-admin/admin-ajax.php", headers, form),
).execute()
val jsonObject = json.decodeFromString<JsonObject>(ajaxResponse.body.string())
return jsonObject["data"]!!.jsonObject["chapters"]!!.jsonArray.map {
SChapter.create().apply {
setUrlWithoutDomain(it.getContent("link"))
name = it.getContent("title")
}
}
}
override fun chapterListSelector() = "ul#slide-out a.chapter-link"
override fun chapterFromElement(element: Element) = SChapter.create().apply {
setUrlWithoutDomain(element.attr("href"))
name = element.text()
private fun JsonElement?.getContent(key: String): String {
return this?.jsonObject?.get(key)?.jsonPrimitive?.content
?: throw Exception("Key $key not found")
}
override fun pageListParse(document: Document) =
document.select("div#viewer img").mapIndexed { i, it ->
override fun chapterListSelector() = throw UnsupportedOperationException()
override fun chapterFromElement(element: Element) = throw UnsupportedOperationException()
override fun pageListParse(document: Document): List<Page> {
return document.select("section#viewer img").mapIndexed { i, it ->
Page(i, imageUrl = it.absUrl("src"))
}
}
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException()
@ -133,10 +151,11 @@ class ManhwaXXL : ParsedHttpSource() {
override fun toString() = name
}
private class GenreFilter(val genres: Array<Genre>) : Filter.Select<String>("Genre", genres.map { it.id }.toTypedArray())
private class GenreFilter(val genres: Array<Genre>) :
Filter.Select<String>("Genre", genres.map { it.name }.toTypedArray())
// https://manhwaxxl.com/genres
// copy([...document.querySelectorAll("section#page ul li a:not([class])")].map((e) => `Genre("${e.textContent.trim()}", "${e.href.split("/").slice(-1)[0].replace(/#page$/u, "")}"),`).join("\n"))
// If you want to add new genres just add the name and id. (eg. https://hentaitnt.net/genre/action) action is the id
// You can search more here: https://hentaitnt.net/genres
private fun getGenreList() = arrayOf(
Genre("All", ""),
Genre("Action", "action"),