add filter on HeanCms , DoujinDesu.tv

Fix GetList GalleryAdultsParser
pull/401/head
devi 2 years ago
parent db770351f3
commit 7c2ac033d7

@ -24,36 +24,42 @@ internal abstract class GalleryAdultsParser(
override val configKeyDomain = ConfigKey.Domain(domain) override val configKeyDomain = ConfigKey.Domain(domain)
override val isMultipleTagsSupported = false override val isMultipleTagsSupported = false
override suspend fun getListPage( override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
page: Int,
query: String?,
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
val tag = tags.oneOrThrowIfMany()
val url = buildString { val url = buildString {
append("https://") append("https://")
append(domain) append(domain)
if (!tags.isNullOrEmpty()) { when (filter) {
if (tag?.key == "languageKey") { is MangaListFilter.Search -> {
append("/language") append("/search/?q=")
append(tag.title) append(filter.query.urlEncoded())
append("/?") append("&")
} else { }
append("/tag/")
append(tag?.key.orEmpty()) is MangaListFilter.Advanced -> {
append("/?") if (filter.tags.isNotEmpty()) {
filter.tags.oneOrThrowIfMany()?.let {
if (it.key == "languageKey") {
append("/language")
append(it.title)
append("/?")
} else {
append("/tag/")
append(it.key)
append("/?")
}
}
} else {
append("/?")
}
} }
} else if (!query.isNullOrEmpty()) {
append("/search/?q=") null -> append("/?")
append(query.urlEncoded())
append("&")
} else {
append("/?")
} }
append("page=") append("page=")
append(page) append(page)
} }
return parseMangaList(webClient.httpGet(url).parseHtml()) return parseMangaList(webClient.httpGet(url).parseHtml())
} }

@ -31,45 +31,58 @@ internal class Hentai3(context: MangaLoaderContext) :
"/japanese", "/japanese",
) )
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY) override val isMultipleTagsSupported = true
override suspend fun getListPage( override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
page: Int,
query: String?, override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
if (query.isNullOrEmpty() && tags != null && tags.size > 1) {
return getListPage(page, buildQuery(tags), emptySet(), sortOrder)
}
val url = buildString { val url = buildString {
append("https://") append("https://")
append(domain) append(domain)
if (!tags.isNullOrEmpty()) { when (filter) {
val tag = tags.single()
if (tag.key == "languageKey") { is MangaListFilter.Search -> {
append("/language") append("/search?q=")
append(tag.title) append(filter.query.urlEncoded())
} else { append("&page=")
append("/tags/") append(page.toString())
append(tag.key)
} }
append("/")
append(page) is MangaListFilter.Advanced -> {
if (sortOrder == SortOrder.POPULARITY) {
append("?sort=popular") if (filter.tags.isNotEmpty() && filter.tags.size > 1) {
append("/search?q=")
append(buildQuery(filter.tags))
if (filter.sortOrder == SortOrder.POPULARITY) {
append("&sort=popular")
}
append("&page=")
append(page.toString())
} else if (filter.tags.isNotEmpty()) {
filter.tags.oneOrThrowIfMany()?.let {
if (it.key == "languageKey") {
append("/language")
append(it.title)
} else {
append("/tags/")
append(it.key)
}
}
append("/")
append(page.toString())
if (filter.sortOrder == SortOrder.POPULARITY) {
append("?sort=popular")
}
} else {
append("/")
append(page)
}
} }
} else if (!query.isNullOrEmpty()) {
append("/search?q=") null -> {
append(query.urlEncoded()) append("/")
if (sortOrder == SortOrder.POPULARITY) { append(page)
append("&sort=popular")
} }
append("&page=")
append(page)
} else {
append("/")
append(page)
} }
} }
return parseMangaList(webClient.httpGet(url).parseHtml()) return parseMangaList(webClient.httpGet(url).parseHtml())

@ -32,40 +32,45 @@ internal class HentaiEnvy(context: MangaLoaderContext) :
"/portuguese", "/portuguese",
) )
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
override suspend fun getListPage( override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
page: Int,
query: String?,
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
val tag = tags.oneOrThrowIfMany()
val url = buildString { val url = buildString {
append("https://") append("https://")
append(domain) append(domain)
if (!tags.isNullOrEmpty()) { when (filter) {
if (tag?.key == "languageKey") { is MangaListFilter.Search -> {
append("/language") append("/search/?s_key=")
append(tag.title) append(filter.query.urlEncoded())
append("/?") append("&")
} else { }
append("/tag/")
append(tag?.key.orEmpty()) is MangaListFilter.Advanced -> {
if (sortOrder == SortOrder.POPULARITY) { if (filter.tags.isNotEmpty()) {
append("/popular") filter.tags.oneOrThrowIfMany()?.let {
if (it.key == "languageKey") {
append("/language")
append(it.title)
append("/?")
} else {
append("/tag/")
append(it.key)
if (filter.sortOrder == SortOrder.POPULARITY) {
append("/popular")
}
append("/?")
}
}
} else {
append("/?")
} }
append("/?")
} }
} else if (!query.isNullOrEmpty()) {
append("/search/?s_key=") null -> append("/?")
append(query.urlEncoded())
append("&")
} else {
append("/?")
} }
append("page=") append("page=")
append(page) append(page)
} }
return parseMangaList(webClient.httpGet(url).parseHtml()) return parseMangaList(webClient.httpGet(url).parseHtml())
} }

