MD: update domain and add filters (#17680)

* MD: update domain

* MD: add filters

* rename file
This commit is contained in:
AwkwardPeak7 2023-08-26 19:23:14 +05:00 committed by GitHub
parent 20b56f4be9
commit f12ba2fcad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 153 additions and 24 deletions

View File

@ -5,7 +5,7 @@ ext {
extName = 'Manga Demon'
pkgNameSuffix = 'en.mangademon'
extClass = '.MangaDemon'
extVersionCode = 3
extVersionCode = 4
}
apply from: "$rootDir/common.gradle"

View File

@ -1,8 +1,10 @@
package eu.kanade.tachiyomi.extension.en.mangademon
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
@ -10,8 +12,10 @@ import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
import java.text.SimpleDateFormat
import java.util.Locale
@ -20,10 +24,10 @@ class MangaDemon : ParsedHttpSource() {
override val lang = "en"
override val supportsLatest = true
override val name = "Manga Demon"
override val baseUrl = "https://mangademon.org"
override val baseUrl = "https://manga-demon.org"
override val client = network.cloudflareClient.newBuilder()
.rateLimit(2)
.rateLimit(1)
.build()
override fun headersBuilder() = super.headersBuilder()
@ -38,14 +42,12 @@ class MangaDemon : ParsedHttpSource() {
override fun latestUpdatesSelector() = "div.leftside"
override fun latestUpdatesFromElement(element: Element): SManga {
return SManga.create().apply {
element.select("a").apply {
title = attr("title").dropLast(4)
url = attr("href")
}
thumbnail_url = element.select("img").attr("abs:src")
override fun latestUpdatesFromElement(element: Element) = SManga.create().apply {
element.select("a").apply {
title = attr("title")
setUrlWithoutDomain(attr("href"))
}
thumbnail_url = element.select("img").attr("abs:src")
}
// Popular
@ -60,6 +62,44 @@ class MangaDemon : ParsedHttpSource() {
override fun popularMangaFromElement(element: Element) = latestUpdatesFromElement(element)
// Search
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
return if (query.isNotEmpty()) {
super.fetchSearchManga(page, query, filters)
} else {
client.newCall(filterSearchRequest(page, filters))
.asObservableSuccess()
.map(::filterSearchParse)
}
}
private fun filterSearchRequest(page: Int, filters: FilterList): Request {
val url = "$baseUrl/browse.php".toHttpUrl().newBuilder().apply {
addQueryParameter("list", page.toString())
filters.forEach { filter ->
when (filter) {
is GenreFilter -> {
filter.checked.forEach { genre ->
addQueryParameter("genre[]", genre)
}
}
is StatusFilter -> {
addQueryParameter("status", filter.selected)
}
is SortFilter -> {
addQueryParameter("orderby", filter.selected)
}
else -> {}
}
}
}.build()
return GET(url, headers)
}
private fun filterSearchParse(response: Response) = popularMangaParse(response)
override fun getFilterList() = getFilters()
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = "$baseUrl/search.php".toHttpUrl().newBuilder()
.addQueryParameter("manga", query)
@ -69,18 +109,14 @@ class MangaDemon : ParsedHttpSource() {
override fun searchMangaSelector() = "a.boxsizing"
override fun searchMangaFromElement(element: Element): SManga {
return SManga.create().apply {
element.select("a").first().let {
title = element.select("li.boxsizing").text()
url = (element.attr("href"))
val urlsorter = title.replace(":", "%20")
thumbnail_url = ("https://readermc.org/images/thumbnails/$urlsorter.webp")
}
}
override fun searchMangaFromElement(element: Element) = SManga.create().apply {
title = element.text()
setUrlWithoutDomain(element.attr("href"))
val urlSorter = title.replace(":", "%20")
thumbnail_url = ("https://readermc.org/images/thumbnails/$urlSorter.webp")
}
override fun searchMangaNextPageSelector() = latestUpdatesNextPageSelector()
override fun searchMangaNextPageSelector() = null
// Manga details
override fun mangaDetailsParse(document: Document): SManga {
@ -109,7 +145,7 @@ class MangaDemon : ParsedHttpSource() {
override fun chapterFromElement(element: Element): SChapter {
return SChapter.create().apply {
element.select("a").let { urlElement ->
url = (urlElement.attr("href"))
setUrlWithoutDomain(urlElement.attr("href"))
name = element.select("strong.chapter-title").text()
}
val date = element.select("time.chapter-update").text()
@ -131,13 +167,13 @@ class MangaDemon : ParsedHttpSource() {
}
override fun pageListParse(document: Document): List<Page> {
val baseImgs = document.select("img.imgholder")
val baseImages = document.select("img.imgholder")
.map { it.attr("abs:src") }
.toMutableList()
baseImgs.addAll(loadMoreImages(document))
baseImages.addAll(loadMoreImages(document))
return baseImgs.mapIndexed { i, img -> Page(i, "", img) }
return baseImages.mapIndexed { i, img -> Page(i, "", img) }
}
private fun loadMoreImages(document: Document): List<String> {

View File

@ -0,0 +1,93 @@
package eu.kanade.tachiyomi.extension.en.mangademon
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
abstract class SelectFilter(
name: String,
private val options: List<Pair<String, String>>,
) : Filter.Select<String>(
name,
options.map { it.first }.toTypedArray(),
) {
val selected get() = options[state].second
}
class StatusFilter : SelectFilter("Status", status) {
companion object {
private val status = listOf(
Pair("All", "all"),
Pair("Ongoing", "ongoing"),
Pair("Completed", "completed"),
)
}
}
class SortFilter : SelectFilter("Sort", sort) {
companion object {
private val sort = listOf(
Pair("Top Views", "VIEWS DESC"),
Pair("A To Z", "NAME ASC"),
)
}
}
class CheckBoxFilter(
name: String,
val value: String,
) : Filter.CheckBox(name)
class GenreFilter : Filter.Group<CheckBoxFilter>(
"Genre",
genres.map { CheckBoxFilter(it.first, it.second) },
) {
val checked get() = state.filter { it.state }.map { it.value }
companion object {
private val genres = listOf(
Pair("All", "all"),
Pair("Action", "1"),
Pair("Adventure", "2"),
Pair("Comedy", "3"),
Pair("Cooking", "34"),
Pair("Doujinshi", "25"),
Pair("Drama", "4"),
Pair("Ecchi", "19"),
Pair("Fantasy", "5"),
Pair("Gender Bender", "30"),
Pair("Harem", "10"),
Pair("Historical", "28"),
Pair("Horror", "8"),
Pair("Isekai", "33"),
Pair("Josei", "31"),
Pair("Martial Arts", "6"),
Pair("Mature", "22"),
Pair("Mecha", "32"),
Pair("Mystery", "15"),
Pair("One Shot", "26"),
Pair("Psychological", "11"),
Pair("Romance", "12"),
Pair("School Life", "13"),
Pair("Sci-fi", "16"),
Pair("Seinen", "17"),
Pair("Shoujo", "14"),
Pair("Shoujo Ai", "23"),
Pair("Shounen", "7"),
Pair("Shounen Ai", "29"),
Pair("Slice of Life", "21"),
Pair("Smut", "27"),
Pair("Sports", "20"),
Pair("Supernatural", "9"),
Pair("Tragedy", "18"),
Pair("Webtoons", "24"),
)
}
}
fun getFilters() = FilterList(
Filter.Header("Ignored when using text search"),
Filter.Separator(),
SortFilter(),
StatusFilter(),
GenreFilter(),
)