DoujinDesu : Fix and Add Some Feature (#6479)

* DoujinDesu : Fix and Add Some Feature

Add some New Filter
- Author Filter
- Character Filter

Add some Detail in MangaDetail
- Author
- Group
- Series / Serialization

Fix or Modified some Selector
- Title Selector
- Page Selector
- Author Selector
- Character Selector
- Series Selector
- Group Selector

Change Language from En to Id on Filter Tab and Change BaseUrl tab

* Change Filter Header

* Lint for Filter Group

* Apply suggestion

* Apply suggestion

* Update src/id/doujindesu/src/eu/kanade/tachiyomi/extension/id/doujindesu/DoujinDesu.kt

Thanks to vetleledaal

Co-authored-by: Vetle Ledaal <vetle.ledaal@gmail.com>

* Apply suggestion

* Lint

* Update Status Selector

Thanks to AwkwardPeak7

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>

* Apply suggestion

* Apply suggestion

Thanks to AwkwardPeak7

* Make description is not null

* Forget to change desc lang to id

---------

Co-authored-by: Vetle Ledaal <vetle.ledaal@gmail.com>
Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>
This commit is contained in:
TheKingTermux 2024-12-12 13:20:02 +07:00 committed by Draff
parent b3f22ebf80
commit 4cc9b24137
No known key found for this signature in database
GPG Key ID: E8A89F3211677653
2 changed files with 79 additions and 33 deletions

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'DoujinDesu' extName = 'DoujinDesu'
extClass = '.DoujinDesu' extClass = '.DoujinDesu'
extVersionCode = 6 extVersionCode = 7
isNsfw = true isNsfw = true
} }

View File

