MangaPark v3 Fixes (#7516)
* Update build.gradle * Update res * Update MangaParkUrlActivity.kt * Update MangaParkFactory.kt * Update MangaPark.kt
|
@ -1,11 +1,12 @@
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'kotlinx-serialization'
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
extName = 'MangaPark v3'
|
extName = 'MangaPark v3'
|
||||||
pkgNameSuffix = 'all.mangapark'
|
pkgNameSuffix = 'all.mangapark'
|
||||||
extClass = '.MangaParkFactory'
|
extClass = '.MangaParkFactory'
|
||||||
extVersionCode = 2
|
extVersionCode = 3
|
||||||
libVersion = '1.2'
|
libVersion = '1.2'
|
||||||
containsNsfw = true
|
containsNsfw = true
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 77 KiB |
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.extension.all.mangapark
|
||||||
|
|
||||||
import com.squareup.duktape.Duktape
|
import com.squareup.duktape.Duktape
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
|
import eu.kanade.tachiyomi.network.POST
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
import eu.kanade.tachiyomi.source.model.Filter
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
|
@ -11,81 +12,88 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
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.buildJsonObject
|
||||||
|
import kotlinx.serialization.json.jsonArray
|
||||||
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
|
import kotlinx.serialization.json.put
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import org.json.JSONArray
|
|
||||||
import org.json.JSONObject
|
|
||||||
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.Calendar
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
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
|
||||||
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
|
|
||||||
|
private val json : Json by injectLazy()
|
||||||
|
|
||||||
|
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 {
|
||||||
val manga = SManga.create()
|
return SManga.create().apply {
|
||||||
val item = element.select("a.position-relative")
|
setUrlWithoutDomain(element.select("a.fw-bold").attr("href"))
|
||||||
val imgurl = item.select("img").attr("abs:src")
|
title = element.select("a.fw-bold").text()
|
||||||
manga.setUrlWithoutDomain(item.attr("href"))
|
thumbnail_url = element.select("a.position-relative img").attr("abs:src")
|
||||||
manga.title = element.select("a.fw-bold").text()
|
}
|
||||||
manga.thumbnail_url = imgurl
|
|
||||||
return manga
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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("ID:") -> {
|
query.startsWith(PREFIX_ID_SEARCH) -> {
|
||||||
val id = query.substringAfter("ID:")
|
val id = query.removePrefix(PREFIX_ID_SEARCH)
|
||||||
client.newCall(GET("$baseUrl/comic/$id", headers)).asObservableSuccess()
|
client.newCall(GET("$baseUrl/comic/$id", headers)).asObservableSuccess()
|
||||||
.map { response ->
|
.map { response ->
|
||||||
queryIDParse(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 ->
|
||||||
queryParse(response)
|
searchParse(response)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
val sortFilter = filters.findInstance<SortFilter>()!!
|
val sortFilter = filters.findInstance<SortFilter>()!!
|
||||||
val reverseSortFilter = filters.findInstance<ReverseSortFilter>()!!
|
val reverseSortFilter = filters.findInstance<ReverseSortFilter>()!!
|
||||||
|
@ -95,8 +103,7 @@ 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")
|
||||||
|
@ -104,7 +111,7 @@ open class MangaPark(
|
||||||
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(",")
|
||||||
)
|
)
|
||||||
|
@ -120,30 +127,32 @@ open class MangaPark(
|
||||||
|
|
||||||
client.newCall(GET(url.build().toString(), headers)).asObservableSuccess()
|
client.newCall(GET(url.build().toString(), headers)).asObservableSuccess()
|
||||||
.map { response ->
|
.map { response ->
|
||||||
queryParse(response)
|
searchParse(response)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun mangaFromID(response: Response, id: String): MangasPage {
|
||||||
|
val infoElement = response.asJsoup().select("div#mainer div.container-fluid")
|
||||||
|
val manga = SManga.create().apply {
|
||||||
|
url = "/comic/$id"
|
||||||
|
title = infoElement.select("h3.item-title").text()
|
||||||
|
thumbnail_url = infoElement.select("div.detail-set div.attr-cover img").attr("abs:src")
|
||||||
|
}
|
||||||
|
|
||||||
private fun queryIDParse(response: Response, id: String): MangasPage {
|
|
||||||
val document = response.asJsoup()
|
|
||||||
val infoElement = document.select("div#mainer div.container-fluid")
|
|
||||||
val manga = SManga.create()
|
|
||||||
manga.title = infoElement.select("h3").text()
|
|
||||||
manga.thumbnail_url = document.select("div.attr-cover img")
|
|
||||||
.attr("abs:src")
|
|
||||||
manga.url = infoElement.select("h3 a").attr("abs:href")
|
|
||||||
return MangasPage(listOf(manga), false)
|
return MangasPage(listOf(manga), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun queryParse(response: Response): MangasPage {
|
private fun searchParse(response: Response): MangasPage {
|
||||||
val mangas = mutableListOf<SManga>()
|
val mangas = mutableListOf<SManga>()
|
||||||
val document = response.asJsoup()
|
|
||||||
document.select("div#search-list div.col").forEach { element ->
|
response.asJsoup().select("div#search-list div.col").forEach { element ->
|
||||||
mangas.add(latestUpdatesFromElement(element))
|
mangas.add(latestUpdatesFromElement(element))
|
||||||
}
|
}
|
||||||
val nextPage = document.select(latestUpdatesNextPageSelector()).first() != null
|
|
||||||
|
val nextPage = response.asJsoup().select(latestUpdatesNextPageSelector()).first() != null
|
||||||
|
|
||||||
return MangasPage(mangas, nextPage)
|
return MangasPage(mangas, nextPage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,32 +161,24 @@ open class MangaPark(
|
||||||
override fun searchMangaFromElement(element: Element) = throw UnsupportedOperationException("Not used")
|
override fun searchMangaFromElement(element: Element) = throw UnsupportedOperationException("Not used")
|
||||||
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException("Not used")
|
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException("Not used")
|
||||||
|
|
||||||
override fun mangaDetailsRequest(manga: SManga): Request {
|
|
||||||
if (manga.url.startsWith("http")) {
|
|
||||||
return GET(manga.url, headers)
|
|
||||||
}
|
|
||||||
return super.mangaDetailsRequest(manga)
|
|
||||||
}
|
|
||||||
|
|
||||||
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 manga = SManga.create()
|
val genreList = mutableListOf<String>()
|
||||||
val genres = mutableListOf<String>()
|
val statusStr = infoElement.select("div.attr-item:contains(status) span").text()
|
||||||
val status = infoElement.select("div.attr-item:contains(status) span").text()
|
infoElement.select("div.attr-item:contains(genres) span span").forEach { element ->
|
||||||
infoElement.select("div.attr-item:contains(genres) span").text().split(
|
genreList.add(element.text())
|
||||||
" / "
|
|
||||||
.toRegex()
|
|
||||||
).forEach { element ->
|
|
||||||
genres.add(element)
|
|
||||||
}
|
}
|
||||||
manga.title = infoElement.select("h3").text()
|
|
||||||
manga.author = infoElement.select("div.attr-item:contains(author) a:first-child").text().split(" / ".toRegex()).joinToString(", ")
|
return SManga.create().apply {
|
||||||
manga.status = parseStatus(status)
|
title = infoElement.select("h3.item-title").text()
|
||||||
manga.genre = infoElement.select("div.attr-item:contains(genre) span").text()
|
description = infoElement.select("div.limit-height-body").select("h5.text-muted, div.limit-html").joinToString("\n\n") { it.text() }
|
||||||
manga.description = infoElement.select("div.limit-height-body").text() //Needs to put new line before extra and notice and stuff.
|
author = infoElement.select("div.attr-item:contains(author)").text().split("/").joinToString(", ") { it.trim() }
|
||||||
manga.thumbnail_url = document.select("div.attr-cover img")
|
status = parseStatus(statusStr)
|
||||||
.attr("abs:src")
|
thumbnail_url = infoElement.select("div.detail-set div.attr-cover img").attr("abs:src")
|
||||||
return manga
|
genre = genreList.joinToString(", ") { it.trim() }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseStatus(status: String?) = when {
|
private fun parseStatus(status: String?) = when {
|
||||||
|
@ -189,73 +190,71 @@ open class MangaPark(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun chapterListRequest(manga: SManga): Request {
|
override fun chapterListRequest(manga: SManga): Request {
|
||||||
if (manga.url.startsWith("http")) {
|
|
||||||
return GET(manga.url, headers)
|
|
||||||
}
|
|
||||||
return super.chapterListRequest(manga)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun chapterListSelector() = "div#mainer div.container-fluid div.episode-list div#episodes-lang-$siteLang div.p-2"
|
val url = manga.url
|
||||||
|
val sid = url.split("/")[2]
|
||||||
|
|
||||||
|
val jsonPayload = buildJsonObject {
|
||||||
|
put("lang", siteLang)
|
||||||
|
put("sid", sid)
|
||||||
|
}
|
||||||
|
|
||||||
|
val requestBody = jsonPayload.toString().toRequestBody("application/json;charset=UTF-8".toMediaType())
|
||||||
|
|
||||||
|
val refererUrl = "$baseUrl/$url".toHttpUrlOrNull()!!.newBuilder()
|
||||||
|
.toString()
|
||||||
|
val newHeaders = headersBuilder()
|
||||||
|
.add("Content-Length", requestBody.contentLength().toString())
|
||||||
|
.add("Content-Type", requestBody.contentType().toString())
|
||||||
|
.set("Referer", refererUrl)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
return POST(
|
||||||
|
"$baseUrl/ajax.reader.subject.episodes.lang",
|
||||||
|
headers = newHeaders,
|
||||||
|
body = requestBody
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun chapterListSelector() = "div.episode-item"
|
||||||
|
|
||||||
override fun chapterFromElement(element: Element): SChapter {
|
override fun chapterFromElement(element: Element): SChapter {
|
||||||
val chapter = SChapter.create()
|
|
||||||
val urlElement = element.select("a.chapt")
|
val urlElement = element.select("a.chapt")
|
||||||
val url = urlElement.attr("href")
|
|
||||||
val time = element.select("div.extra > i.ps-2").text()
|
val time = element.select("div.extra > i.ps-2").text()
|
||||||
chapter.setUrlWithoutDomain(url)
|
|
||||||
chapter.name = urlElement.text()
|
return SChapter.create().apply {
|
||||||
chapter.chapter_number = url.split("/".toRegex()).last().toFloat()
|
name = urlElement.text()
|
||||||
|
chapter_number = urlElement.attr("href").substringAfterLast("/").toFloat()
|
||||||
if (time != "") {
|
if (time != "") { date_upload = parseChapterDate(time) }
|
||||||
chapter.date_upload = parseChapterDate(time)
|
setUrlWithoutDomain(urlElement.attr("href"))
|
||||||
}
|
}
|
||||||
return chapter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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")
|
||||||
|
|
||||||
return when {
|
return when (timeStr) {
|
||||||
"secs" in date -> Calendar.getInstance().apply {
|
"sec" -> Calendar.getInstance().apply {
|
||||||
add(Calendar.SECOND, value * -1)
|
add(Calendar.SECOND, value * -1)
|
||||||
}.timeInMillis
|
}.timeInMillis
|
||||||
"mins" in date -> Calendar.getInstance().apply {
|
"min" -> Calendar.getInstance().apply {
|
||||||
add(Calendar.MINUTE, value * -1)
|
add(Calendar.MINUTE, value * -1)
|
||||||
}.timeInMillis
|
}.timeInMillis
|
||||||
"hours" in date -> Calendar.getInstance().apply {
|
"hour" -> Calendar.getInstance().apply {
|
||||||
add(Calendar.HOUR_OF_DAY, value * -1)
|
add(Calendar.HOUR_OF_DAY, value * -1)
|
||||||
}.timeInMillis
|
}.timeInMillis
|
||||||
"days" in date -> Calendar.getInstance().apply {
|
"day" -> Calendar.getInstance().apply {
|
||||||
add(Calendar.DATE, value * -1)
|
add(Calendar.DATE, value * -1)
|
||||||
}.timeInMillis
|
}.timeInMillis
|
||||||
"weeks" in date -> Calendar.getInstance().apply {
|
"week" -> Calendar.getInstance().apply {
|
||||||
add(Calendar.DATE, value * 7 * -1)
|
add(Calendar.DATE, value * 7 * -1)
|
||||||
}.timeInMillis
|
}.timeInMillis
|
||||||
"months" in date -> Calendar.getInstance().apply {
|
"month" -> Calendar.getInstance().apply {
|
||||||
add(Calendar.MONTH, value * -1)
|
add(Calendar.MONTH, value * -1)
|
||||||
}.timeInMillis
|
}.timeInMillis
|
||||||
"years" in date -> Calendar.getInstance().apply {
|
"year" -> Calendar.getInstance().apply {
|
||||||
add(Calendar.YEAR, value * -1)
|
|
||||||
}.timeInMillis
|
|
||||||
"sec" in date -> Calendar.getInstance().apply {
|
|
||||||
add(Calendar.SECOND, value * -1)
|
|
||||||
}.timeInMillis
|
|
||||||
"min" in date -> Calendar.getInstance().apply {
|
|
||||||
add(Calendar.MINUTE, value * -1)
|
|
||||||
}.timeInMillis
|
|
||||||
"hour" in date -> Calendar.getInstance().apply {
|
|
||||||
add(Calendar.HOUR_OF_DAY, value * -1)
|
|
||||||
}.timeInMillis
|
|
||||||
"day" in date -> Calendar.getInstance().apply {
|
|
||||||
add(Calendar.DATE, value * -1)
|
|
||||||
}.timeInMillis
|
|
||||||
"week" in date -> Calendar.getInstance().apply {
|
|
||||||
add(Calendar.DATE, value * 7 * -1)
|
|
||||||
}.timeInMillis
|
|
||||||
"month" in date -> Calendar.getInstance().apply {
|
|
||||||
add(Calendar.MONTH, value * -1)
|
|
||||||
}.timeInMillis
|
|
||||||
"year" in date -> Calendar.getInstance().apply {
|
|
||||||
add(Calendar.YEAR, value * -1)
|
add(Calendar.YEAR, value * -1)
|
||||||
}.timeInMillis
|
}.timeInMillis
|
||||||
else -> {
|
else -> {
|
||||||
|
@ -264,28 +263,46 @@ open class MangaPark(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pageListRequest(chapter: SChapter): Request {
|
|
||||||
if (chapter.url.startsWith("http")) {
|
|
||||||
return GET(chapter.url, headers)
|
|
||||||
}
|
|
||||||
return super.pageListRequest(chapter)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun pageListParse(document: Document): List<Page> {
|
override fun pageListParse(document: Document): List<Page> {
|
||||||
val viewer = document.select("div#viewer")
|
|
||||||
val pages = mutableListOf<Page>()
|
val pages = mutableListOf<Page>()
|
||||||
viewer.select("div.item").forEach() { i ->
|
|
||||||
val index = i.select("span").text().split("/".toRegex())[0].toInt() - 1
|
val duktape = Duktape.create()
|
||||||
val imageUrl = i.select("img").attr("abs:src")
|
val script = document.select("script").html()
|
||||||
pages.add(Page(index, "", imageUrl))
|
val imgCdnHost = script.substringAfter("const imgCdnHost = ").substringBefore(";")
|
||||||
|
val imgPathLisRaw = script.substringAfter("const imgPathLis = ").substringBefore(";")
|
||||||
|
val imgPathLis = json.parseToJsonElement(imgPathLisRaw).jsonArray
|
||||||
|
val amPass = duktape.evaluate(script.substringAfter("const amPass = ").substringBefore(";")).toString()
|
||||||
|
val amWord = script.substringAfter("const amWord = ").substringBefore(";")
|
||||||
|
|
||||||
|
val decryptScript = cryptoJS + "CryptoJS.AES.decrypt($amWord, \"$amPass\").toString(CryptoJS.enc.Utf8);"
|
||||||
|
|
||||||
|
val imgWordLisRaw = duktape.evaluate(decryptScript).toString()
|
||||||
|
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 pages
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val cryptoJS by lazy {
|
||||||
|
client.newCall(
|
||||||
|
GET(
|
||||||
|
CryptoJSUrl,
|
||||||
|
headers
|
||||||
|
)
|
||||||
|
).execute().body!!.string()
|
||||||
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
|
||||||
|
|
||||||
// Done Down
|
|
||||||
|
|
||||||
override fun getFilterList() = FilterList(
|
override fun getFilterList() = FilterList(
|
||||||
//LetterFilter(),
|
//LetterFilter(),
|
||||||
|
@ -465,6 +482,15 @@ open class MangaPark(
|
||||||
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 {
|
||||||
|
|
||||||
|
const val PREFIX_ID_SEARCH = "id:"
|
||||||
|
|
||||||
|
const val CryptoJSUrl = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,112 +12,109 @@ 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", "en"),
|
LanguageOption("en"),
|
||||||
//LanguageOption("ar"),
|
LanguageOption("ar"),
|
||||||
//LanguageOption("bg"),
|
LanguageOption("bg"),
|
||||||
//LanguageOption("zh"),
|
LanguageOption("zh"),
|
||||||
//LanguageOption("cs"),
|
LanguageOption("cs"),
|
||||||
//LanguageOption("da"),
|
LanguageOption("da"),
|
||||||
//LanguageOption("nl"),
|
LanguageOption("nl"),
|
||||||
//LanguageOption("fil"),
|
LanguageOption("fil"),
|
||||||
//LanguageOption("fi"),
|
LanguageOption("fi"),
|
||||||
//LanguageOption("fr"),
|
LanguageOption("fr"),
|
||||||
//LanguageOption("de"),
|
LanguageOption("de"),
|
||||||
//LanguageOption("el"),
|
LanguageOption("el"),
|
||||||
//LanguageOption("he"),
|
LanguageOption("he"),
|
||||||
//LanguageOption("hi"),
|
LanguageOption("hi"),
|
||||||
//LanguageOption("hu"),
|
LanguageOption("hu"),
|
||||||
//LanguageOption("id"),
|
LanguageOption("id"),
|
||||||
//LanguageOption("it"),
|
LanguageOption("it"),
|
||||||
//LanguageOption("ja"),
|
LanguageOption("ja"),
|
||||||
//LanguageOption("ko"),
|
LanguageOption("ko"),
|
||||||
//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"),
|
||||||
//LanguageOption("uk"),
|
LanguageOption("uk"),
|
||||||
//LanguageOption("vi"),
|
LanguageOption("vi"),
|
||||||
//LanguageOption("af"),
|
LanguageOption("af"),
|
||||||
//LanguageOption("sq"),
|
LanguageOption("sq"),
|
||||||
//LanguageOption("am"),
|
LanguageOption("am"),
|
||||||
//LanguageOption("hy"),
|
LanguageOption("hy"),
|
||||||
//LanguageOption("az"),
|
LanguageOption("az"),
|
||||||
//LanguageOption("be"),
|
LanguageOption("be"),
|
||||||
//LanguageOption("bn"),
|
LanguageOption("bn"),
|
||||||
//LanguageOption("bs"),
|
LanguageOption("bs"),
|
||||||
//LanguageOption("my"),
|
LanguageOption("my"),
|
||||||
//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"),
|
||||||
//LanguageOption("ka"),
|
LanguageOption("ka"),
|
||||||
//LanguageOption("gn"),
|
LanguageOption("gn"),
|
||||||
//LanguageOption("gu"),
|
LanguageOption("gu"),
|
||||||
//LanguageOption("ht",),
|
LanguageOption("ht",),
|
||||||
//LanguageOption("ha"),
|
LanguageOption("ha"),
|
||||||
//LanguageOption("is"),
|
LanguageOption("is"),
|
||||||
//LanguageOption("ig"),
|
LanguageOption("ig"),
|
||||||
//LanguageOption("ga"),
|
LanguageOption("ga"),
|
||||||
//LanguageOption("jv"),
|
LanguageOption("jv"),
|
||||||
//LanguageOption("kn"),
|
LanguageOption("kn"),
|
||||||
//LanguageOption("kk"),
|
LanguageOption("kk"),
|
||||||
//LanguageOption("ku"),
|
LanguageOption("ku"),
|
||||||
//LanguageOption("ky"),
|
LanguageOption("ky"),
|
||||||
//LanguageOption("lo"),
|
LanguageOption("lo"),
|
||||||
//LanguageOption("lv"),
|
LanguageOption("lv"),
|
||||||
//LanguageOption("lt"),
|
LanguageOption("lt"),
|
||||||
//LanguageOption("lb"),
|
LanguageOption("lb"),
|
||||||
//LanguageOption("mk"),
|
LanguageOption("mk"),
|
||||||
//LanguageOption("mg"),
|
LanguageOption("mg"),
|
||||||
//LanguageOption("ml"),
|
LanguageOption("ml"),
|
||||||
//LanguageOption("mt"),
|
LanguageOption("mt"),
|
||||||
//LanguageOption("mi"),
|
LanguageOption("mi"),
|
||||||
//LanguageOption("mr"),
|
LanguageOption("mr"),
|
||||||
//LanguageOption("mo"),
|
LanguageOption("mo"),
|
||||||
//LanguageOption("mn"),
|
LanguageOption("mn"),
|
||||||
//LanguageOption("ne"),
|
LanguageOption("ne"),
|
||||||
//LanguageOption("no"),
|
LanguageOption("no"),
|
||||||
//LanguageOption("ny"),
|
LanguageOption("ny"),
|
||||||
//LanguageOption("ps"),
|
LanguageOption("ps"),
|
||||||
//LanguageOption("fa"),
|
LanguageOption("fa"),
|
||||||
//LanguageOption("rm"),
|
LanguageOption("rm"),
|
||||||
//LanguageOption("sm"),
|
LanguageOption("sm"),
|
||||||
//LanguageOption("sr"),
|
LanguageOption("sr"),
|
||||||
//LanguageOption("sh",),
|
LanguageOption("sh",),
|
||||||
//LanguageOption("st"),
|
LanguageOption("st"),
|
||||||
//LanguageOption("sn"),
|
LanguageOption("sn"),
|
||||||
//LanguageOption("sd"),
|
LanguageOption("sd"),
|
||||||
//LanguageOption("si"),
|
LanguageOption("si"),
|
||||||
//LanguageOption("sk"),
|
LanguageOption("sk"),
|
||||||
//LanguageOption("sl"),
|
LanguageOption("sl"),
|
||||||
//LanguageOption("so"),
|
LanguageOption("so"),
|
||||||
//LanguageOption("sw"),
|
LanguageOption("sw"),
|
||||||
//LanguageOption("tg"),
|
LanguageOption("tg"),
|
||||||
//LanguageOption("ta"),
|
LanguageOption("ta"),
|
||||||
//LanguageOption("ti"),
|
LanguageOption("ti"),
|
||||||
//LanguageOption("to"),
|
LanguageOption("to"),
|
||||||
//LanguageOption("tk"),
|
LanguageOption("tk"),
|
||||||
//LanguageOption("ur"),
|
LanguageOption("ur"),
|
||||||
//LanguageOption("uz"),
|
LanguageOption("uz"),
|
||||||
//LanguageOption("yo"),
|
LanguageOption("yo"),
|
||||||
//LanguageOption("zu"),
|
LanguageOption("zu"),
|
||||||
//LanguageOption("other", "_t"),
|
LanguageOption("other", "_t"),
|
||||||
// Lang options from bato.to brows not in publish.bato.to
|
LanguageOption("eu"),
|
||||||
//LanguageOption("eu"),
|
LanguageOption("pt-PT","pt_pt")
|
||||||
//LanguageOption("pt-PT","pt_pt"),
|
|
||||||
// Lang options that got removed
|
|
||||||
// Pair("xh", "xh"),
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
package eu.kanade.tachiyomi.extension.all.mangapark
|
package eu.kanade.tachiyomi.extension.all.mangapark
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
@ -42,7 +43,7 @@ class MangaParkUrlActivity : Activity() {
|
||||||
private fun fromGuya(pathSegments: MutableList<String>): String? {
|
private fun fromGuya(pathSegments: MutableList<String>): String? {
|
||||||
return if (pathSegments.size >= 2) {
|
return if (pathSegments.size >= 2) {
|
||||||
val id = pathSegments[1]
|
val id = pathSegments[1]
|
||||||
"ID:$id"
|
"id:$id"
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|