@ -25,7 +25,9 @@ internal class HentaiEra(context: MangaLoaderContext) :
"/russian", "/russian",
) )
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
override val isMultipleTagsSupported = true
override fun Element.parseTags() = select("a.tag, .gallery_title a").mapToSet { override fun Element.parseTags() = select("a.tag, .gallery_title a").mapToSet {
val key = it.attr("href").removeSuffix('/').substringAfterLast('/') val key = it.attr("href").removeSuffix('/').substringAfterLast('/')
@ -37,46 +39,54 @@ internal class HentaiEra(context: MangaLoaderContext) :
) )
} }
override suspend fun getListPage( override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
page: Int,
query: String?,
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
if (query.isNullOrEmpty() && tags != null && tags.size > 1) {
return getListPage(page, buildQuery(tags), emptySet(), sortOrder)
}
val url = buildString { val url = buildString {
append("https://") append("https://")
append(domain) append(domain)
if (!tags.isNullOrEmpty()) { when (filter) {
val tag = tags.single()
if (tag.key == "languageKey") { is MangaListFilter.Search -> {
append("/language") append("/search/?key=")
append(tag.title) append(filter.query.urlEncoded())
} else { append("&")
append("/tag/")
append(tag.key)
}
append("/")
if (sortOrder == SortOrder.POPULARITY) {
append("popular/")
} }
append("?")
} else if (!query.isNullOrEmpty()) { is MangaListFilter.Advanced -> {
append("/search/?key=") if (filter.tags.isNotEmpty() && filter.tags.size > 1) {
if (sortOrder == SortOrder.POPULARITY) { append("/search/?key=")
append(query.replace("&lt=1&dl=0&pp=0&tr=0", "&lt=0&dl=0&pp=1&tr=0")) if (filter.sortOrder == SortOrder.POPULARITY) {
} else { append(buildQuery(filter.tags).replace("&lt=1&dl=0&pp=0&tr=0", "&lt=0&dl=0&pp=1&tr=0"))
append(query) } else {
append(buildQuery(filter.tags))
}
append("&")
} else if (filter.tags.isNotEmpty()) {
filter.tags.oneOrThrowIfMany()?.let {
if (it.key == "languageKey") {
append("/language")
append(it.title)
} else {
append("/tag/")
append(it.key)
}
}
append("/")
if (filter.sortOrder == SortOrder.POPULARITY) {
append("popular/")
}
append("?")
} else {
append("/?")
}
} }
append("&")
} else { null -> append("/?")
append("/?")
} }
append("page=") append("page=")
append(page) append(page.toString())
} }
return parseMangaList(webClient.httpGet(url).parseHtml()) return parseMangaList(webClient.httpGet(url).parseHtml())
} }