@ -78,21 +78,21 @@ class DoujinDesu : ParsedHttpSource(), ConfigurableSource {
} }
private val orderBy = arrayOf( private val orderBy = arrayOf(
Order("All", ""), Order("Semua", ""),
Order("A-Z", "title"), Order("A-Z", "title"),
Order("Latest Update", "update"), Order("Update Terbaru", "update"),
Order("Latest Added", "latest"), Order("Baru Ditambahkan", "latest"),
Order("Popular", "popular"), Order("Populer", "popular"),
) )
private val statusList = arrayOf( private val statusList = arrayOf(
Status("All", ""), Status("Semua", ""),
Status("Publishing", "Publishing"), Status("Berlanjut", "Publishing"),
Status("Finished", "Finished"), Status("Selesai", "Finished"),
) )
private val categoryNames = arrayOf( private val categoryNames = arrayOf(
Category("All", ""), Category("Semua", ""),
Category("Doujinshi", "Doujinshi"), Category("Doujinshi", "Doujinshi"),
Category("Manga", "Manga"), Category("Manga", "Manga"),
Category("Manhwa", "Manhwa"), Category("Manhwa", "Manhwa"),
@ -252,17 +252,17 @@ class DoujinDesu : ParsedHttpSource(), ConfigurableSource {
Genre("Yuri"), Genre("Yuri"),
) )
private class CategoryNames(categories: Array<Category>) : private class AuthorFilter : Filter.Text("Author")
Filter.Select<Category>("Category", categories, 0) private class CharacterFilter : Filter.Text("Karakter")
private class CategoryNames(categories: Array<Category>) : Filter.Select<Category>("Kategori", categories, 0)
private class OrderBy(orders: Array<Order>) : Filter.Select<Order>("Order", orders, 0) private class OrderBy(orders: Array<Order>) : Filter.Select<Order>("Urutkan", orders, 0)
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genre", genres) private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genre", genres)
private class StatusList(statuses: Array<Status>) : Filter.Select<Status>("Status", statuses, 0) private class StatusList(statuses: Array<Status>) : Filter.Select<Status>("Status", statuses, 0)
private fun basicInformationFromElement(element: Element): SManga { private fun basicInformationFromElement(element: Element): SManga {
val manga = SManga.create() val manga = SManga.create()
element.select("a").let { element.select("a").let {
manga.title = it.attr("title") manga.title = element.selectFirst("h3.title")!!.text()
manga.setUrlWithoutDomain(it.attr("href")) manga.setUrlWithoutDomain(it.attr("href"))
} }
element.select("a > figure.thumbnail > img").first()?.let { element.select("a > figure.thumbnail > img").first()?.let {
@ -310,9 +310,9 @@ class DoujinDesu : ParsedHttpSource(), ConfigurableSource {
// Element Selectors // Element Selectors
override fun latestUpdatesSelector(): String = "#archives > div.entries > article"
override fun popularMangaSelector(): String = "#archives > div.entries > article" override fun popularMangaSelector(): String = "#archives > div.entries > article"
override fun searchMangaSelector(): String = "#archives > div.entries > article" override fun latestUpdatesSelector() = popularMangaSelector()
override fun searchMangaSelector() = popularMangaSelector()
override fun popularMangaNextPageSelector(): String = "nav.pagination > ul > li.last > a" override fun popularMangaNextPageSelector(): String = "nav.pagination > ul > li.last > a"
override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector() override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
@ -333,6 +333,12 @@ class DoujinDesu : ParsedHttpSource(), ConfigurableSource {
val order = filter.values[filter.state] val order = filter.values[filter.state]
url.addQueryParameter("order", order.key) url.addQueryParameter("order", order.key)
} }
is AuthorFilter -> {
url.addQueryParameter("author", filter.state)
}
is CharacterFilter -> {
url.addQueryParameter("character", filter.state)
}
is GenreList -> { is GenreList -> {
filter.state filter.state
.filter { it.state } .filter { it.state }
@ -349,6 +355,7 @@ class DoujinDesu : ParsedHttpSource(), ConfigurableSource {
else -> {} else -> {}
} }
} }
return GET(url.build(), headers) return GET(url.build(), headers)
} }
@ -356,8 +363,10 @@ class DoujinDesu : ParsedHttpSource(), ConfigurableSource {
basicInformationFromElement(element) basicInformationFromElement(element)
override fun getFilterList() = FilterList( override fun getFilterList() = FilterList(
Filter.Header("NB: Filter diabaikan jika memakai pencarian teks!"), Filter.Header("NB: Filter bisa digabungkan dengan memakai pencarian teks!"),
Filter.Separator(), Filter.Separator(),
AuthorFilter(),
CharacterFilter(),
StatusList(statusList), StatusList(statusList),
CategoryNames(categoryNames), CategoryNames(categoryNames),
OrderBy(orderBy), OrderBy(orderBy),
@ -367,30 +376,67 @@ class DoujinDesu : ParsedHttpSource(), ConfigurableSource {
// Detail Parse // Detail Parse
override fun mangaDetailsParse(document: Document): SManga { override fun mangaDetailsParse(document: Document): SManga {
val infoElement = document.select("section.metadata").first()!! val infoElement = document.selectFirst("section.metadata")!!
val authorName = if (infoElement.select("td:contains(Author) ~ td").isEmpty()) {
null
} else {
infoElement.select("td:contains(Author) ~ td").joinToString { it.text() }
}
val groupName = if (infoElement.select("td:contains(Group) ~ td").isEmpty()) {
"Tidak Diketahui"
} else {
infoElement.select("td:contains(Group) ~ td").joinToString { it.text() }
}
val authorParser = if (authorName.isNullOrEmpty()) {
groupName?.takeIf { !it.isNullOrEmpty() && it != "Tidak Diketahui" }
} else {
authorName
}
val characterName = if (infoElement.select("td:contains(Character) ~ td").isEmpty()) {
"Tidak Diketahui"
} else {
infoElement.select("td:contains(Character) ~ td").joinToString { it.text() }
}
val seriesParser = if (infoElement.select("td:contains(Series) ~ td").text() == "Manhwa") {
infoElement.select("td:contains(Serialization) ~ td").text()
} else {
infoElement.select("td:contains(Series) ~ td").text()
}
val alternativeTitle = if (infoElement.select("h1.title > span.alter").isEmpty()) {
"Tidak Diketahui"
} else {
infoElement.select("h1.title > span.alter").joinToString { it.text() }
}
val manga = SManga.create() val manga = SManga.create()
manga.description = when { manga.description = if (infoElement.select("div.pb-2 > p:nth-child(1)").isEmpty()) {
document.select("section.metadata > div.pb-2 > p:nth-child(1)") """
.isEmpty() -> "Tidak ada deskripsi yang tersedia bosque" Tidak ada deskripsi yang tersedia bosque
else -> document.select("section.metadata > div.pb-2 > p:nth-child(1)").first()!!.text()
Judul Alternatif : $alternativeTitle
Grup : $groupName
Karakter : $characterName
Seri : $seriesParser
""".trimIndent()
} else {
val showDescription = infoElement.selectFirst("div.pb-2 > p:nth-child(1)")!!.text()
"""
$showDescription
Judul Alternatif : $alternativeTitle
Seri : $seriesParser
""".trimIndent()
} }
val genres = mutableListOf<String>() val genres = mutableListOf<String>()
infoElement.select("div.tags > a").forEach { element -> infoElement.select("div.tags > a").forEach { element ->
val genre = element.text() val genre = element.text()
genres.add(genre) genres.add(genre)
} }
manga.author = manga.author = authorParser
document.select("section.metadata > table:nth-child(2) > tbody > tr.pages > td:contains(Author) + td:nth-child(2) > a")
.joinToString { it.text() }
manga.genre = infoElement.select("div.tags > a").joinToString { it.text() } manga.genre = infoElement.select("div.tags > a").joinToString { it.text() }
manga.status = parseStatus( manga.status = parseStatus(
document.select("section.metadata > table:nth-child(2) > tbody > tr:nth-child(1) > td:nth-child(2) > a") infoElement.selectFirst("td:contains(Status) ~ td")!!.text(),
.first()!!.text(),
) )
manga.thumbnail_url = document.selectFirst("figure.thumbnail img")?.attr("src") manga.thumbnail_url = document.selectFirst("figure.thumbnail img")?.attr("src")
manga.artist =
document.select("section.metadata > table:nth-child(2) > tbody > tr.pages > td:contains(Character) + td:nth-child(2) > a")
.joinToString { it.text() }
return manga return manga
} }
@ -441,9 +487,9 @@ class DoujinDesu : ParsedHttpSource(), ConfigurableSource {
companion object { companion object {
private val PREF_DOMAIN_KEY = "preferred_domain_name_v${AppInfo.getVersionName()}" private val PREF_DOMAIN_KEY = "preferred_domain_name_v${AppInfo.getVersionName()}"
private const val PREF_DOMAIN_TITLE = "Override BaseUrl" private const val PREF_DOMAIN_TITLE = "Mengganti BaseUrl"
private const val PREF_DOMAIN_DEFAULT = "https://doujindesu.tv" private const val PREF_DOMAIN_DEFAULT = "https://doujindesu.tv"
private const val PREF_DOMAIN_SUMMARY = "Override default domain with a different one" private const val PREF_DOMAIN_SUMMARY = "Mengganti domain default dengan domain yang berbeda"
} }
override fun setupPreferenceScreen(screen: PreferenceScreen) { override fun setupPreferenceScreen(screen: PreferenceScreen) {
@ -456,7 +502,7 @@ class DoujinDesu : ParsedHttpSource(), ConfigurableSource {
setDefaultValue(PREF_DOMAIN_DEFAULT) setDefaultValue(PREF_DOMAIN_DEFAULT)
setOnPreferenceChangeListener { _, newValue -> setOnPreferenceChangeListener { _, newValue ->
Toast.makeText(screen.context, "Restart App to apply new setting.", Toast.LENGTH_LONG).show() Toast.makeText(screen.context, "Mulai ulang aplikasi untuk menerapkan pengaturan baru.", Toast.LENGTH_LONG).show()
true true
} }
}.also(screen::addPreference) }.also(screen::addPreference)