MangaInUa: fix chapter list and page list (#17540)

This commit is contained in:
stevenyomi 2023-08-17 02:55:34 +08:00 committed by GitHub
parent 61383e923a
commit 1a3b4d2231
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 67 additions and 31 deletions

View File

@ -5,7 +5,7 @@ ext {
extName = 'MangaInUa'
pkgNameSuffix = 'uk.mangainua'
extClass = '.Mangainua'
extVersionCode = 3
extVersionCode = 4
isNsfw = true
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -7,13 +7,17 @@ import eu.kanade.tachiyomi.source.model.Page
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 okhttp3.FormBody
import okhttp3.Headers
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.jsoup.select.Elements
import org.jsoup.select.Evaluator
import java.text.SimpleDateFormat
import java.util.Locale
@ -27,7 +31,7 @@ class Mangainua : ParsedHttpSource() {
override val client: OkHttpClient = network.cloudflareClient
override fun headersBuilder(): Headers.Builder = Headers.Builder()
override fun headersBuilder(): Headers.Builder = super.headersBuilder()
.add("Referer", baseUrl)
// Popular
@ -37,11 +41,11 @@ class Mangainua : ParsedHttpSource() {
override fun popularMangaSelector() = "div.owl-carousel div.card--big"
override fun popularMangaFromElement(element: Element): SManga {
return SManga.create().apply {
element.select("h3.card__title a").first()!!.let {
element.selectFirst("h3.card__title a")!!.let {
setUrlWithoutDomain(it.attr("href"))
title = it.text()
}
thumbnail_url = element.select("img").attr("abs:src")
thumbnail_url = element.selectFirst("img")?.absUrl("src")
}
}
override fun popularMangaNextPageSelector() = "not used"
@ -53,11 +57,11 @@ class Mangainua : ParsedHttpSource() {
override fun latestUpdatesSelector() = "main.main article.item"
override fun latestUpdatesFromElement(element: Element): SManga {
return SManga.create().apply {
element.select("h3.card__title a").first()!!.let {
element.selectFirst("h3.card__title a")!!.let {
setUrlWithoutDomain(it.attr("href"))
title = it.text()
}
thumbnail_url = element.select("div.card--big img").attr("abs:data-src")
thumbnail_url = element.selectFirst("div.card--big img")?.absUrl("data-src")
}
}
override fun latestUpdatesNextPageSelector() = "a:contains(Наступна)"
@ -76,18 +80,18 @@ class Mangainua : ParsedHttpSource() {
headers = headers,
)
} else {
throw UnsupportedOperationException("Запит має містити щонайменше 3 символи / The query must contain at least 3 characters")
throw Exception("Запит має містити щонайменше 3 символи / The query must contain at least 3 characters")
}
}
override fun searchMangaSelector() = latestUpdatesSelector()
override fun searchMangaFromElement(element: Element): SManga {
return SManga.create().apply {
element.select("h3.card__title a").first()!!.let {
element.selectFirst("h3.card__title a")!!.let {
setUrlWithoutDomain(it.attr("href"))
title = it.text()
}
thumbnail_url = element.select("div.card--big img").attr("abs:src")
thumbnail_url = element.selectFirst("div.card--big img")?.absUrl("src")
}
}
override fun searchMangaNextPageSelector() = latestUpdatesNextPageSelector()
@ -95,35 +99,40 @@ class Mangainua : ParsedHttpSource() {
// Manga Details
override fun mangaDetailsParse(document: Document): SManga {
return SManga.create().apply {
title = document.select("span.UAname").text()
description = document.select("div.item__full-description").text()
thumbnail_url = document.select("div.item__full-sidebar--poster img").first()!!.attr("abs:src")
status = when (document.select("div.item__full-sideba--header:has(div:containsOwn(Статус перекладу:))").first()?.select("span.item__full-sidebar--description")?.first()?.text()) {
title = document.selectFirst("span.UAname")!!.text()
description = document.selectFirst("div.item__full-description")!!.text()
thumbnail_url = document.selectFirst("div.item__full-sidebar--poster img")!!.absUrl("src")
status = when (document.selectFirst("div.item__full-sideba--header:has(div:containsOwn(Статус перекладу:))")?.selectFirst("span.item__full-sidebar--description")?.text()) {
"Триває" -> SManga.ONGOING
"Покинуто" -> SManga.CANCELLED
"Закінчений" -> SManga.COMPLETED
else -> SManga.UNKNOWN
}
val type = when (document.select("div.item__full-sideba--header:has(div:containsOwn(Тип:))").first()?.select("span.item__full-sidebar--description")?.first()!!.text()) {
val type = when (document.selectFirst("div.item__full-sideba--header:has(div:containsOwn(Тип:))")?.selectFirst("span.item__full-sidebar--description")!!.text()) {
"ВЕБМАНХВА" -> "Manhwa"
"МАНХВА" -> "Manhwa"
"МАНЬХВА" -> "Manhua"
"ВЕБМАНЬХВА" -> "Manhua"
else -> "Manga"
}
genre = document.select("div.item__full-sideba--header:has(div:containsOwn(Жанри:))").first()?.select("span.item__full-sidebar--description")?.first()!!.select("a").joinToString { it.text() } + ", " + type
genre = document.selectFirst("div.item__full-sideba--header:has(div:containsOwn(Жанри:))")?.selectFirst("span.item__full-sidebar--description")!!.select("a").joinToString { it.text() } + ", " + type
}
}
// Chapters
override fun chapterListSelector() = "div.ltcitems"
private var previousChapterName: String? = null
private var previousChapterNumber: Float = 0.0f
override fun chapterListSelector() = throw UnsupportedOperationException()
override fun chapterFromElement(element: Element): SChapter {
return SChapter.create().apply {
element.select("a").let { urlElement ->
throw UnsupportedOperationException()
}
private fun parseChapterElements(elements: Elements): List<SChapter> {
var previousChapterName: String? = null
var previousChapterNumber: Float = 0.0f
val dateFormat = DATE_FORMATTER
return elements.map { element ->
SChapter.create().apply {
val urlElement = element.selectFirst("a")!!
setUrlWithoutDomain(urlElement.attr("href"))
val chapterName = urlElement.text().substringAfter("НОВЕ").trim()
val chapterNumber = urlElement.text().substringAfter("Розділ").substringBefore("-").trim()
@ -137,31 +146,58 @@ class Mangainua : ParsedHttpSource() {
chapter_number = chapterNumber.toFloat()
previousChapterNumber = chapterNumber.toFloat()
}
date_upload = dateFormat.parse(element.child(0).ownText())?.time!!
}
date_upload = parseDate(element.select("div.ltcright:containsOwn(.)").text())
}
}
override fun chapterListParse(response: Response): List<SChapter> {
return super.chapterListParse(response).reversed()
val document = response.asJsoup()
val userHash = document.parseUserHash()
val metaElement = document.selectFirst(Evaluator.Id("linkstocomics"))!!
val body = FormBody.Builder()
.addEncoded("action", "show")
.addEncoded("news_id", metaElement.attr("data-news_id"))
.addEncoded("news_category", metaElement.attr("data-news_category"))
.addEncoded("this_link", metaElement.attr("data-this_link"))
.addEncoded("user_hash", userHash)
.build()
val request = POST("$baseUrl/engine/ajax/controller.php?mod=load_chapters", headers, body)
val chaptersHtml = client.newCall(request).execute().body.string()
val chaptersDocument = Jsoup.parseBodyFragment(chaptersHtml)
return parseChapterElements(chaptersDocument.body().children()).asReversed()
}
// Pages
override fun pageListParse(document: Document): List<Page> {
return document.select("ul.loadcomicsimages img").mapIndexed { i, element ->
Page(i, "", element.attr("abs:data-src"))
val userHash = document.parseUserHash()
val newsId = document.selectFirst(Evaluator.Id("comics"))!!.attr("data-news_id")
val url = "$baseUrl/engine/ajax/controller.php?mod=load_chapters_image&news_id=$newsId&action=show&user_hash=$userHash"
val pagesHtml = client.newCall(GET(url, headers)).execute().body.string()
val pagesDocument = Jsoup.parseBodyFragment(pagesHtml)
return pagesDocument.getElementsByTag("img").mapIndexed { index, img ->
Page(index, imageUrl = img.attr("data-src"))
}
}
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
private fun parseDate(dateStr: String): Long {
return runCatching { DATE_FORMATTER.parse(dateStr)?.time }
.getOrNull() ?: 0L
}
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
companion object {
private val DATE_FORMATTER by lazy {
SimpleDateFormat("dd.MM.yyyy", Locale.ENGLISH)
}
private fun Document.parseUserHash(): String {
val start = "site_login_hash = '"
for (element in body().children()) {
if (element.tagName() != "script") continue
val data = element.data()
val leftIndex = data.indexOf(start)
if (leftIndex == -1) continue
val startIndex = leftIndex + start.length
val endIndex = data.indexOf('\'', startIndex)
return data.substring(startIndex, endIndex)
}
throw Exception("Couldn't find user hash")
}
}
}