@ -35,50 +35,60 @@ internal class HentaiForce(context: MangaLoaderContext) :
"/vietnamese", "/vietnamese",
) )
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY) override val isMultipleTagsSupported = true
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
override suspend fun getPageUrl(page: MangaPage): String { override suspend fun getPageUrl(page: MangaPage): String {
val doc = webClient.httpGet(page.url.toAbsoluteUrl(domain)).parseHtml() val doc = webClient.httpGet(page.url.toAbsoluteUrl(domain)).parseHtml()
return doc.selectFirstOrThrow(idImg).src() ?: doc.parseFailed("Image src not found") return doc.selectFirstOrThrow(idImg).src() ?: doc.parseFailed("Image src not found")
} }
override suspend fun getListPage( override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
page: Int,
query: String?,
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
if (query.isNullOrEmpty() && tags != null && tags.size > 1) {
return getListPage(page, buildQuery(tags), emptySet(), sortOrder)
}
val url = buildString { val url = buildString {
append("https://") append("https://")
append(domain) append(domain)
if (!tags.isNullOrEmpty()) { when (filter) {
val tag = tags.single() is MangaListFilter.Search -> {
if (tag.key == "languageKey") { append("/search?q=")
append("/language") append(filter.query.urlEncoded())
append(tag.title) append("&page=")
} else {
append("/tag/")
append(tag.key)
} }
if (sortOrder == SortOrder.POPULARITY) {
append("/popular") is MangaListFilter.Advanced -> {
} if (filter.tags.isNotEmpty() && filter.tags.size > 1) {
append("/") append("/search?q=")
} else if (!query.isNullOrEmpty()) { append(buildQuery(filter.tags))
append("/search?q=") if (filter.sortOrder == SortOrder.POPULARITY) {
append(query.urlEncoded()) append("&sort=popular")
if (sortOrder == SortOrder.POPULARITY) { }
append("&sort=popular") append("&page=")
} else if (filter.tags.isNotEmpty()) {
filter.tags.oneOrThrowIfMany()?.let {
if (it.key == "languageKey") {
append("/language")
append(it.title)
} else {
append("/tag/")
append(it.key)
}
}
append("/")
if (filter.sortOrder == SortOrder.POPULARITY) {
append("popular/")
}
append("?")
} else {
append("/page/")
}
} }
append("&page=")
} else { null -> append("/page/")
append("/page/")
} }
append(page) append(page.toString())
} }
return parseMangaList(webClient.httpGet(url).parseHtml()) return parseMangaList(webClient.httpGet(url).parseHtml())
} }

@ -32,59 +32,83 @@ internal class HentaiFox(context: MangaLoaderContext) :
"/vietnamese", "/vietnamese",
) )
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY) override val isMultipleTagsSupported = true
override suspend fun getListPage( override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
page: Int,
query: String?, override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
if (query.isNullOrEmpty() && tags != null && tags.size > 1) {
return getListPage(page, buildQuery(tags), emptySet(), sortOrder)
}
val url = buildString { val url = buildString {
append("https://") append("https://")
append(domain) append(domain)
if (!tags.isNullOrEmpty()) { when (filter) {
val tag = tags.single() is MangaListFilter.Search -> {
if (tag.key == "languageKey") { append("/search/?q=")
append("/language") append(filter.query.urlEncoded())
append(tag.title) if (page > 1) {
} else { append("&page=")
append("/tag/") append(page.toString())
append(tag.key) }
}
if (sortOrder == SortOrder.POPULARITY) {
append("/popular")
} }
if (page > 1) {
append("/pag/") is MangaListFilter.Advanced -> {
append(page) if (filter.tags.isNotEmpty() && filter.tags.size > 1) {
append("/") append("/search/?q=")
} append(buildQuery(filter.tags))
} else if (!query.isNullOrEmpty()) { if (page > 1) {
append("/search/?q=") append("&page=")
append(query.urlEncoded()) append(page.toString())
if (sortOrder == SortOrder.POPULARITY) { }
append("&sort=popular")
} if (filter.sortOrder == SortOrder.POPULARITY) {
if (page > 1) { append("&sort=popular")
append("&page=") }
append(page) } else if (filter.tags.isNotEmpty()) {
filter.tags.oneOrThrowIfMany()?.let {
if (it.key == "languageKey") {
append("/language")
append(it.title)
} else {
append("/tag/")
append(it.key)
}
}
append("/")
if (filter.sortOrder == SortOrder.POPULARITY) {
append("popular/")
}
if (page > 1) {
append("/pag/")
append(page.toString())
append("/")
}
} else {
if (page > 2) {
append("/pag/")
append(page.toString())
append("/")
} else if (page > 1) {
append("/page/")
append(page.toString())
append("/")
}
}
} }
} else {
if (page > 2) { null -> {
append("/pag/") if (page > 2) {
append(page) append("/pag/")
append("/") append(page.toString())
} else if (page > 1) { append("/")
append("/page/") } else if (page > 1) {
append(page) append("/page/")
append("/") append(page.toString())
append("/")
}
} }
} }
} }
return parseMangaList(webClient.httpGet(url).parseHtml()) return parseMangaList(webClient.httpGet(url).parseHtml())
} }

