Fix broken search and chapter images at MP. (#7580)

This commit is contained in:
Alessandro Jean 2021-06-09 18:46:25 -03:00 committed by GitHub
parent d6cd87b712
commit ca27731aa8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 186 additions and 206 deletions

View File

@ -6,7 +6,7 @@ ext {
extName = 'MangaPark v3' extName = 'MangaPark v3'
pkgNameSuffix = 'all.mangapark' pkgNameSuffix = 'all.mangapark'
extClass = '.MangaParkFactory' extClass = '.MangaParkFactory'
extVersionCode = 5 extVersionCode = 6
libVersion = '1.2' libVersion = '1.2'
containsNsfw = true containsNsfw = true
} }

View File

@ -14,50 +14,50 @@ import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.buildJsonObject import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.jsonArray import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.json.put import kotlinx.serialization.json.put
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Request import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.util.Calendar
import java.util.concurrent.TimeUnit
import okhttp3.Response
import rx.Observable import rx.Observable
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.util.Calendar
import java.util.concurrent.TimeUnit
open class MangaPark( open class MangaPark(
override val lang: String, override val lang: String,
private val siteLang: String private val siteLang: String
) : ParsedHttpSource() { ) : ParsedHttpSource() {
override val name : String = "MangaPark v3" override val name: String = "MangaPark v3"
override val baseUrl : String = "https://mangapark.net" override val baseUrl: String = "https://mangapark.net"
override val supportsLatest = true override val supportsLatest = true
private val json : Json by injectLazy() private val json: Json by injectLazy()
override val client : OkHttpClient = network.cloudflareClient.newBuilder() override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.connectTimeout(10, TimeUnit.SECONDS) .connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS)
.build() .build()
override fun latestUpdatesRequest(page: Int): Request { override fun latestUpdatesRequest(page: Int): Request {
return GET("$baseUrl/browse?sort=update&page=$page") return GET("$baseUrl/browse?sort=update&page=$page")
} }
override fun latestUpdatesSelector(): String { override fun latestUpdatesSelector(): String {
return "div#subject-list div.col" return "div#subject-list div.col"
} }
override fun latestUpdatesFromElement(element: Element): SManga { override fun latestUpdatesFromElement(element: Element): SManga {
return SManga.create().apply { return SManga.create().apply {
setUrlWithoutDomain(element.select("a.fw-bold").attr("href")) setUrlWithoutDomain(element.select("a.fw-bold").attr("href"))
@ -65,19 +65,19 @@ open class MangaPark(
thumbnail_url = element.select("a.position-relative img").attr("abs:src") thumbnail_url = element.select("a.position-relative img").attr("abs:src")
} }
} }
override fun latestUpdatesNextPageSelector() = "div#mainer nav.d-none .pagination .page-item:last-of-type:not(.disabled)" override fun latestUpdatesNextPageSelector() = "div#mainer nav.d-none .pagination .page-item:last-of-type:not(.disabled)"
override fun popularMangaRequest(page: Int): Request { override fun popularMangaRequest(page: Int): Request {
return GET("$baseUrl/browse?sort=d007&page=$page") return GET("$baseUrl/browse?sort=d007&page=$page")
} }
override fun popularMangaSelector() = latestUpdatesSelector() override fun popularMangaSelector() = latestUpdatesSelector()
override fun popularMangaFromElement(element: Element) = latestUpdatesFromElement(element) override fun popularMangaFromElement(element: Element) = latestUpdatesFromElement(element)
override fun popularMangaNextPageSelector() = latestUpdatesNextPageSelector() override fun popularMangaNextPageSelector() = latestUpdatesNextPageSelector()
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> { override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
return when { return when {
query.startsWith(PREFIX_ID_SEARCH) -> { query.startsWith(PREFIX_ID_SEARCH) -> {
@ -87,15 +87,15 @@ open class MangaPark(
mangaFromID(response, id) mangaFromID(response, id)
} }
} }
query.isNotBlank() -> { query.isNotBlank() -> {
val url = "$baseUrl/search?word=$query&page=$page" val url = "$baseUrl/search?word=$query&page=$page"
client.newCall(GET(url, headers)).asObservableSuccess() client.newCall(GET(url, headers)).asObservableSuccess()
.map { response -> .map { response ->
searchParse(response) searchMangaParse(response)
} }
} }
else -> { else -> {
val sortFilter = filters.findInstance<SortFilter>()!! val sortFilter = filters.findInstance<SortFilter>()!!
val reverseSortFilter = filters.findInstance<ReverseSortFilter>()!! val reverseSortFilter = filters.findInstance<ReverseSortFilter>()!!
@ -105,21 +105,22 @@ open class MangaPark(
val maxChapterFilter = filters.findInstance<MaxChapterTextFilter>()!! val maxChapterFilter = filters.findInstance<MaxChapterTextFilter>()!!
val url = "$baseUrl/browse".toHttpUrlOrNull()!!.newBuilder() val url = "$baseUrl/browse".toHttpUrlOrNull()!!.newBuilder()
url.addQueryParameter("page", page.toString()) url.addQueryParameter("page", page.toString())
with (sortFilter) { with(sortFilter) {
if (reverseSortFilter.state) { if (reverseSortFilter.state) {
url.addQueryParameter("sort","${this.selected}.az") url.addQueryParameter("sort", "${this.selected}.az")
} else { } else {
url.addQueryParameter("sort","${this.selected}.za") url.addQueryParameter("sort", "${this.selected}.za")
} }
} }
with (genreFilter) { with(genreFilter) {
url.addQueryParameter("genres", included.joinToString(",") + "|" + excluded.joinToString(",") url.addQueryParameter(
"genres", included.joinToString(",") + "|" + excluded.joinToString(",")
) )
} }
with (statusFilter) { with(statusFilter) {
url.addQueryParameter("release", this.selected) url.addQueryParameter("release", this.selected)
} }
@ -129,12 +130,12 @@ open class MangaPark(
client.newCall(GET(url.build().toString(), headers)).asObservableSuccess() client.newCall(GET(url.build().toString(), headers)).asObservableSuccess()
.map { response -> .map { response ->
searchParse(response) searchMangaParse(response)
} }
} }
} }
} }
private fun mangaFromID(response: Response, id: String): MangasPage { private fun mangaFromID(response: Response, id: String): MangasPage {
val infoElement = response.asJsoup().select("div#mainer div.container-fluid") val infoElement = response.asJsoup().select("div#mainer div.container-fluid")
val manga = SManga.create().apply { val manga = SManga.create().apply {
@ -146,41 +147,30 @@ open class MangaPark(
return MangasPage(listOf(manga), false) return MangasPage(listOf(manga), false)
} }
private fun searchParse(response: Response): MangasPage {
val mangas = mutableListOf<SManga>()
response.asJsoup().select("div#search-list div.col").forEach { element ->
mangas.add(latestUpdatesFromElement(element))
}
val nextPage = response.asJsoup().select(latestUpdatesNextPageSelector()).first() != null
return MangasPage(mangas, nextPage)
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = throw UnsupportedOperationException("Not used") override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = throw UnsupportedOperationException("Not used")
override fun searchMangaSelector() = throw UnsupportedOperationException("Not used")
override fun searchMangaFromElement(element: Element) = throw UnsupportedOperationException("Not used") override fun searchMangaSelector() = "div#search-list div.col"
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException("Not used")
override fun searchMangaFromElement(element: Element) = latestUpdatesFromElement(element)
override fun searchMangaNextPageSelector() = latestUpdatesNextPageSelector()
override fun mangaDetailsParse(document: Document): SManga { override fun mangaDetailsParse(document: Document): SManga {
val infoElement = document.select("div#mainer div.container-fluid") val infoElement = document.select("div#mainer div.container-fluid")
val genreList = mutableListOf<String>()
val statusStr = infoElement.select("div.attr-item:contains(status) span").text() val statusStr = infoElement.select("div.attr-item:contains(status) span").text()
infoElement.select("div.attr-item:contains(genres) span span").forEach { element ->
genreList.add(element.text())
}
return SManga.create().apply { return SManga.create().apply {
title = infoElement.select("h3.item-title").text() title = infoElement.select("h3.item-title").text()
description = infoElement.select("div.limit-height-body").select("h5.text-muted, div.limit-html").joinToString("\n\n") { it.text() } description = infoElement.select("div.limit-height-body")
author = infoElement.select("div.attr-item:contains(author)").text().split("/").joinToString(", ") { it.trim() } .select("h5.text-muted, div.limit-html")
.joinToString("\n\n") { it.text() }
author = infoElement.select("div.attr-item:contains(author) a")
.joinToString { it.text().trim() }
status = parseStatus(statusStr) status = parseStatus(statusStr)
thumbnail_url = infoElement.select("div.detail-set div.attr-cover img").attr("abs:src") thumbnail_url = infoElement.select("div.detail-set div.attr-cover img").attr("abs:src")
genre = genreList.joinToString(", ") { it.trim() } genre = infoElement.select("div.attr-item:contains(genres) span span")
.joinToString { it.text().trim() }
} }
} }
private fun parseStatus(status: String?) = when { private fun parseStatus(status: String?) = when {
@ -200,7 +190,7 @@ open class MangaPark(
put("lang", siteLang) put("lang", siteLang)
put("sid", sid) put("sid", sid)
} }
val requestBody = jsonPayload.toString().toRequestBody("application/json;charset=UTF-8".toMediaType()) val requestBody = jsonPayload.toString().toRequestBody("application/json;charset=UTF-8".toMediaType())
val refererUrl = "$baseUrl/$url".toHttpUrlOrNull()!!.newBuilder() val refererUrl = "$baseUrl/$url".toHttpUrlOrNull()!!.newBuilder()
@ -217,20 +207,20 @@ open class MangaPark(
body = requestBody body = requestBody
) )
} }
override fun chapterListParse(response: Response): List<SChapter> { override fun chapterListParse(response: Response): List<SChapter> {
val resToJson = json.parseToJsonElement(response.body!!.string()).jsonObject val resToJson = json.parseToJsonElement(response.body!!.string()).jsonObject
val document = Jsoup.parse(resToJson["html"]!!.jsonPrimitive.content) val document = Jsoup.parse(resToJson["html"]!!.jsonPrimitive.content)
return document.select(chapterListSelector()).map { chapterFromElement(it) } return document.select(chapterListSelector()).map { chapterFromElement(it) }
} }
override fun chapterListSelector() = "div.episode-item" override fun chapterListSelector() = "div.episode-item"
override fun chapterFromElement(element: Element): SChapter { override fun chapterFromElement(element: Element): SChapter {
val urlElement = element.select("a.chapt") val urlElement = element.select("a.chapt")
val time = element.select("div.extra > i.ps-2").text() val time = element.select("div.extra > i.ps-2").text()
return SChapter.create().apply { return SChapter.create().apply {
name = urlElement.text() name = urlElement.text()
chapter_number = urlElement.attr("href").substringAfterLast("/").toFloat() chapter_number = urlElement.attr("href").substringAfterLast("/").toFloat()
@ -238,7 +228,7 @@ open class MangaPark(
setUrlWithoutDomain(urlElement.attr("href")) setUrlWithoutDomain(urlElement.attr("href"))
} }
} }
private fun parseChapterDate(date: String): Long { private fun parseChapterDate(date: String): Long {
val value = date.split(' ')[0].toInt() val value = date.split(' ')[0].toInt()
val timeStr = date.split(' ')[1].removeSuffix("s") val timeStr = date.split(' ')[1].removeSuffix("s")
@ -272,32 +262,25 @@ open class MangaPark(
} }
override fun pageListParse(document: Document): List<Page> { override fun pageListParse(document: Document): List<Page> {
val pages = mutableListOf<Page>()
val duktape = Duktape.create() val duktape = Duktape.create()
val script = document.select("script").html() val script = document.select("script").html()
val imgCdnHost = script.substringAfter("const imgCdnHost = ").substringBefore(";") val imgCdnHost = script.substringAfter("const imgCdnHost = \"").substringBefore("\";")
val imgPathLisRaw = script.substringAfter("const imgPathLis = ").substringBefore(";") val imgPathLisRaw = script.substringAfter("const imgPathLis = ").substringBefore(";")
val imgPathLis = json.parseToJsonElement(imgPathLisRaw).jsonArray val imgPathLis = json.parseToJsonElement(imgPathLisRaw).jsonArray
val amPass = duktape.evaluate(script.substringAfter("const amPass = ").substringBefore(";")).toString() val amPass = script.substringAfter("const amPass = ").substringBefore(";")
val amWord = script.substringAfter("const amWord = ").substringBefore(";") val amWord = script.substringAfter("const amWord = ").substringBefore(";")
val decryptScript = cryptoJS + "CryptoJS.AES.decrypt($amWord, \"$amPass\").toString(CryptoJS.enc.Utf8);" val decryptScript = cryptoJS + "CryptoJS.AES.decrypt($amWord, $amPass).toString(CryptoJS.enc.Utf8);"
val imgWordLisRaw = duktape.evaluate(decryptScript).toString() val imgWordLisRaw = duktape.evaluate(decryptScript).toString()
val imgWordLis = json.parseToJsonElement(imgWordLisRaw).jsonArray val imgWordLis = json.parseToJsonElement(imgWordLisRaw).jsonArray
imgPathLis.mapIndexed { i, imgPathE ->
val imgPath = imgPathE.jsonPrimitive.content
val imgWordE = imgWordLis.elementAt(i)
val imgWord = imgWordE.jsonPrimitive.content
val page = "$imgCdnHost$imgPath?$imgWord"
pages.add(Page(i, "", "$page"))
}
return pages return imgWordLis.mapIndexed { i, imgWordE ->
val imgPath = imgPathLis[i].jsonPrimitive.content
val imgWord = imgWordE.jsonPrimitive.content
Page(i, "", "$imgCdnHost$imgPath?$imgWord")
}
} }
private val cryptoJS by lazy { private val cryptoJS by lazy {
@ -311,9 +294,8 @@ open class MangaPark(
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used") override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
override fun getFilterList() = FilterList( override fun getFilterList() = FilterList(
//LetterFilter(), // LetterFilter(),
Filter.Header("NOTE: Ignored if using text search!"), Filter.Header("NOTE: Ignored if using text search!"),
Filter.Separator(), Filter.Separator(),
SortFilter(getSortFilter(), 10), SortFilter(getSortFilter(), 10),
@ -381,124 +363,122 @@ open class MangaPark(
) )
private fun getGenreFilter() = listOf( private fun getGenreFilter() = listOf(
TriStateFilterOption("artbook","Artbook"), TriStateFilterOption("artbook", "Artbook"),
TriStateFilterOption("cartoon","Cartoon"), TriStateFilterOption("cartoon", "Cartoon"),
TriStateFilterOption("comic","Comic"), TriStateFilterOption("comic", "Comic"),
TriStateFilterOption("doujinshi","Doujinshi"), TriStateFilterOption("doujinshi", "Doujinshi"),
TriStateFilterOption("imageset","Imageset"), TriStateFilterOption("imageset", "Imageset"),
TriStateFilterOption("manga","Manga"), TriStateFilterOption("manga", "Manga"),
TriStateFilterOption("manhua","Manhua"), TriStateFilterOption("manhua", "Manhua"),
TriStateFilterOption("manhwa","Manhwa"), TriStateFilterOption("manhwa", "Manhwa"),
TriStateFilterOption("webtoon","Webtoon"), TriStateFilterOption("webtoon", "Webtoon"),
TriStateFilterOption("western","Western"), TriStateFilterOption("western", "Western"),
TriStateFilterOption("josei","Josei"), TriStateFilterOption("josei", "Josei"),
TriStateFilterOption("seinen","Seinen"), TriStateFilterOption("seinen", "Seinen"),
TriStateFilterOption("shoujo","Shoujo"), TriStateFilterOption("shoujo", "Shoujo"),
TriStateFilterOption("shoujo_ai","Shoujo ai"), TriStateFilterOption("shoujo_ai", "Shoujo ai"),
TriStateFilterOption("shounen","Shounen"), TriStateFilterOption("shounen", "Shounen"),
TriStateFilterOption("shounen_ai","Shounen ai"), TriStateFilterOption("shounen_ai", "Shounen ai"),
TriStateFilterOption("yaoi","Yaoi"), TriStateFilterOption("yaoi", "Yaoi"),
TriStateFilterOption("yuri","Yuri"), TriStateFilterOption("yuri", "Yuri"),
TriStateFilterOption("ecchi","Ecchi"), TriStateFilterOption("ecchi", "Ecchi"),
TriStateFilterOption("mature","Mature"), TriStateFilterOption("mature", "Mature"),
TriStateFilterOption("adult","Adult"), TriStateFilterOption("adult", "Adult"),
TriStateFilterOption("gore","Gore"), TriStateFilterOption("gore", "Gore"),
TriStateFilterOption("violence","Violence"), TriStateFilterOption("violence", "Violence"),
TriStateFilterOption("smut","Smut"), TriStateFilterOption("smut", "Smut"),
TriStateFilterOption("hentai","Hentai"), TriStateFilterOption("hentai", "Hentai"),
TriStateFilterOption("_4_koma","4-Koma"), TriStateFilterOption("_4_koma", "4-Koma"),
TriStateFilterOption("action","Action"), TriStateFilterOption("action", "Action"),
TriStateFilterOption("adaptation","Adaptation"), TriStateFilterOption("adaptation", "Adaptation"),
TriStateFilterOption("adventure","Adventure"), TriStateFilterOption("adventure", "Adventure"),
TriStateFilterOption("aliens","Aliens"), TriStateFilterOption("aliens", "Aliens"),
TriStateFilterOption("animals","Animals"), TriStateFilterOption("animals", "Animals"),
TriStateFilterOption("anthology","Anthology"), TriStateFilterOption("anthology", "Anthology"),
TriStateFilterOption("cars","cars"), TriStateFilterOption("cars", "cars"),
TriStateFilterOption("comedy","Comedy"), TriStateFilterOption("comedy", "Comedy"),
TriStateFilterOption("cooking","Cooking"), TriStateFilterOption("cooking", "Cooking"),
TriStateFilterOption("crime","crime"), TriStateFilterOption("crime", "crime"),
TriStateFilterOption("crossdressing","Crossdressing"), TriStateFilterOption("crossdressing", "Crossdressing"),
TriStateFilterOption("delinquents","Delinquents"), TriStateFilterOption("delinquents", "Delinquents"),
TriStateFilterOption("dementia","Dementia"), TriStateFilterOption("dementia", "Dementia"),
TriStateFilterOption("demons","Demons"), TriStateFilterOption("demons", "Demons"),
TriStateFilterOption("drama","Drama"), TriStateFilterOption("drama", "Drama"),
TriStateFilterOption("fantasy","Fantasy"), TriStateFilterOption("fantasy", "Fantasy"),
TriStateFilterOption("fan_colored","Fan-Colored"), TriStateFilterOption("fan_colored", "Fan-Colored"),
TriStateFilterOption("full_color","Full Color"), TriStateFilterOption("full_color", "Full Color"),
TriStateFilterOption("game","Game"), TriStateFilterOption("game", "Game"),
TriStateFilterOption("gender_bender","Gender Bender"), TriStateFilterOption("gender_bender", "Gender Bender"),
TriStateFilterOption("genderswap","Genderswap"), TriStateFilterOption("genderswap", "Genderswap"),
TriStateFilterOption("ghosts","Ghosts"), TriStateFilterOption("ghosts", "Ghosts"),
TriStateFilterOption("gyaru","Gyaru"), TriStateFilterOption("gyaru", "Gyaru"),
TriStateFilterOption("harem","Harem"), TriStateFilterOption("harem", "Harem"),
TriStateFilterOption("harlequin","Harlequin"), TriStateFilterOption("harlequin", "Harlequin"),
TriStateFilterOption("historical","Historical"), TriStateFilterOption("historical", "Historical"),
TriStateFilterOption("horror","Horror"), TriStateFilterOption("horror", "Horror"),
TriStateFilterOption("incest","Incest"), TriStateFilterOption("incest", "Incest"),
TriStateFilterOption("isekai","Isekai"), TriStateFilterOption("isekai", "Isekai"),
TriStateFilterOption("kids","Kids"), TriStateFilterOption("kids", "Kids"),
TriStateFilterOption("loli","Loli"), TriStateFilterOption("loli", "Loli"),
TriStateFilterOption("lolicon","lolicon"), TriStateFilterOption("lolicon", "lolicon"),
TriStateFilterOption("magic","Magic"), TriStateFilterOption("magic", "Magic"),
TriStateFilterOption("magical_girls","Magical Girls"), TriStateFilterOption("magical_girls", "Magical Girls"),
TriStateFilterOption("martial_arts","Martial Arts"), TriStateFilterOption("martial_arts", "Martial Arts"),
TriStateFilterOption("mecha","Mecha"), TriStateFilterOption("mecha", "Mecha"),
TriStateFilterOption("medical","Medical"), TriStateFilterOption("medical", "Medical"),
TriStateFilterOption("military","Military"), TriStateFilterOption("military", "Military"),
TriStateFilterOption("monster_girls","Monster Girls"), TriStateFilterOption("monster_girls", "Monster Girls"),
TriStateFilterOption("monsters","Monsters"), TriStateFilterOption("monsters", "Monsters"),
TriStateFilterOption("music","Music"), TriStateFilterOption("music", "Music"),
TriStateFilterOption("mystery","Mystery"), TriStateFilterOption("mystery", "Mystery"),
TriStateFilterOption("netorare","Netorare/NTR"), TriStateFilterOption("netorare", "Netorare/NTR"),
TriStateFilterOption("ninja","Ninja"), TriStateFilterOption("ninja", "Ninja"),
TriStateFilterOption("office_workers","Office Workers"), TriStateFilterOption("office_workers", "Office Workers"),
TriStateFilterOption("oneshot","Oneshot"), TriStateFilterOption("oneshot", "Oneshot"),
TriStateFilterOption("parody","parody"), TriStateFilterOption("parody", "parody"),
TriStateFilterOption("philosophical","Philosophical"), TriStateFilterOption("philosophical", "Philosophical"),
TriStateFilterOption("police","Police"), TriStateFilterOption("police", "Police"),
TriStateFilterOption("post_apocalyptic","Post-Apocalyptic"), TriStateFilterOption("post_apocalyptic", "Post-Apocalyptic"),
TriStateFilterOption("psychological","Psychological"), TriStateFilterOption("psychological", "Psychological"),
TriStateFilterOption("reincarnation","Reincarnation"), TriStateFilterOption("reincarnation", "Reincarnation"),
TriStateFilterOption("reverse_harem","Reverse Harem"), TriStateFilterOption("reverse_harem", "Reverse Harem"),
TriStateFilterOption("romance","Romance"), TriStateFilterOption("romance", "Romance"),
TriStateFilterOption("samurai","Samurai"), TriStateFilterOption("samurai", "Samurai"),
TriStateFilterOption("school_life","School Life"), TriStateFilterOption("school_life", "School Life"),
TriStateFilterOption("sci_fi","Sci-Fi"), TriStateFilterOption("sci_fi", "Sci-Fi"),
TriStateFilterOption("shota","Shota"), TriStateFilterOption("shota", "Shota"),
TriStateFilterOption("shotacon","shotacon"), TriStateFilterOption("shotacon", "shotacon"),
TriStateFilterOption("slice_of_life","Slice of Life"), TriStateFilterOption("slice_of_life", "Slice of Life"),
TriStateFilterOption("sm_bdsm","SM/BDSM"), TriStateFilterOption("sm_bdsm", "SM/BDSM"),
TriStateFilterOption("space","Space"), TriStateFilterOption("space", "Space"),
TriStateFilterOption("sports","Sports"), TriStateFilterOption("sports", "Sports"),
TriStateFilterOption("super_power","Super Power"), TriStateFilterOption("super_power", "Super Power"),
TriStateFilterOption("superhero","Superhero"), TriStateFilterOption("superhero", "Superhero"),
TriStateFilterOption("supernatural","Supernatural"), TriStateFilterOption("supernatural", "Supernatural"),
TriStateFilterOption("survival","Survival"), TriStateFilterOption("survival", "Survival"),
TriStateFilterOption("thriller","Thriller"), TriStateFilterOption("thriller", "Thriller"),
TriStateFilterOption("time_travel","Time Travel"), TriStateFilterOption("time_travel", "Time Travel"),
TriStateFilterOption("traditional_games","Traditional Games"), TriStateFilterOption("traditional_games", "Traditional Games"),
TriStateFilterOption("tragedy","Tragedy"), TriStateFilterOption("tragedy", "Tragedy"),
TriStateFilterOption("vampires","Vampires"), TriStateFilterOption("vampires", "Vampires"),
TriStateFilterOption("video_games","Video Games"), TriStateFilterOption("video_games", "Video Games"),
TriStateFilterOption("virtual_reality","Virtual Reality"), TriStateFilterOption("virtual_reality", "Virtual Reality"),
TriStateFilterOption("wuxia","Wuxia"), TriStateFilterOption("wuxia", "Wuxia"),
TriStateFilterOption("xianxia","Xianxia"), TriStateFilterOption("xianxia", "Xianxia"),
TriStateFilterOption("xuanhuan","Xuanhuan"), TriStateFilterOption("xuanhuan", "Xuanhuan"),
TriStateFilterOption("zombies","Zombies"), TriStateFilterOption("zombies", "Zombies"),
// Hidden Genres // Hidden Genres
TriStateFilterOption("award_winning", "Award Winning"), TriStateFilterOption("award_winning", "Award Winning"),
TriStateFilterOption("youkai", "Youkai"), TriStateFilterOption("youkai", "Youkai"),
TriStateFilterOption("uncategorized", "Uncategorized") TriStateFilterOption("uncategorized", "Uncategorized")
) )
private inline fun <reified T> Iterable<*>.findInstance() = find { it is T } as? T private inline fun <reified T> Iterable<*>.findInstance() = find { it is T } as? T
companion object { companion object {
const val PREFIX_ID_SEARCH = "id:" const val PREFIX_ID_SEARCH = "id:"
const val CryptoJSUrl = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js" const val CryptoJSUrl = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"
} }
} }

View File

@ -11,7 +11,7 @@ class MangaParkFactory : SourceFactory {
class LanguageOption(val lang: String, val siteLang: String = lang) class LanguageOption(val lang: String, val siteLang: String = lang)
private val languages = listOf( private val languages = listOf(
//LanguageOption("<Language Format>","<Language Format used in site.>"), // LanguageOption("<Language Format>","<Language Format used in site.>"),
LanguageOption("en"), LanguageOption("en"),
LanguageOption("ar"), LanguageOption("ar"),
LanguageOption("bg"), LanguageOption("bg"),
@ -34,11 +34,11 @@ private val languages = listOf(
LanguageOption("ms"), LanguageOption("ms"),
LanguageOption("pl"), LanguageOption("pl"),
LanguageOption("pt"), LanguageOption("pt"),
LanguageOption("pt-BR","pt_br"), LanguageOption("pt-BR", "pt_br"),
LanguageOption("ro"), LanguageOption("ro"),
LanguageOption("ru"), LanguageOption("ru"),
LanguageOption("es"), LanguageOption("es"),
LanguageOption("es-419","es_419"), LanguageOption("es-419", "es_419"),
LanguageOption("sv"), LanguageOption("sv"),
LanguageOption("th"), LanguageOption("th"),
LanguageOption("tr"), LanguageOption("tr"),
@ -56,10 +56,10 @@ private val languages = listOf(
LanguageOption("km"), LanguageOption("km"),
LanguageOption("ca"), LanguageOption("ca"),
LanguageOption("ceb"), LanguageOption("ceb"),
LanguageOption("zh-rHK","zh_hk"), LanguageOption("zh-rHK", "zh_hk"),
LanguageOption("zh-rTW","zh_tw"), LanguageOption("zh-rTW", "zh_tw"),
LanguageOption("hr"), LanguageOption("hr"),
LanguageOption("en-US","en_us"), LanguageOption("en-US", "en_us"),
LanguageOption("eo"), LanguageOption("eo"),
LanguageOption("et"), LanguageOption("et"),
LanguageOption("fo"), LanguageOption("fo"),
@ -116,5 +116,5 @@ private val languages = listOf(
LanguageOption("zu"), LanguageOption("zu"),
LanguageOption("other", "_t"), LanguageOption("other", "_t"),
LanguageOption("eu"), LanguageOption("eu"),
LanguageOption("pt-PT","pt_pt") LanguageOption("pt-PT", "pt_pt")
) )