diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/ReaperComics.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/ReaperComics.kt index e25b1366..63cf8ea4 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/ReaperComics.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/ReaperComics.kt @@ -24,7 +24,13 @@ private const val MAX_RETRY_COUNT = 5 internal class ReaperComics(context: MangaLoaderContext) : PagedMangaParser(context, MangaParserSource.REAPERCOMICS, pageSize = 20) { - override val availableSortOrders: Set = EnumSet.of(SortOrder.UPDATED, SortOrder.ALPHABETICAL, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL_DESC) + override val availableSortOrders: Set = EnumSet.of( + SortOrder.UPDATED, + SortOrder.ALPHABETICAL, + SortOrder.POPULARITY, + SortOrder.NEWEST, + SortOrder.ALPHABETICAL_DESC, + ) override val configKeyDomain = ConfigKey.Domain("reaperscans.com") @@ -46,7 +52,7 @@ internal class ReaperComics(context: MangaLoaderContext) : } override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { - if(page > 1) return emptyList() + if (page > 1) return emptyList() val url = buildString { append("https://") @@ -154,7 +160,7 @@ internal class ReaperComics(context: MangaLoaderContext) : MangaTag( key = id, title = name.toTitleCase(sourceLocale), - source = source + source = source, ) } else { null @@ -168,6 +174,7 @@ internal class ReaperComics(context: MangaLoaderContext) : super.onCreateConfig(keys) keys.add(userAgentKey) } + private val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", sourceLocale) override suspend fun getDetails(manga: Manga): Manga { @@ -177,7 +184,8 @@ internal class ReaperComics(context: MangaLoaderContext) : val data = response.getJSONArray("data") return manga.copy( chapters = data.mapJSONIndexed { index, it -> - val chapterUrl = "/series/${it.getJSONObject("series").getString("series_slug")}/${it.getString("chapter_slug")}" + val chapterUrl = + "/series/${it.getJSONObject("series").getString("series_slug")}/${it.getString("chapter_slug")}" MangaChapter( id = it.getLong("id"), name = it.getString("chapter_name"), @@ -189,7 +197,7 @@ internal class ReaperComics(context: MangaLoaderContext) : branch = null, source = source, ) - } + }, ) } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/id/DoujinDesuParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/id/DoujinDesuParser.kt index 2c95a59a..9c6f3593 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/id/DoujinDesuParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/id/DoujinDesuParser.kt @@ -76,15 +76,14 @@ class DoujinDesuParser(context: MangaLoaderContext) : .requireElementById("archives") .selectFirstOrThrow("div.entries") .select(".entry") - .map { - val titleTag = it.selectFirstOrThrow(".metadata > a") - val relativeUrl = titleTag.attrAsRelativeUrl("href") + .mapNotNull { + val href = it.selectFirst(".metadata > a")?.attr("href") ?: return@mapNotNull null Manga( - id = generateUid(relativeUrl), - title = titleTag.attr("title"), + id = generateUid(href), + title = it.selectFirst(".metadata > a")?.attr("title").orEmpty(), altTitle = null, - url = relativeUrl, - publicUrl = relativeUrl.toAbsoluteUrl(domain), + url = href, + publicUrl = href.toAbsoluteUrl(domain), rating = RATING_UNKNOWN, isNsfw = true, coverUrl = it.selectFirst(".thumbnail > img")?.src().orEmpty(), diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/FireScans.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/FireScans.kt index 168e4b51..be614178 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/FireScans.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/FireScans.kt @@ -1,6 +1,5 @@ package org.koitharu.kotatsu.parsers.site.madara.en -import org.json.JSONObject import org.jsoup.nodes.Document import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser @@ -10,7 +9,7 @@ import org.koitharu.kotatsu.parsers.util.* @MangaSourceParser("FIRESCANS", "FireScans", "en") internal class FireScans(context: MangaLoaderContext) : - MadaraParser(context, MangaParserSource.FIRESCANS, "firescans.xyz", 10) { + MadaraParser(context, MangaParserSource.FIRESCANS, "firecomics.org", 10) { override fun parseMangaList(doc: Document): List { return doc.select("div.row.c-tabs-item__content").ifEmpty { @@ -53,37 +52,15 @@ internal class FireScans(context: MangaLoaderContext) : } } - override suspend fun getPages(chapter: MangaChapter): List { - val fullUrl = chapter.url.toAbsoluteUrl(domain) - val doc = webClient.httpGet(fullUrl).parseHtml() - val chapterProtector = doc.requireElementById("chapter-protector-data") - val chapterProtectorHtml = - context.decodeBase64(chapterProtector.attr("src").removePrefix("data:text/javascript;base64,")) - .toString(Charsets.UTF_8) - val password = chapterProtectorHtml.substringAfter("wpmangaprotectornonce='").substringBefore("';") - val chapterData = JSONObject( - chapterProtectorHtml.substringAfter("chapter_data='").substringBefore("';").replace("\\/", "/"), - ) - val unsaltedCiphertext = context.decodeBase64(chapterData.getString("ct")) - val salt = chapterData.getString("s").toString().decodeHex() - val ciphertext = "Salted__".toByteArray(Charsets.UTF_8) + salt + unsaltedCiphertext - val rawImgArray = CryptoAES(context).decrypt(context.encodeBase64(ciphertext), password) - val imgArrayString = rawImgArray.filterNot { c -> c == '[' || c == ']' || c == '\\' || c == '"' } - - return imgArrayString.split(",").map { url -> - MangaPage( - id = generateUid(url), - url = url, - preview = null, + override suspend fun getAvailableTags(): Set { + val doc = webClient.httpGet("https://$domain/?s=&post_type=wp-manga").parseHtml() + return doc.select("form.search-advanced-form div.form-group div.checkbox ").mapNotNullToSet { div -> + val key = div.selectFirst("input")?.attr("value") ?: return@mapNotNullToSet null + MangaTag( + key = key, + title = div.selectFirst("label")?.text() ?: key, source = source, ) } } - - private fun String.decodeHex(): ByteArray { - check(length % 2 == 0) { "Must have an even length" } - - return chunked(2).map { it.toInt(16).toByte() }.toByteArray() - } - } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/ImmortalUpdates.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/ImmortalUpdates.kt index b78962c5..c1920968 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/ImmortalUpdates.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/ImmortalUpdates.kt @@ -1,11 +1,13 @@ package org.koitharu.kotatsu.parsers.site.madara.en +import org.koitharu.kotatsu.parsers.Broken import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.MangaParserSource import org.koitharu.kotatsu.parsers.site.madara.MadaraParser -@MangaSourceParser("IMMORTALUPDATES", "Immortal Updates", "en") +@Broken // Redirect to @MortalsGroove +@MangaSourceParser("IMMORTALUPDATES", "ImmortalUpdates", "en") internal class ImmortalUpdates(context: MangaLoaderContext) : MadaraParser(context, MangaParserSource.IMMORTALUPDATES, "immortalupdates.com") { override val listUrl = "mangas/" diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/MortalsGroove.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/MortalsGroove.kt index 5cd2d0fa..eb43cbc2 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/MortalsGroove.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/MortalsGroove.kt @@ -5,7 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.MangaParserSource import org.koitharu.kotatsu.parsers.site.madara.MadaraParser -@MangaSourceParser("MORTALSGROOVE", "Mortals Groove", "en") +@MangaSourceParser("MORTALSGROOVE", "MortalsGroove", "en") internal class MortalsGroove(context: MangaLoaderContext) : MadaraParser(context, MangaParserSource.MORTALSGROOVE, "mortalsgroove.com") { override val postReq = true diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/MangasNoSekai.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/MangasNoSekai.kt index 567a922d..e75bf214 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/MangasNoSekai.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/MangasNoSekai.kt @@ -1,10 +1,98 @@ package org.koitharu.kotatsu.parsers.site.madara.es +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope +import org.jsoup.nodes.Document import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.exception.ParseException +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaChapter +import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.model.MangaParserSource +import org.koitharu.kotatsu.parsers.model.MangaState +import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.site.madara.MadaraParser +import org.koitharu.kotatsu.parsers.util.* +import java.text.SimpleDateFormat @MangaSourceParser("MANGASNOSEKAI", "MangasNoSekai", "es") internal class MangasNoSekai(context: MangaLoaderContext) : - MadaraParser(context, MangaParserSource.MANGASNOSEKAI, "mangasnosekai.com") + MadaraParser(context, MangaParserSource.MANGASNOSEKAI, "mangasnosekai.com") { + + override suspend fun getDetails(manga: Manga): Manga = coroutineScope { + val fullUrl = manga.url.toAbsoluteUrl(domain) + val doc = webClient.httpGet(fullUrl).parseHtml() + val body = doc.body() + val chaptersDeferred = async { loadChapters(manga.url, doc) } + manga.copy( + tags = doc.body().select("#section-sinopsis a[href*=genre]").mapNotNullToSet { a -> + MangaTag( + key = a.attr("href").removeSuffix("/").substringAfterLast('/'), + title = a.text().toTitleCase(), + source = source, + ) + }, + author = doc.selectFirst("section#section-sinopsis div.d-flex:has(div:contains(Autor)) p a")?.text() + .orEmpty(), + description = body.selectFirst("#section-sinopsis p")?.text().orEmpty(), + altTitle = doc.selectFirst("section#section-sinopsis div.d-flex:has(div:contains(Otros nombres)) p")?.text() + .orEmpty(), + state = body.selectFirst("section#section-sinopsis div.d-flex:has(div:contains(Estado)) p") + ?.let { + when (it.text()) { + in ongoing -> MangaState.ONGOING + in finished -> MangaState.FINISHED + in abandoned -> MangaState.ABANDONED + in paused -> MangaState.PAUSED + else -> null + } + }, + chapters = chaptersDeferred.await(), + ) + } + + // todo take other pages + override suspend fun loadChapters(mangaUrl: String, document: Document): List { + val dateFormat = SimpleDateFormat(datePattern, sourceLocale) + return document.select("div.container-capitulos div.contenedor-capitulo-miniatura") + .mapChapters(reversed = true) { i, div -> + val a = div.selectFirst("a") + val href = a?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link is missing") + val link = href + stylePage + val dateText = div.selectFirst("a div.chapter-text")?.text() + val name = div.selectFirst("a div.text-sm")?.text() ?: a.ownText() + MangaChapter( + id = generateUid(href), + url = link, + name = name, + number = i + 1f, + volume = 0, + branch = null, + uploadDate = parseChapterDate( + dateFormat, + dateText, + ), + scanlator = null, + source = source, + ) + } + } + + override suspend fun getPages(chapter: MangaChapter): List { + val fullUrl = chapter.url.toAbsoluteUrl(domain) + val doc = webClient.httpGet(fullUrl).parseHtml() + val root = doc.body().selectFirst("div.reading-content") + ?: throw ParseException("No image found, try to log in", fullUrl) + return root.select(selectPage).map { div -> + val img = div.selectFirstOrThrow("img") + val url = img.src()?.toRelativeUrl(domain) ?: div.parseFailed("Image src not found") + MangaPage( + id = generateUid(url), + url = url, + preview = null, + source = source, + ) + } + } +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/id/LumosKomik.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/id/LumosKomik.kt new file mode 100644 index 00000000..0e5b16b3 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/id/LumosKomik.kt @@ -0,0 +1,16 @@ +package org.koitharu.kotatsu.parsers.site.madara.id + +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.model.MangaParserSource +import org.koitharu.kotatsu.parsers.site.madara.MadaraParser +import java.util.* + +@MangaSourceParser("LUMOSKOMIK", "LumosKomik", "id") +internal class LumosKomik(context: MangaLoaderContext) : + MadaraParser(context, MangaParserSource.LUMOSKOMIK, "lumoskomik.com") { + override val tagPrefix = "genre/" + override val listUrl = "komik/" + override val datePattern = "dd MMMM yyyy" + override val sourceLocale: Locale = Locale.ENGLISH +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ja/MangaFenxi.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ja/MangaFenxi.kt index 8f1a790f..681e7f15 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ja/MangaFenxi.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ja/MangaFenxi.kt @@ -1,9 +1,22 @@ package org.koitharu.kotatsu.parsers.site.madara.ja +import org.jsoup.nodes.Document import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaParserSource +import org.koitharu.kotatsu.parsers.model.MangaState +import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.site.madara.MadaraParser +import org.koitharu.kotatsu.parsers.util.attrAsRelativeUrlOrNull +import org.koitharu.kotatsu.parsers.util.domain +import org.koitharu.kotatsu.parsers.util.generateUid +import org.koitharu.kotatsu.parsers.util.host +import org.koitharu.kotatsu.parsers.util.mapNotNullToSet +import org.koitharu.kotatsu.parsers.util.parseFailed +import org.koitharu.kotatsu.parsers.util.removeSuffix +import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl +import org.koitharu.kotatsu.parsers.util.toTitleCase import java.util.Locale @MangaSourceParser("MANGAFENXI", "MangaFenxi", "ja") @@ -11,4 +24,46 @@ internal class MangaFenxi(context: MangaLoaderContext) : MadaraParser(context, MangaParserSource.MANGAFENXI, "mangafenxi.net", 40) { override val sourceLocale: Locale = Locale.ENGLISH override val tagPrefix = "genres/" + + override fun parseMangaList(doc: Document): List { + return doc.select("div.row.c-tabs-item__content").ifEmpty { + doc.select("div.page-item-detail") + }.map { div -> + val href = div.selectFirst("a")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found") + val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary") + Manga( + id = generateUid(href), + url = href, + publicUrl = href.toAbsoluteUrl(div.host ?: domain), + coverUrl = div.selectFirst("img")?.attr("src")?.replace("-193x278", "").orEmpty(), + title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4") + ?: div.selectFirst(".manga-name") ?: div.selectFirst(".post-title"))?.text().orEmpty(), + altTitle = null, + rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f, + tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a -> + MangaTag( + key = a.attr("href").removeSuffix('/').substringAfterLast('/'), + title = a.text().ifEmpty { return@mapNotNullToSet null }.toTitleCase(), + source = source, + ) + }.orEmpty(), + author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(), + state = when ( + summary?.selectFirst(".mg_status") + ?.selectFirst(".summary-content") + ?.ownText() + .orEmpty() + ) { + in ongoing -> MangaState.ONGOING + in finished -> MangaState.FINISHED + in abandoned -> MangaState.ABANDONED + in paused -> MangaState.PAUSED + in upcoming -> MangaState.UPCOMING + else -> null + }, + source = source, + isNsfw = isNsfwSource, + ) + } + } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/pt/LimitedTimePoject.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/pt/LimitedTimePoject.kt new file mode 100644 index 00000000..e04f858b --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/pt/LimitedTimePoject.kt @@ -0,0 +1,14 @@ +package org.koitharu.kotatsu.parsers.site.madara.pt + +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.model.MangaParserSource +import org.koitharu.kotatsu.parsers.site.madara.MadaraParser + +@MangaSourceParser("LIMITEDTIMEPOJECT", "LimitedTimePoject", "pt") +internal class LimitedTimePoject(context: MangaLoaderContext) : + MadaraParser(context, MangaParserSource.LIMITEDTIMEPOJECT, "limitedtimeproject.com", 10) { + override val listUrl = "manhwa/" + override val tagPrefix = "manhwa-genero/" + override val datePattern = "dd 'de' MMMMM 'de' yyyy" +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/pt/DemonSect.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/pt/PussySussyToons.kt similarity index 50% rename from src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/pt/DemonSect.kt rename to src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/pt/PussySussyToons.kt index ba482fe3..582747cc 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/pt/DemonSect.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/pt/PussySussyToons.kt @@ -2,9 +2,10 @@ package org.koitharu.kotatsu.parsers.site.madara.pt 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.MangaParserSource import org.koitharu.kotatsu.parsers.site.madara.MadaraParser -@MangaSourceParser("DEMONSECT", "DemonSect", "pt") -internal class DemonSect(context: MangaLoaderContext) : - MadaraParser(context, MangaParserSource.DEMONSECT, "dsectcomics.org", 10) +@MangaSourceParser("PUSSYSUSSYTOONS", "PussySussyToons", "pt", ContentType.HENTAI) +internal class PussySussyToons(context: MangaLoaderContext) : + MadaraParser(context, MangaParserSource.PUSSYSUSSYTOONS, "pussy.sussytoons.com") diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/tr/MangaOkusana.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/tr/MangaOkusana.kt new file mode 100644 index 00000000..a5c3394a --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/tr/MangaOkusana.kt @@ -0,0 +1,12 @@ +package org.koitharu.kotatsu.parsers.site.madara.tr + +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.model.MangaParserSource +import org.koitharu.kotatsu.parsers.site.madara.MadaraParser + +@MangaSourceParser("MANGAOKUSANA", "MangaOkusana", "tr") +internal class MangaOkusana(context: MangaLoaderContext) : + MadaraParser(context, MangaParserSource.MANGAOKUSANA, "mangaokusana.com") { + override val datePattern = "dd MMMM yyyy" +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/AltayScans.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/AltayScans.kt new file mode 100644 index 00000000..41b4643c --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/AltayScans.kt @@ -0,0 +1,12 @@ +package org.koitharu.kotatsu.parsers.site.mangareader.en + +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.model.MangaParserSource +import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser + +@MangaSourceParser("ALTAYSCANS", "AltayScans", "en") +internal class AltayScans(context: MangaLoaderContext) : + MangaReaderParser(context, MangaParserSource.ALTAYSCANS, "altayscans.com", pageSize = 20, searchPageSize = 10) { + override val isTagsExclusionSupported = false +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/LuaComicCom.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/LuaComicCom.kt new file mode 100644 index 00000000..808f8efc --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/LuaComicCom.kt @@ -0,0 +1,12 @@ +package org.koitharu.kotatsu.parsers.site.mangareader.en + +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.model.MangaParserSource +import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser + +@MangaSourceParser("LUACOMIC_COM", "luaComic.com", "en") +internal class LuaComicCom(context: MangaLoaderContext) : + MangaReaderParser(context, MangaParserSource.LUACOMIC_COM, "luacomic.com", pageSize = 20, searchPageSize = 10) { + override val isTagsExclusionSupported = false +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/LuaScans.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/LuaScans.kt index 536ee42e..1a00088f 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/LuaScans.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/LuaScans.kt @@ -5,8 +5,8 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.MangaParserSource import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser -@MangaSourceParser("LUASCANS", "LuaScans", "en") +@MangaSourceParser("LUASCANS", "luaComic.net", "en") internal class LuaScans(context: MangaLoaderContext) : - MangaReaderParser(context, MangaParserSource.LUASCANS, "luacomic.com", pageSize = 20, searchPageSize = 10) { + MangaReaderParser(context, MangaParserSource.LUASCANS, "luacomic.net", pageSize = 20, searchPageSize = 10) { override val isTagsExclusionSupported = false } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/DoujinKu.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/DoujinKu.kt index 81878798..ba6aa8f6 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/DoujinKu.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/DoujinKu.kt @@ -5,11 +5,9 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.ContentType import org.koitharu.kotatsu.parsers.model.MangaParserSource import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser -import java.util.* @MangaSourceParser("DOUJINKU", "DoujinKu", "id", ContentType.HENTAI) internal class DoujinKu(context: MangaLoaderContext) : MangaReaderParser(context, MangaParserSource.DOUJINKU, "doujinku.org", pageSize = 20, searchPageSize = 10) { - override val sourceLocale: Locale = Locale.ENGLISH override val isTagsExclusionSupported = false } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Duniakomik.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Duniakomik.kt index 3b89b14d..fd5f1e83 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Duniakomik.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Duniakomik.kt @@ -1,11 +1,13 @@ package org.koitharu.kotatsu.parsers.site.mangareader.id +import org.koitharu.kotatsu.parsers.Broken 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.MangaParserSource import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser +@Broken @MangaSourceParser("DUNIAKOMIK", "DuniaKomik", "id", ContentType.HENTAI) internal class Duniakomik(context: MangaLoaderContext) : MangaReaderParser(context, MangaParserSource.DUNIAKOMIK, "duniakomik.org", pageSize = 12, searchPageSize = 12) { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/KiryuuParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/KiryuuParser.kt index 3414b12c..5586287d 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/KiryuuParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/KiryuuParser.kt @@ -7,6 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser @MangaSourceParser("KIRYUU", "Kiryuu", "id") internal class KiryuuParser(context: MangaLoaderContext) : - MangaReaderParser(context, MangaParserSource.KIRYUU, "kiryuu.id", pageSize = 30, searchPageSize = 10) { + MangaReaderParser(context, MangaParserSource.KIRYUU, "kiryuu.org", pageSize = 30, searchPageSize = 10) { override val isTagsExclusionSupported = false } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/KomikIndo.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/KomikIndo.kt new file mode 100644 index 00000000..7815d7fa --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/KomikIndo.kt @@ -0,0 +1,13 @@ +package org.koitharu.kotatsu.parsers.site.mangareader.id + +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.model.MangaParserSource +import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser +import java.util.Locale + +@MangaSourceParser("KOMIKINDO_MOE", "KomikIndo.moe", "id") +internal class KomikIndo(context: MangaLoaderContext) : + MangaReaderParser(context, MangaParserSource.KOMIKINDO_MOE, "komikindo.moe", pageSize = 20, searchPageSize = 10) { + override val sourceLocale: Locale = Locale.ENGLISH +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Manhwaku.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Manhwaku.kt new file mode 100644 index 00000000..ca038e15 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Manhwaku.kt @@ -0,0 +1,10 @@ +package org.koitharu.kotatsu.parsers.site.mangareader.id + +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.model.MangaParserSource +import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser + +@MangaSourceParser("MANHWAKU", "Manhwaku", "id") +internal class Manhwaku(context: MangaLoaderContext) : + MangaReaderParser(context, MangaParserSource.MANHWAKU, "manhwaku.id", pageSize = 20, searchPageSize = 10) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/pt/DemonSect.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/pt/DemonSect.kt new file mode 100644 index 00000000..6e2cf328 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/pt/DemonSect.kt @@ -0,0 +1,13 @@ +package org.koitharu.kotatsu.parsers.site.mangareader.pt + +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.model.MangaParserSource +import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser + +@MangaSourceParser("DEMONSECT", "DemonSect", "pt") +internal class DemonSect(context: MangaLoaderContext) : + MangaReaderParser(context, MangaParserSource.DEMONSECT, "dsectcomics.org", pageSize = 20, searchPageSize = 10) { + override val listUrl = "/comics" + override val isTagsExclusionSupported = false +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/CultureSubs.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/CultureSubs.kt new file mode 100644 index 00000000..7c3e6469 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/CultureSubs.kt @@ -0,0 +1,12 @@ +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.MangaParserSource +import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser + +@MangaSourceParser("CULTURESUBS", "CultureSubs", "tr") +internal class CultureSubs(context: MangaLoaderContext) : + MangaReaderParser(context, MangaParserSource.CULTURESUBS, "culturesubs.com", pageSize = 20, searchPageSize = 10) { + override val isMultipleTagsSupported = false +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/fr/MangaScan.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/fr/MangaScan.kt index 62a8ad5e..bf7b9c57 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/fr/MangaScan.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/fr/MangaScan.kt @@ -8,7 +8,7 @@ import java.util.* @MangaSourceParser("MANGA_SCAN", "MangaScan", "fr") internal class MangaScan(context: MangaLoaderContext) : - MmrcmsParser(context, MangaParserSource.MANGA_SCAN, "mangascan-fr.co") { + MmrcmsParser(context, MangaParserSource.MANGA_SCAN, "mangascan-fr.net") { override val imgUpdated = ".jpg" override val sourceLocale: Locale = Locale.ENGLISH } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/fr/MangaScanFr.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/fr/MangaScanFr.kt deleted file mode 100644 index 39ff2bee..00000000 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/fr/MangaScanFr.kt +++ /dev/null @@ -1,14 +0,0 @@ -package org.koitharu.kotatsu.parsers.site.mmrcms.fr - -import org.koitharu.kotatsu.parsers.MangaLoaderContext -import org.koitharu.kotatsu.parsers.MangaSourceParser -import org.koitharu.kotatsu.parsers.model.MangaParserSource -import org.koitharu.kotatsu.parsers.site.mmrcms.MmrcmsParser -import java.util.* - -@MangaSourceParser("MANGASCANFR", "MangaScanFr", "fr") -internal class MangaScanFr(context: MangaLoaderContext) : - MmrcmsParser(context, MangaParserSource.MANGASCANFR, "mangascan-fr.net") { - override val sourceLocale: Locale = Locale.ENGLISH - override val imgUpdated = ".jpg" -} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/WpComicsParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/WpComicsParser.kt index a20f8545..74084154 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/WpComicsParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/WpComicsParser.kt @@ -141,15 +141,17 @@ internal abstract class WpComicsParser( protected open fun parseMangaList(doc: Document, tagMap: ArrayMap): List { return doc.select("div.items div.item").mapNotNull { item -> - val tooltipElement = item.selectFirst("div.box_tootip") ?: return@mapNotNull null + val tooltipElement = item.selectFirst("div.box_tootip") val absUrl = item.selectFirst("div.image > a")?.attrAsAbsoluteUrlOrNull("href") ?: return@mapNotNull null val slug = absUrl.substringAfterLast('/') - val mangaState = when (tooltipElement.selectFirst("div.message_main > p:contains(Tình trạng)")?.ownText()) { - in ongoing -> MangaState.ONGOING - in finished -> MangaState.FINISHED - else -> null - } - val tagsElement = tooltipElement.selectFirst("div.message_main > p:contains(Thể loại)")?.ownText().orEmpty() + val mangaState = + when (tooltipElement?.selectFirst("div.message_main > p:contains(Tình trạng)")?.ownText()) { + in ongoing -> MangaState.ONGOING + in finished -> MangaState.FINISHED + else -> null + } + val tagsElement = + tooltipElement?.selectFirst("div.message_main > p:contains(Thể loại)")?.ownText().orEmpty() val mangaTags = tagsElement.split(',').mapNotNullToSet { tagMap[it.trim()] } Manga( id = generateUid(slug), @@ -163,8 +165,8 @@ internal abstract class WpComicsParser( largeCoverUrl = null, tags = mangaTags, state = mangaState, - author = tooltipElement.selectFirst("div.message_main > p:contains(Tác giả)")?.ownText(), - description = tooltipElement.selectFirst("div.box_text")?.text(), + author = tooltipElement?.selectFirst("div.message_main > p:contains(Tác giả)")?.ownText(), + description = tooltipElement?.selectFirst("div.box_text")?.text(), chapters = null, source = source, ) @@ -180,8 +182,8 @@ internal abstract class WpComicsParser( return tagSet } - private val mutex = Mutex() - private var tagCache: ArrayMap? = null + protected open val mutex = Mutex() + protected open var tagCache: ArrayMap? = null protected open suspend fun getOrCreateTagMap(): ArrayMap = mutex.withLock { tagCache?.let { return@withLock it } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyen.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyen.kt index 101ef545..cb78f158 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyen.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyen.kt @@ -8,8 +8,8 @@ import org.koitharu.kotatsu.parsers.site.wpcomics.WpComicsParser @MangaSourceParser("NETTRUYEN", "NetTruyen", "vi") internal class NetTruyen(context: MangaLoaderContext) : - WpComicsParser(context, MangaParserSource.NETTRUYEN, "nettruyenaa.com") { + WpComicsParser(context, MangaParserSource.NETTRUYEN, "www.nettruyenupp.com", 44) { override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain( - "nettruyenssr.com", + "www.nettruyenupp.com", "nettruyenaa.com", "nettruyenx.com", ) } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenSSR.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenSSR.kt new file mode 100644 index 00000000..2ba18284 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenSSR.kt @@ -0,0 +1,136 @@ +package org.koitharu.kotatsu.parsers.site.wpcomics.vi + +import androidx.collection.ArrayMap +import kotlinx.coroutines.sync.withLock +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.exception.NotFoundException +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaListFilter +import org.koitharu.kotatsu.parsers.model.MangaParserSource +import org.koitharu.kotatsu.parsers.model.MangaState +import org.koitharu.kotatsu.parsers.model.MangaTag +import org.koitharu.kotatsu.parsers.model.SortOrder +import org.koitharu.kotatsu.parsers.site.wpcomics.WpComicsParser +import org.koitharu.kotatsu.parsers.util.* +import java.util.EnumSet + +@MangaSourceParser("NETTRUYENSSR", "NetTruyenSSR", "vi") +internal class NetTruyenSSR(context: MangaLoaderContext) : + WpComicsParser(context, MangaParserSource.NETTRUYENSSR, "nettruyenssr.com", 20) { + + override val isMultipleTagsSupported = true + override val isTagsExclusionSupported = true + override val listUrl = "/tim-kiem-nang-cao" + override val availableStates: Set = + EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.PAUSED, MangaState.ABANDONED) + override val availableSortOrders: Set = EnumSet.allOf(SortOrder::class.java) + + override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { + val response = + when (filter) { + is MangaListFilter.Search -> { + val url = buildString { + append("https://") + append(domain) + append("/search") + append('/') + append(page.toString()) + append('/') + append("?keyword=") + append(filter.query.urlEncoded()) + } + + val result = runCatchingCancellable { webClient.httpGet(url) } + val exception = result.exceptionOrNull() + if (exception is NotFoundException) { + return emptyList() + } + result.getOrThrow() + } + + is MangaListFilter.Advanced -> { + val url = buildString { + append("https://") + append(domain) + append(listUrl) + + append('/') + append(page.toString()) + append('/') + + val tagQuery = filter.tags.joinToString(",") { it.key } + append("?genres=") + append(tagQuery) + + val tagQueryExclude = filter.tagsExclude.joinToString(",") { it.key } + append("¬Genres=") + append(tagQueryExclude) + + append("&sex=All") + + filter.states.oneOrThrowIfMany()?.let { + append("&status=") + append( + when (it) { + MangaState.ONGOING -> "on-going" + MangaState.FINISHED -> "completed" + MangaState.PAUSED -> "on-hold" + MangaState.ABANDONED -> "canceled" + else -> "-1" + }, + ) + } + + append("&chapter_count=0") + + append("&sort=") + append( + when (filter.sortOrder) { + SortOrder.UPDATED -> "latest-updated" + SortOrder.POPULARITY -> "views" + SortOrder.NEWEST -> "new" + SortOrder.RATING -> "score" + SortOrder.ALPHABETICAL -> "az" + SortOrder.ALPHABETICAL_DESC -> "za" + }, + ) + } + + webClient.httpGet(url) + } + + null -> { + val url = buildString { + append("https://") + append(domain) + append(listUrl) + append('/') + append(page.toString()) + append('/') + append("?genres=¬Genres=&sex=All&status=&chapter_count=0&sort=latest-updated") + } + webClient.httpGet(url) + } + } + + val tagMap = getOrCreateTagMap() + return parseMangaList(response.parseHtml(), tagMap) + } + + override suspend fun getOrCreateTagMap(): ArrayMap = mutex.withLock { + tagCache?.let { return@withLock it } + val doc = webClient.httpGet(listUrl.toAbsoluteUrl(domain)).parseHtml() + val tagItems = doc.select("div.genre-item") + val result = ArrayMap(tagItems.size) + for (item in tagItems) { + val title = item.text() + val key = item.selectFirstOrThrow("span").attr("data-id") + if (key.isNotEmpty() && title.isNotEmpty()) { + result[title] = MangaTag(title = title, key = key, source = source) + } + } + tagCache = result + result + } +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NhatTruyenVN.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NhatTruyenVN.kt index 6530654f..314b0a14 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NhatTruyenVN.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NhatTruyenVN.kt @@ -2,9 +2,14 @@ package org.koitharu.kotatsu.parsers.site.wpcomics.vi import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.model.MangaParserSource import org.koitharu.kotatsu.parsers.site.wpcomics.WpComicsParser @MangaSourceParser("NHATTRUYENVN", "NhatTruyenVN", "vi") -internal class NhattruyenVN(context: MangaLoaderContext) : - WpComicsParser(context, MangaParserSource.NHATTRUYENVN, "nhattruyenvn.com") +internal class NhatTruyenVN(context: MangaLoaderContext) : + WpComicsParser(context, MangaParserSource.NHATTRUYENVN, "nhattruyenvn.com", 36) { + override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain( + "nhattruyenvn.com", "www.nhattruyenss.net", + ) +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/zeistmanga/ZeistMangaParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/zeistmanga/ZeistMangaParser.kt index 2ba778ec..7729a4b4 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/zeistmanga/ZeistMangaParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/zeistmanga/ZeistMangaParser.kt @@ -159,7 +159,7 @@ internal abstract class ZeistMangaParser( ?.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") + Jsoup.parse(j.getJSONObject("content").getString("\$t")).selectFirst("img")?.attr("src") } Manga( id = generateUid(href), diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/zeistmanga/id/Magerin.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/zeistmanga/id/Magerin.kt new file mode 100644 index 00000000..e32d00b9 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/zeistmanga/id/Magerin.kt @@ -0,0 +1,11 @@ +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.MangaParserSource +import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser + + +@MangaSourceParser("MAGERIN", "Magerin", "id") +internal class Magerin(context: MangaLoaderContext) : + ZeistMangaParser(context, MangaParserSource.MAGERIN, "www.magerin.com") diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/zeistmanga/tr/HyperionScans.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/zeistmanga/tr/HyperionScans.kt new file mode 100644 index 00000000..7507a09a --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/zeistmanga/tr/HyperionScans.kt @@ -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.MangaParserSource +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("HYPERIONSCANS", "HyperionScans", "tr") +internal class HyperionScans(context: MangaLoaderContext) : + ZeistMangaParser(context, MangaParserSource.HYPERIONSCANS, "www.hyperionscans.site") { + override val sateOngoing: String = "Devam Ediyor" + override val sateFinished: String = "Tamamlandı" + override val sateAbandoned: String = "Güncel" + + override suspend fun getAvailableTags(): Set { + 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, + ) + } + } +}