ManhwaFreakXyz: Migrate theme (#7739)
* Migrate theme * Fix lint * Add nonce setting in the popular manga
This commit is contained in:
parent
027d09ffd9
commit
d4c94d0972
|
@ -1,7 +1,7 @@
|
||||||
ext {
|
ext {
|
||||||
extName = 'ManhwaFreak.xyz'
|
extName = 'ManhwaFreak.xyz'
|
||||||
extClass = '.ManhwaFreakXyz'
|
extClass = '.ManhwaFreakXyz'
|
||||||
themePkg = 'mangathemesia'
|
themePkg = 'madara'
|
||||||
baseUrl = 'https://manhwafreak.xyz'
|
baseUrl = 'https://manhwafreak.xyz'
|
||||||
overrideVersionCode = 0
|
overrideVersionCode = 0
|
||||||
isNsfw = false
|
isNsfw = false
|
||||||
|
|
|
@ -1,11 +1,152 @@
|
||||||
package eu.kanade.tachiyomi.extension.en.manhwafreakxyz
|
package eu.kanade.tachiyomi.extension.en.manhwafreakxyz
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
|
import android.util.Base64
|
||||||
|
import eu.kanade.tachiyomi.multisrc.madara.Madara
|
||||||
|
import eu.kanade.tachiyomi.network.GET
|
||||||
|
import eu.kanade.tachiyomi.network.POST
|
||||||
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
|
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||||
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
|
import kotlinx.serialization.json.decodeFromStream
|
||||||
|
import okhttp3.FormBody
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.Response
|
||||||
|
import org.jsoup.Jsoup
|
||||||
|
import org.jsoup.nodes.Document
|
||||||
|
import org.jsoup.nodes.Element
|
||||||
|
|
||||||
class ManhwaFreakXyz : MangaThemesia(
|
class ManhwaFreakXyz : Madara(
|
||||||
"ManhwaFreak.xyz",
|
"ManhwaFreak.xyz",
|
||||||
"https://manhwafreak.xyz",
|
"https://manhwafreak.xyz",
|
||||||
"en",
|
"en",
|
||||||
) {
|
) {
|
||||||
override val seriesStatusSelector = ".status-value"
|
// ===================== Popular ============================
|
||||||
|
|
||||||
|
override fun popularMangaRequest(page: Int): Request {
|
||||||
|
val url = "$baseUrl/$mangaSubString/${searchPage(page)}".toHttpUrl().newBuilder()
|
||||||
|
.addQueryParameter("post_type", "wp-manga")
|
||||||
|
.addQueryParameter("s", "")
|
||||||
|
.addQueryParameter("sort", "most_viewed")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
return GET(url, headers)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun popularMangaSelector() = "div[class*=unit item]"
|
||||||
|
|
||||||
|
override val popularMangaUrlSelector = ".info a"
|
||||||
|
|
||||||
|
override fun popularMangaFromElement(element: Element): SManga {
|
||||||
|
return super.popularMangaFromElement(element).apply {
|
||||||
|
element.selectFirst("img:not(.flag-icon)")?.let {
|
||||||
|
thumbnail_url = imageFromElement(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun popularMangaParse(response: Response): MangasPage {
|
||||||
|
if (nonce.isBlank()) {
|
||||||
|
nonce = response.peekBody().let(::findNonceValue)
|
||||||
|
}
|
||||||
|
return super.popularMangaParse(response)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Response.peekBody(): Document =
|
||||||
|
Jsoup.parseBodyFragment(peekBody(Long.MAX_VALUE).string())
|
||||||
|
|
||||||
|
override fun popularMangaNextPageSelector() = ".navigation .page-item:last-child:not(.disabled)"
|
||||||
|
|
||||||
|
// ===================== Latest ============================
|
||||||
|
|
||||||
|
override fun latestUpdatesRequest(page: Int): Request {
|
||||||
|
val request = popularMangaRequest(page)
|
||||||
|
val url = request.url.newBuilder()
|
||||||
|
.setQueryParameter("sort", "recently_added")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
return request.newBuilder()
|
||||||
|
.url(url)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================== Search ============================
|
||||||
|
|
||||||
|
override fun searchRequest(page: Int, query: String, filters: FilterList): Request {
|
||||||
|
if (nonce.isBlank()) {
|
||||||
|
nonce = findNonceValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
val form = FormBody.Builder()
|
||||||
|
.add("action", "live_search")
|
||||||
|
.add("search", query)
|
||||||
|
.add("nonce", nonce)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
return POST("$baseUrl/wp-admin/admin-ajax.php", xhrHeaders, form)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun searchMangaParse(response: Response): MangasPage {
|
||||||
|
val searchDto = json.decodeFromStream<SearchDto>(response.body.byteStream())
|
||||||
|
val mangas = searchDto.mangas.map {
|
||||||
|
SManga.create().apply {
|
||||||
|
title = it.title
|
||||||
|
thumbnail_url = it.thumbnail
|
||||||
|
setUrlWithoutDomain(it.url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MangasPage(mangas, hasNextPage = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var nonce: String = ""
|
||||||
|
|
||||||
|
private fun findNonceValue(document: Document? = null): String {
|
||||||
|
val dom = document ?: client.newCall(popularMangaRequest(1)).execute().asJsoup()
|
||||||
|
return dom.select("script")
|
||||||
|
.map(Element::data)
|
||||||
|
.firstOrNull { it.contains("'nonce','") }
|
||||||
|
?.substringAfter("'nonce','")
|
||||||
|
?.substringBefore("'") ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================== Manga Details ============================
|
||||||
|
|
||||||
|
override val mangaDetailsSelectorTitle = ".serie-title"
|
||||||
|
override val mangaDetailsSelectorAuthor = ".stat-label:contains(Author) + .stat-value"
|
||||||
|
override val mangaDetailsSelectorArtist = ".stat-label:contains(Artist) + .stat-value"
|
||||||
|
override val mangaDetailsSelectorStatus = ".stat-label:contains(Status) + .manga"
|
||||||
|
override val mangaDetailsSelectorDescription = ".description-content"
|
||||||
|
override val mangaDetailsSelectorThumbnail = ".main-cover img.cover"
|
||||||
|
override val mangaDetailsSelectorGenre = ".genre-list .genre-link"
|
||||||
|
|
||||||
|
// ===================== Chapters ============================
|
||||||
|
|
||||||
|
override fun chapterListSelector() = ".list-body-hh li"
|
||||||
|
|
||||||
|
override fun chapterDateSelector() = "a > span:not(:has(i))"
|
||||||
|
|
||||||
|
override fun chapterFromElement(element: Element): SChapter {
|
||||||
|
return super.chapterFromElement(element).apply {
|
||||||
|
name = name.split(" ")
|
||||||
|
.take(2)
|
||||||
|
.joinToString(" ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================== Pages ============================
|
||||||
|
|
||||||
|
override fun pageListParse(document: Document): List<Page> {
|
||||||
|
launchIO { countViews(document) }
|
||||||
|
|
||||||
|
return document.select("canvas.manga-canvas").mapIndexed { index, canvas ->
|
||||||
|
val imageUrl = canvas.attr("data-src")
|
||||||
|
.let { Base64.decode(it, Base64.DEFAULT).toString(Charsets.UTF_8) }
|
||||||
|
Page(index, document.location(), imageUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getFilterList() = FilterList()
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package eu.kanade.tachiyomi.extension.en.manhwafreakxyz
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
class SearchDto(
|
||||||
|
@SerialName("data")
|
||||||
|
val mangas: List<MangaDto>,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
class MangaDto(
|
||||||
|
val thumbnail: String,
|
||||||
|
val title: String,
|
||||||
|
val url: String,
|
||||||
|
)
|
Loading…
Reference in New Issue