Mangafire: fix manga chapters load (#18298)

* Mangafire: fix manga and chapters load

* Mangafire: increase version code
This commit is contained in:
SkyNalix 2023-10-02 00:19:36 +02:00 committed by GitHub
parent 1da48fa265
commit 9a48fc85ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 38 deletions

View File

@ -85,15 +85,15 @@ open class MangaFire(
return GET(urlBuilder.build(), headers) return GET(urlBuilder.build(), headers)
} }
override fun searchMangaSelector() = ".mangas.items .inner"
override fun searchMangaNextPageSelector() = ".page-item.active + .page-item .page-link" override fun searchMangaNextPageSelector() = ".page-item.active + .page-item .page-link"
override fun searchMangaSelector() = ".original.card-lg .unit .inner"
override fun searchMangaFromElement(element: Element) = override fun searchMangaFromElement(element: Element) =
SManga.create().apply { SManga.create().apply {
element.selectFirst("a.color-light")!!.let { element.selectFirst(".info > a")!!.let {
url = it.attr("href") setUrlWithoutDomain(it.attr("href"))
title = it.attr("title") title = it.ownText()
} }
element.selectFirst(Evaluator.Tag("img"))!!.let { element.selectFirst(Evaluator.Tag("img"))!!.let {
thumbnail_url = it.attr("src") thumbnail_url = it.attr("src")
@ -101,25 +101,26 @@ open class MangaFire(
} }
override fun mangaDetailsParse(document: Document) = SManga.create().apply { override fun mangaDetailsParse(document: Document) = SManga.create().apply {
val root = document.selectFirst(".detail .top .wrapper")!! val root = document.selectFirst(".info")!!
val mangaTitle = root.selectFirst(Evaluator.Class("name"))!!.ownText() val mangaTitle = root.child(1).ownText()
title = mangaTitle title = mangaTitle
description = document.run { description = document.run {
val description = selectFirst(Evaluator.Class("summary"))!!.ownText() val description = selectFirst(Evaluator.Class("description"))!!.ownText()
when (val altTitle = root.selectFirst(Evaluator.Class("al-name"))!!.ownText()) { when (val altTitle = root.child(2).ownText()) {
"", mangaTitle -> description "", mangaTitle -> description
else -> "$description\n\nAlternative Title: $altTitle" else -> "$description\n\nAlternative Title: $altTitle"
} }
} }
thumbnail_url = root.selectFirst(Evaluator.Tag("img"))!!.attr("src") thumbnail_url = document.selectFirst(".poster")!!
status = when (root.selectFirst(Evaluator.Class("status"))!!.ownText()) { .selectFirst("img")!!.attr("src")
status = when (root.child(0).ownText()) {
"Completed" -> SManga.COMPLETED "Completed" -> SManga.COMPLETED
"Releasing" -> SManga.ONGOING "Releasing" -> SManga.ONGOING
"On_hiatus" -> SManga.ON_HIATUS "On_hiatus" -> SManga.ON_HIATUS
"Discontinued" -> SManga.CANCELLED "Discontinued" -> SManga.CANCELLED
else -> SManga.UNKNOWN else -> SManga.UNKNOWN
} }
with(root.selectFirst(Evaluator.Class("more-info"))!!) { with(document.selectFirst(Evaluator.Class("meta"))!!) {
author = selectFirst("span:contains(Author:) + span")?.text() author = selectFirst("span:contains(Author:) + span")?.text()
val type = selectFirst("span:contains(Type:) + span")?.text() val type = selectFirst("span:contains(Type:) + span")?.text()
val genres = selectFirst("span:contains(Genres:) + span")?.text() val genres = selectFirst("span:contains(Genres:) + span")?.text()
@ -132,20 +133,39 @@ open class MangaFire(
override fun chapterListRequest(mangaUrl: String, type: String): Request { override fun chapterListRequest(mangaUrl: String, type: String): Request {
val id = mangaUrl.substringAfterLast('.') val id = mangaUrl.substringAfterLast('.')
return GET("$baseUrl/ajax/read/$id/list?viewby=$type", headers) return GET("$baseUrl/ajax/manga/$id/$type/$langCode", headers)
} }
override fun parseChapterElements(response: Response, isVolume: Boolean): List<Element> { override fun parseChapterElements(response: Response, isVolume: Boolean): List<Element> {
val result = json.decodeFromString<ResponseDto<ChapterListDto>>(response.body.string()).result val result = json.decodeFromString<ResponseDto<String>>(response.body.string()).result
val container = result.parseHtml(if (isVolume) volumeType else chapterType) val document = Jsoup.parse(result)
?.selectFirst(".numberlist[data-lang=$langCode]")
?: return emptyList() val elements = document.select("ul li")
return container.children().map { it.child(0) } if (elements.size > 0) {
val linkToFirstChapter = elements[0].selectFirst(Evaluator.Tag("a"))!!.attr("href")
val mangaId = linkToFirstChapter.toString().substringAfter('.').substringBefore('/')
val request = GET("$baseUrl/ajax/read/$mangaId/chapter/$langCode", headers)
val response = client.newCall(request).execute()
val res = json.decodeFromString<ResponseDto<ChapterIdsDto>>(response.body.string()).result.html
val chapterInfoDocument = Jsoup.parse(res)
val chapters = chapterInfoDocument.select("ul li")
for ((i, it) in elements.withIndex()) {
it.attr("data-id", chapters[i].select("a").attr("data-id"))
}
}
return elements.toList()
} }
@Serializable
class ChapterIdsDto(
val html: String,
val title_format: String,
)
override fun updateChapterList(manga: SManga, chapters: List<SChapter>) { override fun updateChapterList(manga: SManga, chapters: List<SChapter>) {
val document = client.newCall(mangaDetailsRequest(manga)).execute().asJsoup() val document = client.newCall(mangaDetailsRequest(manga)).execute().asJsoup()
val elements = document.selectFirst(".chapter-list[data-name=$langCode]")!!.children() val elements = document.selectFirst(".scroll-sm")!!.children()
val chapterCount = chapters.size val chapterCount = chapters.size
if (elements.size != chapterCount) throw Exception("Chapter count doesn't match. Try updating again.") if (elements.size != chapterCount) throw Exception("Chapter count doesn't match. Try updating again.")
val dateFormat = SimpleDateFormat("MMM dd, yyyy", Locale.US) val dateFormat = SimpleDateFormat("MMM dd, yyyy", Locale.US)
@ -180,6 +200,20 @@ open class MangaFire(
} }
} }
@Serializable
class PageListDto(private val images: List<List<JsonPrimitive>>) {
val pages get() = images.map {
Image(it[0].content, it[2].int)
}
}
class Image(val url: String, val offset: Int)
@Serializable
class ResponseDto<T>(
val result: T,
val status: Int,
)
override fun getFilterList() = override fun getFilterList() =
FilterList( FilterList(
Filter.Header("NOTE: Ignored if using text search!"), Filter.Header("NOTE: Ignored if using text search!"),
@ -191,22 +225,4 @@ open class MangaFire(
ChapterCountFilter(), ChapterCountFilter(),
SortFilter(), SortFilter(),
) )
@Serializable
class ChapterListDto(private val html: String, private val link_format: String) {
fun parseHtml(type: String): Document? {
if ("LANG/$type-NUMBER" !in link_format) return null
return Jsoup.parseBodyFragment(html)
}
}
@Serializable
class PageListDto(private val images: List<List<JsonPrimitive>>) {
val pages get() = images.map { Image(it[0].content, it[2].int) }
}
class Image(val url: String, val offset: Int)
@Serializable
class ResponseDto<T>(val result: T)
} }

View File

@ -21,7 +21,7 @@ class MangaReaderGenerator : ThemeSourceGenerator {
baseUrl = "https://mangafire.to", baseUrl = "https://mangafire.to",
langs = listOf("en", "es", "es-419", "fr", "ja", "pt", "pt-BR"), langs = listOf("en", "es", "es-419", "fr", "ja", "pt", "pt-BR"),
isNsfw = true, isNsfw = true,
overrideVersionCode = 1, overrideVersionCode = 2,
), ),
) )