Merge pull request #413 from KotatsuApp/ZeistMangaParser
Add ZeistMangaParser
This commit is contained in:
@@ -35,13 +35,14 @@ import java.util.EnumSet
|
||||
import java.util.Locale
|
||||
|
||||
@MangaSourceParser("NINENINENINEHENTAI", "999Hentai", type = ContentType.HENTAI)
|
||||
internal class NineNineNineHentaiParser(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.NINENINENINEHENTAI, size), Interceptor {
|
||||
internal class NineNineNineHentaiParser(context: MangaLoaderContext) :
|
||||
PagedMangaParser(context, MangaSource.NINENINENINEHENTAI, size), Interceptor {
|
||||
|
||||
override val configKeyDomain = ConfigKey.Domain("999hentai.net")
|
||||
|
||||
override val availableSortOrders: EnumSet<SortOrder> = EnumSet.of(
|
||||
SortOrder.POPULARITY,
|
||||
SortOrder.NEWEST
|
||||
SortOrder.NEWEST,
|
||||
)
|
||||
|
||||
override val isMultipleTagsSupported = false
|
||||
@@ -50,7 +51,7 @@ internal class NineNineNineHentaiParser(context: MangaLoaderContext) : PagedMang
|
||||
Locale.ENGLISH,
|
||||
Locale.CHINESE,
|
||||
Locale.JAPANESE,
|
||||
Locale("es")
|
||||
Locale("es"),
|
||||
)
|
||||
|
||||
private fun Locale?.getSiteLang(): String {
|
||||
@@ -107,7 +108,7 @@ internal class NineNineNineHentaiParser(context: MangaLoaderContext) : PagedMang
|
||||
MangaTag(
|
||||
title = name.toCamelCase(),
|
||||
key = name,
|
||||
source = source
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -121,9 +122,11 @@ internal class NineNineNineHentaiParser(context: MangaLoaderContext) : PagedMang
|
||||
getSearchList(page, null, filter.locale, filter.tags, filter.sortOrder)
|
||||
}
|
||||
}
|
||||
|
||||
is MangaListFilter.Search -> {
|
||||
getSearchList(page, filter.query, null, null, filter.sortOrder)
|
||||
}
|
||||
|
||||
else -> {
|
||||
getPopularList(page, null)
|
||||
}
|
||||
@@ -132,7 +135,7 @@ internal class NineNineNineHentaiParser(context: MangaLoaderContext) : PagedMang
|
||||
|
||||
private suspend fun getPopularList(
|
||||
page: Int,
|
||||
locale: Locale?
|
||||
locale: Locale?,
|
||||
): List<Manga> {
|
||||
val query = """
|
||||
queryPopularChapters(
|
||||
@@ -268,7 +271,7 @@ internal class NineNineNineHentaiParser(context: MangaLoaderContext) : PagedMang
|
||||
val tags = entry.optJSONArray("tags")?.mapJSON {
|
||||
SiteTag(
|
||||
name = it.getString("tagName"),
|
||||
type = it.getStringOrNull("tagType")
|
||||
type = it.getStringOrNull("tagType"),
|
||||
)
|
||||
}
|
||||
return manga.copy(
|
||||
@@ -282,7 +285,7 @@ internal class NineNineNineHentaiParser(context: MangaLoaderContext) : PagedMang
|
||||
MangaTag(
|
||||
title = it.name.toCamelCase(),
|
||||
key = it.name,
|
||||
source = source
|
||||
source = source,
|
||||
)
|
||||
}.orEmpty(),
|
||||
state = null,
|
||||
@@ -307,15 +310,15 @@ internal class NineNineNineHentaiParser(context: MangaLoaderContext) : PagedMang
|
||||
|
||||
return@let locale.getDisplayLanguage(locale)
|
||||
},
|
||||
scanlator = when(entry.getStringOrNull("format")) {
|
||||
scanlator = when (entry.getStringOrNull("format")) {
|
||||
"artistcg" -> "ArtistCG"
|
||||
"gamecg" -> "GameCG"
|
||||
"imageset" -> "ImageSet"
|
||||
else -> entry.getStringOrNull("format")?.toCamelCase()
|
||||
},
|
||||
source = source
|
||||
)
|
||||
)
|
||||
source = source,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -383,7 +386,7 @@ internal class NineNineNineHentaiParser(context: MangaLoaderContext) : PagedMang
|
||||
id = generateUid(img),
|
||||
url = cdn + img,
|
||||
preview = cdn + imgS,
|
||||
source = source
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,4 +7,4 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
|
||||
@MangaSourceParser("VFSCAN", "VfScan", "fr")
|
||||
internal class VfScan(context: MangaLoaderContext) :
|
||||
MangaReaderParser(context, MangaSource.VFSCAN, "www.vfscan.com", pageSize = 18, searchPageSize = 18)
|
||||
MangaReaderParser(context, MangaSource.VFSCAN, "www.vfscan.cc", pageSize = 18, searchPageSize = 18)
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.mangareader.tr
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
|
||||
@MangaSourceParser("MANGAKINGS", "MangaKings", "tr")
|
||||
internal class MangaKings(context: MangaLoaderContext) :
|
||||
MangaReaderParser(context, MangaSource.MANGAKINGS, "mangakings.com.tr", pageSize = 20, searchPageSize = 10)
|
||||
@@ -0,0 +1,331 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga
|
||||
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import org.json.JSONArray
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Document
|
||||
import org.koitharu.kotatsu.parsers.ErrorMessages
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.getStringOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.json.toJSONList
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
internal abstract class ZeistMangaParser(
|
||||
context: MangaLoaderContext,
|
||||
source: MangaSource,
|
||||
domain: String,
|
||||
pageSize: Int = 12,
|
||||
) : PagedMangaParser(context, source, pageSize) {
|
||||
|
||||
override val configKeyDomain = ConfigKey.Domain(domain)
|
||||
|
||||
override val isMultipleTagsSupported = false
|
||||
|
||||
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
|
||||
|
||||
override val availableStates: Set<MangaState> =
|
||||
EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.ABANDONED)
|
||||
|
||||
protected open val datePattern = "yyyy-MM-dd"
|
||||
|
||||
@JvmField
|
||||
protected val ongoing: Set<String> = hashSetOf(
|
||||
"ongoing",
|
||||
"en curso",
|
||||
"ativo",
|
||||
"lançando",
|
||||
"مستمر",
|
||||
"devam ediyor",
|
||||
"güncel",
|
||||
)
|
||||
|
||||
@JvmField
|
||||
protected val finished: Set<String> = hashSetOf(
|
||||
"completed",
|
||||
"completo",
|
||||
"tamamlandı",
|
||||
)
|
||||
|
||||
@JvmField
|
||||
protected val abandoned: Set<String> = hashSetOf(
|
||||
"cancelled",
|
||||
"dropped",
|
||||
"dropado",
|
||||
"abandonado",
|
||||
"cancelado",
|
||||
)
|
||||
|
||||
@JvmField
|
||||
protected val paused: Set<String> = hashSetOf(
|
||||
"hiatus",
|
||||
)
|
||||
|
||||
protected open val sateOngoing: String = "Ongoing"
|
||||
protected open val sateFinished: String = "Completed"
|
||||
protected open val sateAbandoned: String = "Cancelled"
|
||||
|
||||
protected open val maxMangaResults: Int = 20
|
||||
|
||||
protected open val mangaCategory: String = "Series"
|
||||
|
||||
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
|
||||
val startIndex = maxMangaResults * (page - 1) + 1
|
||||
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
append("/feeds/posts/default/-/")
|
||||
when (filter) {
|
||||
|
||||
is MangaListFilter.Search -> {
|
||||
append(mangaCategory)
|
||||
append("?alt=json&orderby=published&max-results=")
|
||||
append((maxMangaResults + 1).toString())
|
||||
append("&start-index=")
|
||||
append(startIndex.toString())
|
||||
append("&q=label:")
|
||||
append(mangaCategory)
|
||||
append("+")
|
||||
append(filter.query.urlEncoded())
|
||||
}
|
||||
|
||||
is MangaListFilter.Advanced -> {
|
||||
|
||||
|
||||
if (filter.tags.isNotEmpty() && filter.states.isNotEmpty()) {
|
||||
throw IllegalArgumentException(ErrorMessages.FILTER_BOTH_STATES_GENRES_NOT_SUPPORTED)
|
||||
}
|
||||
|
||||
if (filter.tags.isNotEmpty()) {
|
||||
append(filter.tags.oneOrThrowIfMany()?.key.orEmpty())
|
||||
} else if (filter.states.isNotEmpty()) {
|
||||
append(
|
||||
filter.states.oneOrThrowIfMany().let {
|
||||
when (it) {
|
||||
MangaState.ONGOING -> sateOngoing
|
||||
MangaState.FINISHED -> sateFinished
|
||||
MangaState.ABANDONED -> sateAbandoned
|
||||
else -> mangaCategory
|
||||
}
|
||||
},
|
||||
)
|
||||
} else {
|
||||
append(mangaCategory)
|
||||
}
|
||||
|
||||
append("?alt=json&orderby=published&max-results=")
|
||||
append((maxMangaResults + 1).toString())
|
||||
append("&start-index=")
|
||||
append(startIndex.toString())
|
||||
}
|
||||
|
||||
null -> {
|
||||
append(mangaCategory)
|
||||
append("?alt=json&orderby=published&max-results=")
|
||||
append((maxMangaResults + 1).toString())
|
||||
append("&start-index=")
|
||||
append(startIndex.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val json = webClient.httpGet(url).parseJson().getJSONObject("feed")
|
||||
|
||||
return if (json.toString().contains("\"entry\":")) {
|
||||
parseMangaList(json.getJSONArray("entry"))
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun parseMangaList(json: JSONArray): List<Manga> {
|
||||
return json.toJSONList().map { j ->
|
||||
val name = j.getJSONObject("title").getString("\$t")
|
||||
val href =
|
||||
j.getJSONArray("link").toJSONList().first { it.getString("rel") == "alternate" }.getString("href")
|
||||
val urlImg = if (j.toString().contains("media\$thumbnail")) {
|
||||
j.getJSONObject("media\$thumbnail").getStringOrNull("url")
|
||||
?.replace("""/s.+?-c/""".toRegex(), "/w600/")
|
||||
?.replace("""=s(?!.*=s).+?-c$""".toRegex(), "=w600")
|
||||
?.replace("""/s.+?-c-rw/""".toRegex(), "/w600/")
|
||||
?.replace("""=s(?!.*=s).+?-c-rw$""".toRegex(), "=w600")
|
||||
} else {
|
||||
Jsoup.parse(j.getJSONObject("content").getString("\$t")).selectFirstOrThrow("img").attr("src")
|
||||
}
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
publicUrl = href,
|
||||
coverUrl = urlImg.orEmpty(),
|
||||
title = name,
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.selectFirstOrThrow("div.filter").select("ul li").mapNotNullToSet {
|
||||
MangaTag(
|
||||
key = it.selectFirstOrThrow("input").attr("value"),
|
||||
title = it.selectFirstOrThrow("label").text(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
protected open val selectTags = "article div.mt-15 a, .info-genre a"
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val state =
|
||||
doc.selectFirst("div.y6x11p:contains(Status) .dt")
|
||||
?: doc.selectFirst("div.y6x11p:contains(Estado) .dt")
|
||||
?: doc.selectFirst("ul.infonime li:contains(Status) span")
|
||||
?: doc.selectFirst("ul.infonime li:contains(Estado) span")
|
||||
?: doc.selectFirst("span.status-novel")
|
||||
val mangaState = state?.text()?.lowercase().let {
|
||||
when (it) {
|
||||
in ongoing -> MangaState.ONGOING
|
||||
in finished -> MangaState.FINISHED
|
||||
in abandoned -> MangaState.ABANDONED
|
||||
in paused -> MangaState.PAUSED
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
val desc = doc.getElementById("synopsis") ?: doc.getElementById("Sinopse") ?: doc.getElementById("sinopas")
|
||||
val chaptersDeferred = async { loadChapters(manga.url, doc) }
|
||||
manga.copy(
|
||||
tags = doc.select(selectTags).mapNotNullToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast("label/").substringBefore("?"),
|
||||
title = a.text().toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
description = desc?.text().orEmpty(),
|
||||
state = mangaState,
|
||||
chapters = chaptersDeferred.await(),
|
||||
)
|
||||
}
|
||||
|
||||
protected open suspend fun loadChapters(mangaUrl: String, doc: Document): List<MangaChapter> {
|
||||
|
||||
val feed = if (doc.getElementById("myUL") != null) {
|
||||
doc.requireElementById("myUL").selectFirstOrThrow("script").attr("src")
|
||||
.substringAfterLast("/-/").substringBefore("?").urlDecode()
|
||||
|
||||
} else if (doc.selectFirst("#latest > script") != null) {
|
||||
val chapterRegex = """label\s*=\s*'([^']+)'""".toRegex()
|
||||
val scriptSelector = "#latest > script"
|
||||
val script = doc.selectFirstOrThrow(scriptSelector)
|
||||
chapterRegex
|
||||
.find(script.html())
|
||||
?.groupValues?.get(1)
|
||||
?: throw Exception("Failed to find chapter feed")
|
||||
|
||||
} else if (doc.selectFirst("#clwd > script") != null) {
|
||||
val chapterRegex = """clwd\.run\('([^']+)'""".toRegex()
|
||||
val scriptSelector = "#clwd > script"
|
||||
val script = doc.selectFirstOrThrow(scriptSelector)
|
||||
chapterRegex
|
||||
.find(script.html())
|
||||
?.groupValues?.get(1)
|
||||
?: throw Exception("Failed to find chapter feed")
|
||||
|
||||
} else {
|
||||
doc.selectFirstOrThrow("script:containsData(var label_chapter)").data()
|
||||
.substringAfter("label_chapter = \"").substringBefore("\"")
|
||||
}
|
||||
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
append("/feeds/posts/default/-/")
|
||||
append(feed)
|
||||
append("?alt=json&orderby=published&max-results=9999")
|
||||
}
|
||||
val json =
|
||||
webClient.httpGet(url).parseJson().getJSONObject("feed").getJSONArray("entry").toJSONList().reversed()
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
return json.mapIndexedNotNull { i, j ->
|
||||
val name = j.getJSONObject("title").getString("\$t")
|
||||
val href =
|
||||
j.getJSONArray("link").toJSONList().first { it.getString("rel") == "alternate" }.getString("href")
|
||||
val dateText = j.getJSONObject("published").getString("\$t").substringBefore("T")
|
||||
val slug = mangaUrl.substringAfterLast('/')
|
||||
val slugChapter = href.substringAfterLast('/')
|
||||
if (slug == slugChapter) {
|
||||
return@mapIndexedNotNull null
|
||||
}
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
name = name,
|
||||
number = i + 1,
|
||||
branch = null,
|
||||
uploadDate = dateFormat.tryParse(dateText),
|
||||
scanlator = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
protected open val selectPage = "div.check-box img, article#reader .separator img, article.container .separator img"
|
||||
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
|
||||
val doc = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
|
||||
return if (doc.selectFirst("script:containsData(chapterImage =)") != null) {
|
||||
doc.selectFirstOrThrow("script:containsData(chapterImage =)").data()
|
||||
.substringAfter("[").substringBefore("]")
|
||||
.replace(" ", "").replace("\"", "")
|
||||
.split(",").map { url ->
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
preview = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
} else if (doc.selectFirst("script:containsData(const content = )") != null) {
|
||||
doc.selectFirstOrThrow("script:containsData(const content = )").data()
|
||||
.substringAfter("`").substringBefore("`;").split("src=\"").drop(1)
|
||||
|
||||
.map { img ->
|
||||
val url = img.substringBefore("\"")
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
preview = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
} else {
|
||||
doc.select(selectPage).map { img ->
|
||||
val url = img.src() ?: img.parseFailed("Image src not found")
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
preview = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.ar
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
|
||||
@MangaSourceParser("HIJALA", "Hijala", "ar")
|
||||
internal class Hijala(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.HIJALA, "hijala.blogspot.com")
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.ar
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
|
||||
@MangaSourceParser("LONERTL", "LonerTranslations", "ar")
|
||||
internal class LonerTl(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.LONERTL, "loner-tl.blogspot.com") {
|
||||
override val sateOngoing: String = "مستمرة"
|
||||
override val sateFinished: String = "مكتملة"
|
||||
override val sateAbandoned: String = "متوقفة"
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.ar
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.requireElementById
|
||||
|
||||
@MangaSourceParser("MANGAAILAND", "MangaAiLand", "ar")
|
||||
internal class MangaAiLand(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.MANGAAILAND, "manga-ai-land.blogspot.com") {
|
||||
override val sateOngoing: String = "مستمر"
|
||||
override val sateFinished: String = "مكتملة"
|
||||
override val sateAbandoned: String = "متوقفة"
|
||||
|
||||
override suspend fun getAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.requireElementById("LinkList1").select("ul li a").mapNotNullToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").substringBefore("?").substringAfterLast('/'),
|
||||
title = it.text(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.ar
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
|
||||
@MangaSourceParser("MANGASOUL", "MangaSoul", "ar")
|
||||
internal class MangaSoul(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.MANGASOUL, "www.manga-soul.com")
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.ar
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
|
||||
@MangaSourceParser("ROCKSMANGA_COM", "RocksManga.com", "ar")
|
||||
internal class RocksManga(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.ROCKSMANGA_COM, "www.rocks-manga.com")
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.ar
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
|
||||
@MangaSourceParser("YOKAITEAM", "YokaiTeam", "ar")
|
||||
internal class YokaiTeam(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.YOKAITEAM, "yokai-team.blogspot.com")
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.id
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
|
||||
@MangaSourceParser("ASUPANKOMIK", "AsupanKomik", "id")
|
||||
internal class AsupanKomik(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.ASUPANKOMIK, "www.asupankomik.my.id")
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.id
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.ContentType
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.requireElementById
|
||||
|
||||
@MangaSourceParser("KLMANHUA", "KlManhua", "id", ContentType.HENTAI)
|
||||
internal class KlManhua(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.KLMANHUA, "klmanhua.blogspot.com") {
|
||||
|
||||
override suspend fun getAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.requireElementById("LinkList1").select("ul li a").mapNotNullToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").substringBefore("?").substringAfterLast('/'),
|
||||
title = it.text(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.id
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
|
||||
@MangaSourceParser("KOMIKREALM", "KomikRealm", "id")
|
||||
internal class KomikRealm(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.KOMIKREALM, "www.komikrealm.my.id")
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.id
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.ContentType
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.requireElementById
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
|
||||
@MangaSourceParser("MIKOROKU", "Mikoroku", "id", ContentType.HENTAI)
|
||||
internal class Mikoroku(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.MIKOROKU, "www.mikoroku.web.id") {
|
||||
|
||||
override suspend fun getAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.requireElementById("Genre").select("div.items-center").mapNotNullToSet {
|
||||
MangaTag(
|
||||
key = it.selectFirstOrThrow("input").attr("value"),
|
||||
title = it.selectFirstOrThrow("label").text().substringBefore('('),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.id
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
|
||||
@MangaSourceParser("SHIYURASUB", "ShiyuraSub", "id")
|
||||
internal class ShiyuraSub(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.SHIYURASUB, "shiyurasub.blogspot.com") {
|
||||
|
||||
override val selectTags = ".leading-8 div.my-5.gap-2 a"
|
||||
|
||||
override suspend fun getAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.select("div.list-label-widget-content ul li a").mapNotNullToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
title = it.html().substringBefore("<span"),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.id
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
|
||||
@MangaSourceParser("SOBATMANKU", "Sobatmanku", "id")
|
||||
internal class Sobatmanku(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.SOBATMANKU, "www.sobatmanku19.site")
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.id
|
||||
|
||||
import org.jsoup.nodes.Document
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.ContentType
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
|
||||
@MangaSourceParser("TOONCUBUS", "ToonCubus", "id", ContentType.HENTAI)
|
||||
internal class ToonCubus(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.TOONCUBUS, "www.tooncubus.top") {
|
||||
override suspend fun getAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/p/genre-list.html").parseHtml()
|
||||
return doc.select(".dzdes-genre ul li a").mapNotNullToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").removeSuffix("/").substringAfterLast("/"),
|
||||
title = it.selectFirstOrThrow("span").text(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadChapters(mangaUrl: String, doc: Document): List<MangaChapter> {
|
||||
return doc.selectFirstOrThrow("ul.series-chapterlist").select("div.flexch-infoz")
|
||||
.mapChapters(reversed = true) { i, div ->
|
||||
val url = div.selectFirstOrThrow("a").attr("href")
|
||||
val name = div.selectFirstOrThrow("a span").text()
|
||||
MangaChapter(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
name = name,
|
||||
number = i + 1,
|
||||
branch = null,
|
||||
uploadDate = 0,
|
||||
scanlator = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.pt
|
||||
|
||||
import org.jsoup.nodes.Document
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
|
||||
@MangaSourceParser("ANIMEXNOVEL", "AnimeXNovel", "pt")
|
||||
internal class AnimeXNovel(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.ANIMEXNOVEL, "www.animexnovel.com") {
|
||||
|
||||
override val sateOngoing: String = "Ativo"
|
||||
override val sateFinished: String = "Completo"
|
||||
override val sateAbandoned: String = "Dropado"
|
||||
|
||||
override suspend fun getAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.requireElementById("LinkList1").select("ul li a").mapNotNullToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
title = it.text(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadChapters(mangaUrl: String, doc: Document): List<MangaChapter> {
|
||||
return doc.select("div:has(> .list-judul:contains(Lista de Capítulos)) div#latest ul > li, div.tab:has(> label:contains(Lista de Capítulos)) div.tab-content ul > li")
|
||||
.mapChapters(reversed = true) { i, li ->
|
||||
val url = li.selectFirstOrThrow("a").attr("href")
|
||||
val name = li.selectFirstOrThrow("a span").text()
|
||||
MangaChapter(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
name = name,
|
||||
number = i + 1,
|
||||
branch = null,
|
||||
uploadDate = 0,
|
||||
scanlator = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.pt
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
|
||||
@MangaSourceParser("ELEVENSCANLATOR", "ElevenScanlator", "pt")
|
||||
internal class ElevenScanlator(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.ELEVENSCANLATOR, "elevenscanlator.blogspot.com") {
|
||||
override val sateOngoing: String = "Lançando"
|
||||
override val sateFinished: String = "Completo"
|
||||
override val sateAbandoned: String = "Dropado"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.pt
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
|
||||
@MangaSourceParser("GALAXSCANS", "GalaxScans", "pt")
|
||||
internal class GalaxScans(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.GALAXSCANS, "galaxscans.blogspot.com") {
|
||||
override val mangaCategory = "Recentes"
|
||||
override val sateOngoing: String = "Lançando"
|
||||
override val sateFinished: String = "Completo"
|
||||
override val sateAbandoned: String = "Dropado"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.pt
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.requireElementById
|
||||
|
||||
@MangaSourceParser("GUILDATIERDRAW", "GuildaTierDraw", "pt")
|
||||
internal class GuildaTierDraw(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.GUILDATIERDRAW, "www.guildatierdraw.com") {
|
||||
|
||||
override suspend fun getAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.requireElementById("LinkList2").select("ul li a").mapNotNullToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").substringBefore("?").substringAfterLast('/'),
|
||||
title = it.text(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.pt
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
|
||||
@MangaSourceParser("MAXGSSCAN", "MaxgsScan", "pt")
|
||||
internal class MaxgsScan(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.MAXGSSCAN, "www.maxgsscan.online")
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.pt
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
|
||||
@MangaSourceParser("TYRANTSCANS", "TyrantScans", "pt")
|
||||
internal class TyrantScans(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.TYRANTSCANS, "www.tyrantscans.com")
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.pt
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
|
||||
@MangaSourceParser("WOLFSCANBR", "WolfScanBr", "pt")
|
||||
internal class WolfScanBr(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.WOLFSCANBR, "wolfscanbr.blogspot.com")
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.tr
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.requireElementById
|
||||
|
||||
@MangaSourceParser("EPIKMAN", "EpikMan", "tr")
|
||||
internal class EpikMan(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.EPIKMAN, "www.epikman.ga") {
|
||||
override val sateOngoing = "Devam Ediyor"
|
||||
override val sateFinished = "Tamamlandı"
|
||||
override val mangaCategory = "Seri"
|
||||
|
||||
override suspend fun getAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.requireElementById("LinkList1").select("ul li a").mapNotNullToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").substringBefore("?").substringAfterLast('/'),
|
||||
title = it.text(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.tr
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.ContentType
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
|
||||
@MangaSourceParser("MIKROKOSMOSFB", "Mikrokosmosfb", "tr", ContentType.HENTAI)
|
||||
internal class Mikrokosmosfb(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.MIKROKOSMOSFB, "mikrokosmosfb.blogspot.com") {
|
||||
override val sateOngoing: String = "Devam Ediyor"
|
||||
override val sateFinished: String = "Tamamlandı"
|
||||
override val sateAbandoned: String = "Güncel"
|
||||
|
||||
override suspend fun getAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
val tags = doc.selectFirstOrThrow("script:containsData(label: )").data()
|
||||
.substringAfter("label: [").substringBefore("]").replace("\"", "").split(", ")
|
||||
return tags.mapNotNullToSet {
|
||||
MangaTag(
|
||||
key = it,
|
||||
title = it,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.tr
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.ContentType
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
|
||||
@MangaSourceParser("SNSCOEURTURKEY", "SnscoeurTurkey", "tr", ContentType.HENTAI)
|
||||
internal class SnscoeurTurkey(context: MangaLoaderContext) :
|
||||
ZeistMangaParser(context, MangaSource.SNSCOEURTURKEY, "snscoeurturkey.blogspot.com") {
|
||||
override val sateOngoing: String = "Güncel"
|
||||
override val sateFinished: String = "Final"
|
||||
override val sateAbandoned: String = "Düzenleniyor"
|
||||
|
||||
override val mangaCategory = "Seriler"
|
||||
|
||||
override suspend fun getAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/p/gelismis-arama.html").parseHtml()
|
||||
return doc.selectFirstOrThrow("div.filter").select("ul li").mapNotNullToSet {
|
||||
MangaTag(
|
||||
key = it.selectFirstOrThrow("input").attr("value"),
|
||||
title = it.selectFirstOrThrow("label").text(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ package org.koitharu.kotatsu.parsers.util
|
||||
import androidx.annotation.FloatRange
|
||||
import androidx.collection.arraySetOf
|
||||
import java.math.BigInteger
|
||||
import java.net.URLDecoder
|
||||
import java.net.URLEncoder
|
||||
import java.security.MessageDigest
|
||||
import java.util.*
|
||||
@@ -98,6 +99,8 @@ fun String.splitTwoParts(delimiter: Char): Pair<String, String>? {
|
||||
|
||||
fun String.urlEncoded(): String = URLEncoder.encode(this, Charsets.UTF_8.name())
|
||||
|
||||
fun String.urlDecode(): String = URLDecoder.decode(this, Charsets.UTF_8.name())
|
||||
|
||||
fun ByteArray.byte2HexFormatted(): String {
|
||||
val str = StringBuilder(size * 2)
|
||||
for (i in indices) {
|
||||
|
||||
Reference in New Issue
Block a user