@ -27,50 +27,60 @@ internal class NHentaiParser(context: MangaLoaderContext) :
"/chinese", "/chinese",
) )
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
override val isMultipleTagsSupported = true
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
override suspend fun getListPage(
page: Int,
query: String?,
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
if (query.isNullOrEmpty() && tags != null && tags.size > 1) {
return getListPage(page, buildQuery(tags), emptySet(), sortOrder)
}
val url = buildString { val url = buildString {
append("https://") append("https://")
append(domain) append(domain)
if (!tags.isNullOrEmpty()) { when (filter) {
val tag = tags.single()
if (tag.key == "languageKey") { is MangaListFilter.Search -> {
append("/language") append("/search/?q=")
append(tag.title) append(filter.query.urlEncoded())
} else { append("&")
append("/tag/")
append(tag.key)
}
append("/")
if (sortOrder == SortOrder.POPULARITY) {
append("popular")
}
append("?")
} else if (!query.isNullOrEmpty()) {
append("/search/?q=")
append(query.urlEncoded())
if (sortOrder == SortOrder.POPULARITY) {
append("&sort=popular")
} }
append("&")
} else { is MangaListFilter.Advanced -> {
if (sortOrder == SortOrder.POPULARITY) { if (filter.tags.isNotEmpty() && filter.tags.size > 1) {
append("/?sort=popular&") append("/search/?q=")
} else { append(buildQuery(filter.tags))
append("/?") if (filter.sortOrder == SortOrder.POPULARITY) {
append("&sort=popular")
}
append("&")
} else if (filter.tags.isNotEmpty()) {
filter.tags.oneOrThrowIfMany()?.let {
if (it.key == "languageKey") {
append("/language")
append(it.title)
} else {
append("/tag/")
append(it.key)
}
}
append("/")
if (filter.sortOrder == SortOrder.POPULARITY) {
append("popular/")
}
append("?")
} else {
if (filter.sortOrder == SortOrder.POPULARITY) {
append("/?sort=popular&")
} else {
append("/?")
}
}
} }
null -> append("/?")
} }
append("page=") append("page=")
append(page) append(page.toString())
} }
return parseMangaList(webClient.httpGet(url).parseHtml()) return parseMangaList(webClient.httpGet(url).parseHtml())
} }

@ -33,33 +33,39 @@ internal class NHentaiUk(context: MangaLoaderContext) :
"/turkish", "/turkish",
) )
override suspend fun getListPage( override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
page: Int,
query: String?,
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
val tag = tags.oneOrThrowIfMany()
val url = buildString { val url = buildString {
append("https://") append("https://")
append(domain) append(domain)
if (!tags.isNullOrEmpty()) { when (filter) {
if (tag?.key == "languageKey") {
append("/language") is MangaListFilter.Search -> {
append(tag.title) throw IllegalArgumentException("Search is not supported by this source")
append("/?p=") }
} else {
append("/tag/") is MangaListFilter.Advanced -> {
append(tag?.key) if (filter.tags.isNotEmpty()) {
append("/?p=") filter.tags.oneOrThrowIfMany()?.let {
if (it.key == "languageKey") {
append("/language")
append(it.title)
} else {
append("/tag/")
append(it.key)
}
}
append("/?p=")
} else {
append("/home?p=")
}
} }
} else if (!query.isNullOrEmpty()) {
throw IllegalArgumentException("Search is not supported by this source") null -> append("/?")
} else {
append("/home?p=")
} }
append(page) append(page.toString())
} }
return parseMangaList(webClient.httpGet(url).parseHtml()) return parseMangaList(webClient.httpGet(url).parseHtml())
} }

