Fix SenManga (#15590)

This commit is contained in:
Skitty 2023-03-05 15:43:09 -06:00 committed by GitHub
parent 7d495942af
commit fc736e83d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 105 additions and 62 deletions

View File

@ -5,7 +5,7 @@ ext {
extName = 'Sen Manga' extName = 'Sen Manga'
pkgNameSuffix = 'ja.senmanga' pkgNameSuffix = 'ja.senmanga'
extClass = '.SenManga' extClass = '.SenManga'
extVersionCode = 5 extVersionCode = 6
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View File

@ -8,6 +8,7 @@ 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.Companion.toHttpUrlOrNull import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.Request import okhttp3.Request
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
@ -41,14 +42,12 @@ class SenManga : ParsedHttpSource() {
it.proceed(request) it.proceed(request)
}.build() }.build()
override fun popularMangaSelector() = "div.item" override fun popularMangaSelector() = ".mng"
override fun popularMangaFromElement(element: Element) = SManga.create().apply { override fun popularMangaFromElement(element: Element) = SManga.create().apply {
element.select("a").let { setUrlWithoutDomain(element.select("a").attr("href"))
setUrlWithoutDomain(it.attr("href")) title = element.select("div.series-title").text()
title = it.select("div.series-title").text() thumbnail_url = element.select(".cover img").attr("data-src")
}
thumbnail_url = element.select("img").attr("abs:src")
} }
override fun popularMangaNextPageSelector() = "ul.pagination a[rel=next]" override fun popularMangaNextPageSelector() = "ul.pagination a[rel=next]"
@ -72,13 +71,14 @@ class SenManga : ParsedHttpSource() {
filters.forEach { filter -> filters.forEach { filter ->
when (filter) { when (filter) {
is GenreFilter -> { is GenreFilter -> filter.state.forEach { genre ->
val genreInclude = filter.state.filter { it.isIncluded() }.joinToString("%2C") { it.id } if (genre.state) {
val genreExclude = filter.state.filter { it.isExcluded() }.joinToString("%2C") { it.id } url.addQueryParameter("genre[]", genre.id)
url.addQueryParameter("genre", genreInclude)
url.addQueryParameter("nogenre", genreExclude)
} }
is SortFilter -> url.addQueryParameter("sort", filter.toUriPart()) }
is StatusFilter -> url.addQueryParameter("status", filter.toUriPart())
is TypeFilter -> url.addQueryParameter("type", filter.toUriPart())
is OrderFilter -> url.addQueryParameter("order", filter.toUriPart())
else -> {} else -> {}
} }
} }
@ -96,14 +96,18 @@ class SenManga : ParsedHttpSource() {
val seriesElement = document.select("div.series-desc .info") val seriesElement = document.select("div.series-desc .info")
genre = seriesElement.select(".item:eq(0)").text().substringAfter(": ") genre = seriesElement.select(".item.genre a").joinToString(", ") { it.text() }
status = seriesElement.select(".item:eq(1)").first()?.text().orEmpty().let { parseStatus(it.substringAfter("Status:")) } status = seriesElement.select(".item:has(strong:contains(Status))").first()?.text().orEmpty().let {
author = seriesElement.select(".item:eq(3)").text().substringAfter(": ") parseStatus(it.substringAfter("Status:"))
}
author = seriesElement.select(".item:has(strong:contains(Author)) a").text()
} }
private fun parseStatus(status: String) = when { private fun parseStatus(status: String) = when {
status.contains("Ongoing") -> SManga.ONGOING status.contains("Ongoing") -> SManga.ONGOING
status.contains("Complete") -> SManga.COMPLETED status.contains("Complete") -> SManga.COMPLETED
status.contains("Hiatus") -> SManga.ON_HIATUS
status.contains("Dropped") -> SManga.CANCELLED
else -> SManga.UNKNOWN else -> SManga.UNKNOWN
} }
@ -131,9 +135,25 @@ class SenManga : ParsedHttpSource() {
} }
override fun pageListParse(document: Document): List<Page> { override fun pageListParse(document: Document): List<Page> {
return listOf(1..document.select("select[name=page] option:last-of-type").first()!!.text().toInt()).flatten().map { i -> val pageCount = document
.select("select.page-list option:last-of-type")
.first()!!
.attr("value")
.toInt()
val firstUrl = document.select("img.picture").first()!!.attr("src")
return if (firstUrl.contains(baseUrl)) {
listOf(1..pageCount).flatten().map { i ->
Page(i - 1, "", "${document.location().replace(baseUrl, "$baseUrl/viewer")}/$i") Page(i - 1, "", "${document.location().replace(baseUrl, "$baseUrl/viewer")}/$i")
} }
} else {
// request each page for image url
listOf(Page(0, "", firstUrl)) + listOf(1 until pageCount).flatten().map { i ->
val url = "${document.location()}/${i + 1}"
val doc = client.newCall(GET(url)).execute().asJsoup()
val imageUrl = doc.select("img.picture").first()!!.attr("src")
Page(i, "", imageUrl)
}
}
} }
override fun imageUrlParse(document: Document) = override fun imageUrlParse(document: Document) =
@ -141,10 +161,12 @@ class SenManga : ParsedHttpSource() {
override fun getFilterList() = FilterList( override fun getFilterList() = FilterList(
GenreFilter(getGenreList()), GenreFilter(getGenreList()),
SortFilter(), StatusFilter(),
TypeFilter(),
OrderFilter(),
) )
private class Genre(name: String, val id: String = name) : Filter.TriState(name) private class Genre(name: String, val id: String = name) : Filter.CheckBox(name)
private class GenreFilter(genres: List<Genre>) : Filter.Group<Genre>("Genre", genres) private class GenreFilter(genres: List<Genre>) : Filter.Group<Genre>("Genre", genres)
open class UriPartFilter(displayName: String, private val vals: Array<Pair<String, String>>) : open class UriPartFilter(displayName: String, private val vals: Array<Pair<String, String>>) :
@ -152,51 +174,72 @@ class SenManga : ParsedHttpSource() {
fun toUriPart() = vals[state].first fun toUriPart() = vals[state].first
} }
private class SortFilter : UriPartFilter( private class StatusFilter : UriPartFilter(
"Sort By", "Status",
arrayOf( arrayOf(
Pair("total_views", "Total Views"), Pair("", "All"),
Pair("title", "Title"), Pair("Ongoing", "Ongoing"),
Pair("rank", "Rank"), Pair("Completed", "Completed"),
Pair("last_update", "Last Update"), Pair("Hiatus", "Hiatus"),
),
)
private class TypeFilter : UriPartFilter(
"Type",
arrayOf(
Pair("", "All"),
Pair("Manga", "Manga"),
Pair("Manhua", "Manhua"),
Pair("Manhwa", "Manhwa"),
),
)
private class OrderFilter : UriPartFilter(
"Order",
arrayOf(
Pair("", "Default"),
Pair("A-Z", "A-Z"),
Pair("Z-A", "Z-A"),
Pair("Update", "Update"),
Pair("Added", "Added"),
Pair("Popular", "Popular"),
Pair("Rating", "Rating"),
), ),
) )
private fun getGenreList(): List<Genre> = listOf( private fun getGenreList(): List<Genre> = listOf(
Genre("Action", "Action"), Genre("Action"),
Genre("Adult", "Adult"), Genre("Adult"),
Genre("Adventure", "Adventure"), Genre("Adventure"),
Genre("Comedy", "Comedy"), Genre("Comedy"),
Genre("Cooking", "Cooking"), Genre("Cooking"),
Genre("Drama", "Drama"), Genre("Drama"),
Genre("Ecchi", "Ecchi"), Genre("Ecchi"),
Genre("Fantasy", "Fantasy"), Genre("Fantasy"),
Genre("Gender Bender", "Gender+Bender"), Genre("Gender Bender"),
Genre("Harem", "Harem"), Genre("Harem"),
Genre("Historical", "Historical"), Genre("Historical"),
Genre("Horror", "Horror"), Genre("Horror"),
Genre("Josei", "Josei"), Genre("Josei"),
Genre("Light Novel", "Light+Novel"), Genre("Light Novel"),
Genre("Martial Arts", "Martial+Arts"), Genre("Martial Arts"),
Genre("Mature", "Mature"), Genre("Mature"),
Genre("Music", "Music"), Genre("Music"),
Genre("Mystery", "Mystery"), Genre("Mystery"),
Genre("Psychological", "Psychological"), Genre("Psychological"),
Genre("Romance", "Romance"), Genre("Romance"),
Genre("School Life", "School+Life"), Genre("School Life"),
Genre("Sci-Fi", "Sci+Fi"), Genre("Sci-Fi"),
Genre("Seinen", "Seinen"), Genre("Seinen"),
Genre("Shoujo", "Shoujo"), Genre("Shoujo"),
Genre("Shoujo Ai", "Shoujo+Ai"), Genre("Shoujo Ai"),
Genre("Shounen", "Shounen"), Genre("Shounen"),
Genre("Shounen Ai", "Shounen+Ai"), Genre("Shounen Ai"),
Genre("Slice of Life", "Slice+of+Life"), Genre("Slice of Life"),
Genre("Smut", "Smut"), Genre("Smut"),
Genre("Sports", "Sports"), Genre("Sports"),
Genre("Supernatural", "Supernatural"), Genre("Supernatural"),
Genre("Tragedy", "Tragedy"), Genre("Tragedy"),
Genre("Webtoons", "Webtoons"), Genre("Webtoons"),
Genre("Yaoi", "Yaoi"), Genre("Yaoi"),
Genre("Yuri", "Yuri"), Genre("Yuri"),
) )
} }