Hennojin: Fix chapter not found for Suwayomi user (#6296)

* Fix chapter not found for Suwayomi user

* Update changes by vetleledaal

* Fix build

* Revert old code URL, because code new URL doesn't work

* Update url

* make thumbnail optional

* use .absUrl() where possible

---------

Co-authored-by: Vetle Ledaal <vetle.ledaal@gmail.com>
This commit is contained in:
are-are-are 2024-11-29 03:45:10 +07:00 committed by Draff
parent abcea6a91a
commit 348c373bc0
No known key found for this signature in database
GPG Key ID: E8A89F3211677653
3 changed files with 67 additions and 38 deletions

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'Hennojin' extName = 'Hennojin'
extClass = '.HennojinFactory' extClass = '.HennojinFactory'
extVersionCode = 1 extVersionCode = 2
isNsfw = true isNsfw = true
} }

View File

@ -1,30 +1,32 @@
package eu.kanade.tachiyomi.extension.all.hennojin package eu.kanade.tachiyomi.extension.all.hennojin
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import org.jsoup.select.Evaluator
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
class Hennojin(override val lang: String, suffix: String) : ParsedHttpSource() { class Hennojin(override val lang: String) : ParsedHttpSource() {
override val baseUrl = "https://hennojin.com/home/$suffix" override val baseUrl = "https://hennojin.com"
override val name = "Hennojin" override val name = "Hennojin"
// Popular is latest // Popular is latest
override val supportsLatest = false override val supportsLatest = false
private val httpUrl by lazy { baseUrl.toHttpUrl() } private val httpUrl by lazy { "$baseUrl/home".toHttpUrl() }
override fun latestUpdatesSelector() = popularMangaSelector() override fun latestUpdatesSelector() = popularMangaSelector()
@ -41,15 +43,23 @@ class Hennojin(override val lang: String, suffix: String) : ParsedHttpSource() {
override fun popularMangaNextPageSelector() = ".paginate .next" override fun popularMangaNextPageSelector() = ".paginate .next"
override fun popularMangaRequest(page: Int) = override fun popularMangaRequest(page: Int) =
httpUrl.request { addEncodedPathSegments("page/$page") } httpUrl.request {
when (lang) {
"ja" -> {
addEncodedPathSegments("page/$page/")
addQueryParameter("archive", "raw")
}
else -> addEncodedPathSegments("page/$page")
}
}
override fun popularMangaFromElement(element: Element) = override fun popularMangaFromElement(element: Element) =
SManga.create().apply { SManga.create().apply {
element.selectFirst(".title_link > a").let { element.selectFirst(".title_link > a").let {
title = it!!.text() title = it!!.text()
setUrlWithoutDomain(it.attr("href")) setUrlWithoutDomain(it.absUrl("href"))
} }
thumbnail_url = element.selectFirst("img")!!.attr("src") thumbnail_url = element.selectFirst("img")?.absUrl("src")
} }
override fun searchMangaSelector() = popularMangaSelector() override fun searchMangaSelector() = popularMangaSelector()
@ -66,46 +76,68 @@ class Hennojin(override val lang: String, suffix: String) : ParsedHttpSource() {
override fun searchMangaFromElement(element: Element) = override fun searchMangaFromElement(element: Element) =
popularMangaFromElement(element) popularMangaFromElement(element)
override fun mangaDetailsRequest(manga: SManga) =
GET("https://hennojin.com" + manga.url, headers)
override fun mangaDetailsParse(document: Document) = override fun mangaDetailsParse(document: Document) =
SManga.create().apply { SManga.create().apply {
description = document.selectFirst( description = document.select(
".manga-subtitle + p + p", ".manga-subtitle + p + p",
)?.html()?.replace("<br> ", "\n") ).joinToString("\n") {
it
.apply { select(Evaluator.Tag("br")).prepend("\\n") }
.text()
.replace("\\n", "\n")
.replace("\n ", "\n")
}.trim()
genre = document.select( genre = document.select(
".tags-list a[href*=/parody/]," + ".tags-list a[href*=/parody/]," +
".tags-list a[href*=/tags/]," + ".tags-list a[href*=/tags/]," +
".tags-list a[href*=/character/]", ".tags-list a[href*=/character/]",
)?.joinToString { it.text() } ).joinToString { it.text() }
artist = document.select( artist = document.selectFirst(
".tags-list a[href*=/artist/]", ".tags-list a[href*=/artist/]",
)?.joinToString { it.text() } )?.text()
author = document.select( author = document.selectFirst(
".tags-list a[href*=/group/]", ".tags-list a[href*=/group/]",
)?.joinToString { it.text() } ?: artist )?.text() ?: artist
status = SManga.COMPLETED status = SManga.COMPLETED
} }
override fun fetchChapterList(manga: SManga) = override fun chapterListParse(response: Response): List<SChapter> {
Request.Builder().url(manga.thumbnail_url!!) val document = response.asJsoup(response.body.string())
.head().build().run(client::newCall) val date = document
.asObservableSuccess().map { res -> .selectFirst(".manga-thumbnail > img")
?.absUrl("src")
?.let { url ->
Request.Builder()
.url(url)
.head()
.build()
.run(client::newCall)
.execute()
.date
}
return document.select("a:contains(Read Online)").map {
SChapter.create().apply { SChapter.create().apply {
setUrlWithoutDomain(
it
?.absUrl("href")
?.toHttpUrlOrNull()
?.newBuilder()
?.removeAllQueryParameters("view")
?.addQueryParameter("view", "multi")
?.build()
?.toString()
?: it.absUrl("href"),
)
name = "Chapter" name = "Chapter"
url = manga.reader date?.run { date_upload = this }
date_upload = res.date
chapter_number = -1f chapter_number = -1f
}.let(::listOf) }
}!! }
}
override fun pageListRequest(chapter: SChapter) =
GET("https://hennojin.com" + chapter.url, headers)
override fun pageListParse(document: Document) = override fun pageListParse(document: Document) =
document.select(".slideshow-container > img") document.select(".slideshow-container > img")
.mapIndexed { idx, img -> Page(idx, "", img.absUrl("src")) } .mapIndexed { idx, img -> Page(idx, imageUrl = img.absUrl("src")) }
private inline fun HttpUrl.request( private inline fun HttpUrl.request(
block: HttpUrl.Builder.() -> HttpUrl.Builder, block: HttpUrl.Builder.() -> HttpUrl.Builder,
@ -114,9 +146,6 @@ class Hennojin(override val lang: String, suffix: String) : ParsedHttpSource() {
private inline val Response.date: Long private inline val Response.date: Long
get() = headers["Last-Modified"]?.run(httpDate::parse)?.time ?: 0L get() = headers["Last-Modified"]?.run(httpDate::parse)?.time ?: 0L
private inline val SManga.reader: String
get() = "/home/manga-reader/?manga=$title&view=multi"
override fun chapterListSelector() = override fun chapterListSelector() =
throw UnsupportedOperationException() throw UnsupportedOperationException()

View File

@ -4,7 +4,7 @@ import eu.kanade.tachiyomi.source.SourceFactory
class HennojinFactory : SourceFactory { class HennojinFactory : SourceFactory {
override fun createSources() = listOf( override fun createSources() = listOf(
Hennojin("en", ""), Hennojin("en"),
Hennojin("ja", "?archive=raw"), Hennojin("ja"),
) )
} }