@ -27,6 +27,8 @@ internal abstract class HeanCms(
SortOrder.POPULARITY, SortOrder.POPULARITY,
) )
override val availableStates: Set<MangaState> = EnumSet.allOf(MangaState::class.java)
override val headers: Headers = Headers.Builder() override val headers: Headers = Headers.Builder()
.add("User-Agent", UserAgents.CHROME_DESKTOP) .add("User-Agent", UserAgents.CHROME_DESKTOP)
.build() .build()
@ -34,50 +36,54 @@ internal abstract class HeanCms(
protected open val pathManga = "series" protected open val pathManga = "series"
//For some sources, you need to send a json. For the moment, this part only works in Get. ( ex source need json gloriousscan.com , omegascans.org ) //For some sources, you need to send a json. For the moment, this part only works in Get. ( ex source need json gloriousscan.com , omegascans.org )
override suspend fun getListPage( override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
page: Int,
query: String?,
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
var firstTag = false
val url = buildString { val url = buildString {
append("https://api.") append("https://api.")
append(domain) append(domain)
append("/query?query_string=") append("/query?query_string=")
when (filter) {
is MangaListFilter.Search -> {
append(filter.query.urlEncoded())
}
if (!query.isNullOrEmpty()) { is MangaListFilter.Advanced -> {
append(query.urlEncoded())
}
append("&series_status=All&order=desc&orderBy=") filter.states.oneOrThrowIfMany()?.let {
when (sortOrder) { append("&series_status=")
SortOrder.POPULARITY -> append("total_views") append(
SortOrder.UPDATED -> append("latest") when (it) {
SortOrder.NEWEST -> append("created_at") MangaState.ONGOING -> "Ongoing"
SortOrder.ALPHABETICAL -> append("title") MangaState.FINISHED -> "Completed"
else -> append("latest") MangaState.ABANDONED -> "Dropped"
} MangaState.PAUSED -> "Hiatus"
},
)
append("&series_type=Comic&page=")
append(page)
append("&perPage=12&tags_ids=")
append("[".urlEncoded())
if (!tags.isNullOrEmpty()) {
for (tag in tags) {
// Just to make it fit [1,2,44] ect
if (!firstTag) {
firstTag = true
} else {
append(",")
} }
append(tag.key) append("&order=desc")
append("&orderBy=")
when (filter.sortOrder) {
SortOrder.POPULARITY -> append("total_views")
SortOrder.UPDATED -> append("latest")
SortOrder.NEWEST -> append("created_at")
SortOrder.ALPHABETICAL -> append("title")
else -> append("latest")
}
append("&series_type=Comic&perPage=12")
append("&tags_ids=")
append("[".urlEncoded())
append(filter.tags.joinToString(",") { it.key })
append("]".urlEncoded())
} }
null -> {}
} }
append("]".urlEncoded()) append("&page=")
append(page.toString())
} }
val json = webClient.httpGet(url).parseJson() val json = webClient.httpGet(url).parseJson()
return json.getJSONArray("data").mapJSON { j -> return json.getJSONArray("data").mapJSON { j ->
val slug = j.getString("series_slug") val slug = j.getString("series_slug")
val urlManga = "https://$domain/$pathManga/$slug" val urlManga = "https://$domain/$pathManga/$slug"
@ -107,8 +113,10 @@ internal abstract class HeanCms(
source = source, source = source,
) )
} }
} }
protected open val datePattern = "yyyy-MM-dd" protected open val datePattern = "yyyy-MM-dd"
override suspend fun getDetails(manga: Manga): Manga { override suspend fun getDetails(manga: Manga): Manga {
val root = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml() val root = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()

@ -2,19 +2,10 @@ package org.koitharu.kotatsu.parsers.site.heancms.es
import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.ContentType import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.model.MangaState
import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.parsers.model.RATING_UNKNOWN
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.site.heancms.HeanCms import org.koitharu.kotatsu.parsers.site.heancms.HeanCms
import org.koitharu.kotatsu.parsers.util.domain
import org.koitharu.kotatsu.parsers.util.generateUid
import org.koitharu.kotatsu.parsers.util.json.mapJSON import org.koitharu.kotatsu.parsers.util.json.mapJSON
import org.koitharu.kotatsu.parsers.util.parseJson import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.urlEncoded
@MangaSourceParser("YUGEN_MANGAS_ES", "YugenMangas.lat", "es", ContentType.HENTAI) @MangaSourceParser("YUGEN_MANGAS_ES", "YugenMangas.lat", "es", ContentType.HENTAI)
internal class YugenMangasEs(context: MangaLoaderContext) : internal class YugenMangasEs(context: MangaLoaderContext) :
@ -22,46 +13,55 @@ internal class YugenMangasEs(context: MangaLoaderContext) :
private val domainAlt = "yugenmangas.net" private val domainAlt = "yugenmangas.net"
override suspend fun getListPage( override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
page: Int,
query: String?,
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
var firstTag = false
val url = buildString { val url = buildString {
append("https://api.") append("https://api.")
append(domainAlt) append(domainAlt)
append("/query?query_string=") append("/query?query_string=")
if (!query.isNullOrEmpty()) { when (filter) {
append(query.urlEncoded()) is MangaListFilter.Search -> {
} append(filter.query.urlEncoded())
append("&series_status=All&order=desc&orderBy=") }
when (sortOrder) {
SortOrder.POPULARITY -> append("total_views") is MangaListFilter.Advanced -> {
SortOrder.UPDATED -> append("latest")
SortOrder.NEWEST -> append("created_at") filter.states.oneOrThrowIfMany()?.let {
SortOrder.ALPHABETICAL -> append("title") append("&series_status=")
else -> append("latest") append(
} when (it) {
append("&series_type=Comic&page=") MangaState.ONGOING -> "Ongoing"
append(page) MangaState.FINISHED -> "Completed"
append("&perPage=12&tags_ids=") MangaState.ABANDONED -> "Dropped"
append("[".urlEncoded()) MangaState.PAUSED -> "Hiatus"
if (!tags.isNullOrEmpty()) { },
for (tag in tags) { )
// Just to make it fit [1,2,44] ect
if (!firstTag) {
firstTag = true
} else {
append(",")
} }
append(tag.key) append("&order=desc")
append("&orderBy=")
when (filter.sortOrder) {
SortOrder.POPULARITY -> append("total_views")
SortOrder.UPDATED -> append("latest")
SortOrder.NEWEST -> append("created_at")
SortOrder.ALPHABETICAL -> append("title")
else -> append("latest")
}
append("&series_type=Comic&perPage=12")
append("&tags_ids=")
append("[".urlEncoded())
append(filter.tags.joinToString(",") { it.key })
append("]".urlEncoded())
} }
null -> {}
} }
append("]".urlEncoded())
append("&page=")
append(page.toString())
} }
val json = webClient.httpGet(url).parseJson() val json = webClient.httpGet(url).parseJson()
return json.getJSONArray("data").mapJSON { j -> return json.getJSONArray("data").mapJSON { j ->
val slug = j.getString("series_slug") val slug = j.getString("series_slug")
val urlManga = "https://$domain/series/$slug" val urlManga = "https://$domain/series/$slug"

@ -5,6 +5,7 @@ import org.koitharu.kotatsu.parsers.PagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.* import org.koitharu.kotatsu.parsers.util.*
import java.lang.IllegalArgumentException
import java.text.DateFormat import java.text.DateFormat
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
@ -33,23 +34,24 @@ internal abstract class HeanCmsAlt(
protected open val selectManga = "div.grid.grid-cols-2 div:not([class]):contains(M)" protected open val selectManga = "div.grid.grid-cols-2 div:not([class]):contains(M)"
protected open val selectMangaTitle = "h5" protected open val selectMangaTitle = "h5"
override suspend fun getListPage( override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
page: Int,
query: String?,
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
// No search or tag
if (!query.isNullOrEmpty()) {
return emptyList()
}
val url = buildString { val url = buildString {
append("https://") append("https://")
append(domain) append(domain)
append(listUrl) append(listUrl)
when (filter) {
is MangaListFilter.Search -> {
throw IllegalArgumentException("Search is not supported by this source")
}
is MangaListFilter.Advanced -> {
}
null -> {}
}
if (page > 1) { if (page > 1) {
append("?page=") append("?page=")
append(page) append(page.toString())
} }
} }
val doc = webClient.httpGet(url).parseHtml() val doc = webClient.httpGet(url).parseHtml()

@ -18,6 +18,78 @@ class DoujinDesuParser(context: MangaLoaderContext) : PagedMangaParser(context,
override val availableSortOrders: Set<SortOrder> override val availableSortOrders: Set<SortOrder>
get() = EnumSet.of(SortOrder.UPDATED, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.POPULARITY) get() = EnumSet.of(SortOrder.UPDATED, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.POPULARITY)
override val availableStates: Set<MangaState> = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED)
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
val url = urlBuilder().apply {
addPathSegment("manga")
addPathSegment("page")
addPathSegment("$page/")
when (filter) {
is MangaListFilter.Search -> {
addQueryParameter("title", filter.query)
}
is MangaListFilter.Advanced -> {
addQueryParameter("title", "")
addQueryParameter(
"order",
when (filter.sortOrder) {
SortOrder.UPDATED -> "update"
SortOrder.POPULARITY -> "popular"
SortOrder.ALPHABETICAL -> "title"
SortOrder.NEWEST -> "latest"
else -> "latest"
},
)
filter.tags.forEach {
addEncodedQueryParameter("genre[]".urlEncoded(), it.key.urlEncoded())
}
filter.states.oneOrThrowIfMany()?.let {
addEncodedQueryParameter(
"statusx",
when (it) {
MangaState.ONGOING -> "Publishing"
MangaState.FINISHED -> "Finished"
else -> ""
},
)
}
}
null -> addQueryParameter("order", "update")
}
}.build()
return webClient.httpGet(url).parseHtml()
.requireElementById("archives")
.selectFirstOrThrow("div.entries")
.select(".entry")
.map {
val titleTag = it.selectFirstOrThrow(".metadata > a")
val relativeUrl = titleTag.attrAsRelativeUrl("href")
Manga(
id = generateUid(relativeUrl),
title = titleTag.attr("title"),
altTitle = null,
url = relativeUrl,
publicUrl = relativeUrl.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,
isNsfw = true,
coverUrl = it.selectFirst(".thumbnail > img")?.src().orEmpty(),
tags = emptySet(),
state = null,
author = null,
largeCoverUrl = null,
description = null,
source = source,
)
}
}
override suspend fun getDetails(manga: Manga): Manga { override suspend fun getDetails(manga: Manga): Manga {
val docs = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml().selectFirstOrThrow("#archive") val docs = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml().selectFirstOrThrow("#archive")
val chapterDateFormat = SimpleDateFormat("EEEE, dd MMMM yyyy", sourceLocale) val chapterDateFormat = SimpleDateFormat("EEEE, dd MMMM yyyy", sourceLocale)
@ -58,56 +130,6 @@ class DoujinDesuParser(context: MangaLoaderContext) : PagedMangaParser(context,
) )
} }
override suspend fun getListPage(
page: Int,
query: String?,
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
val url = urlBuilder().apply {
addPathSegment("manga")
addPathSegment("page")
addPathSegment("$page/")
val order = when (sortOrder) {
SortOrder.UPDATED -> "update"
SortOrder.POPULARITY -> "popular"
SortOrder.ALPHABETICAL -> "title"
SortOrder.NEWEST -> "latest"
else -> throw IllegalArgumentException("Sort order not supported")
}
addQueryParameter("order", order)
addQueryParameter("title", query.orEmpty())
tags?.forEach {
addEncodedQueryParameter("genre[]".urlEncoded(), it.key.urlEncoded())
}
}.build()
return webClient.httpGet(url).parseHtml()
.requireElementById("archives")
.selectFirstOrThrow("div.entries")
.select(".entry")
.map {
val titleTag = it.selectFirstOrThrow(".metadata > a")
val relativeUrl = titleTag.attrAsRelativeUrl("href")
Manga(
id = generateUid(relativeUrl),
title = titleTag.attr("title"),
altTitle = null,
url = relativeUrl,
publicUrl = relativeUrl.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,
isNsfw = true,
coverUrl = it.selectFirst(".thumbnail > img")?.src().orEmpty(),
tags = emptySet(),
state = null,
author = null,
largeCoverUrl = null,
description = null,
source = source,
)
}
}
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> { override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
val id = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml() val id = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml()
.requireElementById("reader") .requireElementById("reader")

Loading…
Cancel
Save