ZeistManga: Add popular tab and more manga details + add sources (#19031)
* Update ZeistManga * Wrong order * Add more sources * Lint * Add MikoRoku * Lint again * Finally fix search * Finally fix search * Use correct parser for search
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 110 KiB |
|
@ -0,0 +1,41 @@
|
|||
package eu.kanade.tachiyomi.extension.pt.animexnovel
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.zeistmanga.ZeistManga
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.Response
|
||||
|
||||
class AnimeXNovel : ZeistManga("AnimeXNovel", "https://www.animexnovel.com", "pt-BR") {
|
||||
|
||||
override val mangaCategory: String = "Manga"
|
||||
|
||||
override fun popularMangaParse(response: Response): MangasPage {
|
||||
val document = response.asJsoup()
|
||||
val mangas = document.select("div.PopularPosts div.grid > figure").map { element ->
|
||||
SManga.create().apply {
|
||||
thumbnail_url = element.selectFirst("img")!!.attr("abs:src")
|
||||
title = element.selectFirst("figcaption > a")!!.text()
|
||||
setUrlWithoutDomain(element.selectFirst("figcaption > a")!!.attr("href"))
|
||||
}
|
||||
}.filter { it.title.contains("[Mangá]") }
|
||||
|
||||
return MangasPage(mangas, false)
|
||||
}
|
||||
|
||||
override val mangaDetailsSelectorDescription = "div.bc-fff.s1 > h3:contains(Sinopse) ~ div[style=text-align: justify;]"
|
||||
|
||||
private val chapterListSelector = "div:has(> .list-judul:contains(Lista de Capítulos)) div#latest ul > li, div.tab:has(> label:contains(Lista de Capítulos)) div.tab-content ul > li"
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
val document = response.asJsoup()
|
||||
val chapters = document.select(chapterListSelector)
|
||||
return chapters.map {
|
||||
SChapter.create().apply {
|
||||
name = it.select("a").text()
|
||||
setUrlWithoutDomain(it.select("a").attr("href"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 6.6 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 92 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 91 KiB |
|
@ -0,0 +1,7 @@
|
|||
package eu.kanade.tachiyomi.extension.pt.guildatierdraw
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.zeistmanga.ZeistManga
|
||||
|
||||
class GuildaTierDraw : ZeistManga("Guilda Tier Draw", "https://www.guildatierdraw.com", "pt-BR") {
|
||||
override val mangaDetailsSelectorDescription = "#Sinopse"
|
||||
}
|
|
@ -2,12 +2,20 @@ package eu.kanade.tachiyomi.extension.ar.hijala
|
|||
|
||||
import eu.kanade.tachiyomi.multisrc.zeistmanga.Genre
|
||||
import eu.kanade.tachiyomi.multisrc.zeistmanga.ZeistManga
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
|
||||
class Hijala : ZeistManga("Hijala", "https://hijala.blogspot.com", "ar") {
|
||||
|
||||
override val hasFilters = true
|
||||
override val hasLanguageFilter = false
|
||||
|
||||
override val supportsLatest = false
|
||||
|
||||
override fun popularMangaRequest(page: Int): Request = latestUpdatesRequest(page)
|
||||
override fun popularMangaParse(response: Response): MangasPage = latestUpdatesParse(response)
|
||||
|
||||
override fun getGenreList(): List<Genre> = listOf(
|
||||
Genre("أكشن", "Action"),
|
||||
Genre("أثارة", "Thriller"),
|
||||
|
|
|
@ -7,12 +7,14 @@ import eu.kanade.tachiyomi.multisrc.zeistmanga.ZeistManga
|
|||
import eu.kanade.tachiyomi.multisrc.zeistmanga.ZeistMangaDto
|
||||
import eu.kanade.tachiyomi.multisrc.zeistmanga.ZeistMangaIntl
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
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.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
@ -30,6 +32,27 @@ class KomikRealm : ZeistManga(
|
|||
|
||||
override val chapterCategory = ""
|
||||
|
||||
override fun popularMangaRequest(page: Int): Request {
|
||||
val url = apiUrl("Project")
|
||||
.addQueryParameter("orderby", "updated")
|
||||
.addQueryParameter("max-results", "12")
|
||||
.build()
|
||||
|
||||
return GET(url, headers)
|
||||
}
|
||||
|
||||
override fun popularMangaParse(response: Response): MangasPage {
|
||||
val jsonString = response.body.string()
|
||||
val result = json.decodeFromString<ZeistMangaDto>(jsonString)
|
||||
|
||||
val mangas = result.feed?.entry.orEmpty()
|
||||
.filter { it.category.orEmpty().any { category -> category.term == "Series" } }
|
||||
.filter { !it.category.orEmpty().any { category -> category.term == "Anime" } }
|
||||
.map { it.toSManga(baseUrl) }
|
||||
|
||||
return MangasPage(mangas, false)
|
||||
}
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
val document = response.asJsoup()
|
||||
val profileManga = document.select(".bigcontent")
|
||||
|
@ -54,12 +77,6 @@ class KomikRealm : ZeistManga(
|
|||
}
|
||||
}
|
||||
|
||||
private fun parseStatus(element: String): Int = when (element.lowercase()) {
|
||||
"ongoing" -> SManga.ONGOING
|
||||
"completed" -> SManga.COMPLETED
|
||||
else -> SManga.UNKNOWN
|
||||
}
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
val document = response.asJsoup()
|
||||
|
||||
|
|
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 84 KiB |
|
@ -0,0 +1,7 @@
|
|||
package eu.kanade.tachiyomi.extension.ar.mangasoul
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.zeistmanga.ZeistManga
|
||||
|
||||
class MangaSoul : ZeistManga("Manga Soul", "https://www.manga-soul.com", "ar") {
|
||||
override val mangaDetailsSelectorInfo = ".y6x11p, .y6x11p > b > span"
|
||||
}
|
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 7.7 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 85 KiB |
|
@ -0,0 +1,26 @@
|
|||
package eu.kanade.tachiyomi.extension.id.mikoroku
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.zeistmanga.ZeistManga
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.Response
|
||||
|
||||
class MikoRoku : ZeistManga("MikoRoku", "https://www.mikoroku.web.id", "id") {
|
||||
|
||||
override val popularMangaSelector = "div.PopularPosts article"
|
||||
override val popularMangaSelectorTitle = ".post-title a"
|
||||
override val popularMangaSelectorUrl = ".post-title a"
|
||||
|
||||
override val pageListSelector = "article#reader div.separator a"
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga = SManga.create().apply {
|
||||
val document = response.asJsoup()
|
||||
with(document.selectFirst("div.section#main div.widget header")!!) {
|
||||
thumbnail_url = selectFirst("img")!!.attr("abs:src")
|
||||
genre = select("aside dl:has(dt:contains(Genre)) dd a")
|
||||
.joinToString { it.text() }
|
||||
status = parseStatus(selectFirst("span[data-status]")!!.text())
|
||||
}
|
||||
description = document.select("div.section#main div.widget div.grid #synopsis").text()
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 6.6 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 216 KiB |
|
@ -0,0 +1,22 @@
|
|||
package eu.kanade.tachiyomi.extension.tr.mikrokosmosfansub
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.zeistmanga.ZeistManga
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.Response
|
||||
import org.jsoup.Jsoup
|
||||
|
||||
class MikrokosmosFansub : ZeistManga("Mikrokosmos Fansub", "https://mikrokosmosfb.blogspot.com", "tr") {
|
||||
|
||||
override val pageListSelector = "div.check-box > script"
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
val document = response.asJsoup()
|
||||
val script = document.select(pageListSelector)
|
||||
val content = script.html().substringAfter("const content = `").substringBefore("`;")
|
||||
val images = Jsoup.parse(content).select("a")
|
||||
return images.select("img[src]").mapIndexed { i, img ->
|
||||
Page(i, "", img.attr("abs:src"))
|
||||
}
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 241 KiB |
|
@ -1,9 +0,0 @@
|
|||
package eu.kanade.tachiyomi.extension.es.muslosnosekai
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.zeistmanga.ZeistManga
|
||||
|
||||
class MuslosNoSekai : ZeistManga("Muslos No Sekai", "https://muslosnosekai.blogspot.com", "es") {
|
||||
|
||||
override val hasFilters = true
|
||||
override val hasLanguageFilter = false
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
package eu.kanade.tachiyomi.extension.id.shiyurasub
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.zeistmanga.ZeistManga
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
|
||||
class ShiyuraSub : ZeistManga("ShiyuraSub", "https://shiyurasub.blogspot.com", "id") {
|
||||
|
@ -10,6 +12,11 @@ class ShiyuraSub : ZeistManga("ShiyuraSub", "https://shiyurasub.blogspot.com", "
|
|||
override val hasFilters = true
|
||||
override val hasLanguageFilter = false
|
||||
|
||||
override val supportsLatest = false
|
||||
|
||||
override fun popularMangaRequest(page: Int): Request = latestUpdatesRequest(page)
|
||||
override fun popularMangaParse(response: Response): MangasPage = latestUpdatesParse(response)
|
||||
|
||||
override val pageListSelector = "main.content article.container"
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
|
|
|
@ -1,69 +1,13 @@
|
|||
package eu.kanade.tachiyomi.extension.id.sobatmanku
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.zeistmanga.ZeistManga
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
|
||||
class SobatManKu : ZeistManga("SobatManKu", "https://www.sobatmanku19.site", "id") {
|
||||
|
||||
override val supportsLatest = true
|
||||
|
||||
override val hasFilters = true
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request {
|
||||
return GET("$baseUrl/search/label/Update", headers)
|
||||
}
|
||||
|
||||
override fun latestUpdatesParse(response: Response): MangasPage {
|
||||
val doc = response.asJsoup()
|
||||
val selector = doc.select(".grid.gtc-f141a > div")
|
||||
val mangas = selector.map { element ->
|
||||
|
||||
SManga.create().apply {
|
||||
element.select("a:nth-child(2)").let {
|
||||
title = it.text()
|
||||
setUrlWithoutDomain(it.attr("href"))
|
||||
}
|
||||
thumbnail_url = element.select("img").first()!!.attr("abs:src")
|
||||
}
|
||||
}
|
||||
|
||||
return MangasPage(mangas, false)
|
||||
}
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
val document = response.asJsoup()
|
||||
val profileManga = document.selectFirst(".grid.gtc-235fr")!!
|
||||
return SManga.create().apply {
|
||||
thumbnail_url = profileManga.selectFirst("img")!!.attr("abs:src")
|
||||
description = profileManga.select("#synopsis").text()
|
||||
genre = profileManga.select("div.mt-15 > a[rel=tag]").joinToString { it.text() }
|
||||
|
||||
val infoElement = profileManga.select(".y6x11p")
|
||||
infoElement.forEach {
|
||||
val descText = it.select("span.dt").text()
|
||||
when (it.ownText().trim()) {
|
||||
"Status" -> {
|
||||
status = parseStatus(descText)
|
||||
}
|
||||
|
||||
"Author" -> {
|
||||
author = descText
|
||||
}
|
||||
|
||||
"Artist" -> {
|
||||
artist = descText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
return super.chapterListParse(response).onEach {
|
||||
// fix some chapter name
|
||||
|
@ -72,10 +16,4 @@ class SobatManKu : ZeistManga("SobatManKu", "https://www.sobatmanku19.site", "id
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseStatus(element: String): Int = when (element.lowercase()) {
|
||||
"ongoing" -> SManga.ONGOING
|
||||
"completed" -> SManga.COMPLETED
|
||||
else -> SManga.UNKNOWN
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.extension.id.tooncubus
|
|||
import eu.kanade.tachiyomi.multisrc.zeistmanga.ZeistManga
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.Response
|
||||
|
||||
|
@ -14,7 +13,7 @@ class Tooncubus : ZeistManga("Tooncubus", "https://www.tooncubus.top", "id") {
|
|||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
return response.asJsoup().selectFirst("ul.series-chapterlist")!!.select("div.flexch-infoz").map { element ->
|
||||
SChapter.create().apply {
|
||||
name = element.select("span")!!.text()
|
||||
name = element.select("span").text()
|
||||
url = element.select("a").attr("href") // The website uses another domain for reading
|
||||
}
|
||||
}
|
||||
|
@ -23,14 +22,4 @@ class Tooncubus : ZeistManga("Tooncubus", "https://www.tooncubus.top", "id") {
|
|||
override fun pageListRequest(chapter: SChapter) = GET(chapter.url, headers)
|
||||
|
||||
override fun getChapterUrl(chapter: SChapter) = chapter.url
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
val document = response.asJsoup()
|
||||
val profileManga = document.selectFirst(".grid.gtc-235fr")!!
|
||||
return SManga.create().apply {
|
||||
thumbnail_url = profileManga.selectFirst("img")!!.attr("src")
|
||||
genre = profileManga.select("div.mt-15 > a[rel=tag]")
|
||||
.joinToString { it.text() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 83 KiB |
|
@ -0,0 +1,15 @@
|
|||
package eu.kanade.tachiyomi.extension.pt.tyrantscans
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.zeistmanga.ZeistManga
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
|
||||
class TyrantScans : ZeistManga("Tyrant Scans", "https://www.tyrantscans.com", "pt-BR") {
|
||||
|
||||
override val supportsLatest = false
|
||||
|
||||
override fun popularMangaRequest(page: Int): Request = latestUpdatesRequest(page)
|
||||
|
||||
override fun popularMangaParse(response: Response): MangasPage = latestUpdatesParse(response)
|
||||
}
|
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 82 KiB |
|
@ -11,6 +11,7 @@ import eu.kanade.tachiyomi.source.online.HttpSource
|
|||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.Request
|
||||
|
@ -24,13 +25,34 @@ abstract class ZeistManga(
|
|||
override val lang: String,
|
||||
) : HttpSource() {
|
||||
|
||||
override val supportsLatest = false
|
||||
override val supportsLatest = true
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
private val intl by lazy { ZeistMangaIntl(lang) }
|
||||
|
||||
override fun popularMangaRequest(page: Int): Request {
|
||||
override fun headersBuilder(): Headers.Builder = super.headersBuilder()
|
||||
.add("Referer", "$baseUrl/")
|
||||
|
||||
override fun popularMangaRequest(page: Int): Request = GET(baseUrl, headers)
|
||||
|
||||
protected open val popularMangaSelector = "div.PopularPosts div.grid > figure"
|
||||
protected open val popularMangaSelectorTitle = "figcaption > a"
|
||||
protected open val popularMangaSelectorUrl = "figcaption > a"
|
||||
|
||||
override fun popularMangaParse(response: Response): MangasPage {
|
||||
val document = response.asJsoup()
|
||||
val mangas = document.select(popularMangaSelector).map { element ->
|
||||
SManga.create().apply {
|
||||
thumbnail_url = element.selectFirst("img")!!.attr("abs:src")
|
||||
title = element.selectFirst(popularMangaSelectorTitle)!!.text()
|
||||
setUrlWithoutDomain(element.selectFirst(popularMangaSelectorUrl)!!.attr("href"))
|
||||
}
|
||||
}
|
||||
return MangasPage(mangas, false)
|
||||
}
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request {
|
||||
val startIndex = maxMangaResults * (page - 1) + 1
|
||||
val url = apiUrl()
|
||||
.addQueryParameter("orderby", "published")
|
||||
|
@ -41,7 +63,7 @@ abstract class ZeistManga(
|
|||
return GET(url, headers)
|
||||
}
|
||||
|
||||
override fun popularMangaParse(response: Response): MangasPage {
|
||||
override fun latestUpdatesParse(response: Response): MangasPage {
|
||||
val jsonString = response.body.string()
|
||||
val result = json.decodeFromString<ZeistMangaDto>(jsonString)
|
||||
|
||||
|
@ -59,9 +81,6 @@ abstract class ZeistManga(
|
|||
return MangasPage(mangalist, false)
|
||||
}
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request = throw UnsupportedOperationException("Not used.")
|
||||
override fun latestUpdatesParse(response: Response): MangasPage = throw UnsupportedOperationException("Not used.")
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
val startIndex = maxMangaResults * (page - 1) + 1
|
||||
val url = apiUrl()
|
||||
|
@ -70,7 +89,8 @@ abstract class ZeistManga(
|
|||
|
||||
if (query.isNotBlank()) {
|
||||
url.addQueryParameter("q", query)
|
||||
return GET(url.build(), headers)
|
||||
val searchUrl = url.build().toString().replaceLast("q=", "q=label:$mangaCategory+")
|
||||
return GET(searchUrl, headers)
|
||||
}
|
||||
|
||||
filters.forEach { filter ->
|
||||
|
@ -103,20 +123,65 @@ abstract class ZeistManga(
|
|||
return GET(url.build(), headers)
|
||||
}
|
||||
|
||||
override fun searchMangaParse(response: Response) = popularMangaParse(response)
|
||||
override fun searchMangaParse(response: Response) = latestUpdatesParse(response)
|
||||
|
||||
protected open val statusSelectorList = listOf(
|
||||
"Status",
|
||||
"Estado",
|
||||
)
|
||||
|
||||
protected open val authorSelectorList = listOf(
|
||||
"Author",
|
||||
"Autor",
|
||||
"الكاتب",
|
||||
"Yazar",
|
||||
)
|
||||
|
||||
protected open val artisSelectorList = listOf(
|
||||
"Artist",
|
||||
"Artista",
|
||||
"الرسام",
|
||||
"Çizer",
|
||||
)
|
||||
|
||||
protected open val mangaDetailsSelector = ".grid.gtc-235fr"
|
||||
protected open val mangaDetailsSelectorDescription = "#synopsis"
|
||||
protected open val mangaDetailsSelectorGenres = "div.mt-15 > a[rel=tag]"
|
||||
protected open val mangaDetailsSelectorInfo = ".y6x11p"
|
||||
protected open val mangaDetailsSelectorInfoTitle = "strong"
|
||||
protected open val mangaDetailsSelectorInfoDescription = "span.dt"
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
val document = response.asJsoup()
|
||||
val profileManga = document.selectFirst(".grid.gtc-235fr")!!
|
||||
val profileManga = document.selectFirst(mangaDetailsSelector)!!
|
||||
return SManga.create().apply {
|
||||
thumbnail_url = profileManga.selectFirst("img")!!.attr("abs:src")
|
||||
description = profileManga.select("#synopsis").text()
|
||||
genre = profileManga.select("div.mt-15 > a[rel=tag]")
|
||||
description = profileManga.select(mangaDetailsSelectorDescription).text()
|
||||
genre = profileManga.select(mangaDetailsSelectorGenres)
|
||||
.joinToString { it.text() }
|
||||
|
||||
val infoElement = profileManga.select(mangaDetailsSelectorInfo)
|
||||
infoElement.forEach { element ->
|
||||
val infoText = element.ownText().trim().ifEmpty { element.selectFirst(mangaDetailsSelectorInfoTitle)?.text()?.trim() ?: "" }
|
||||
val descText = element.select(mangaDetailsSelectorInfoDescription).text().trim()
|
||||
when {
|
||||
statusSelectorList.any { infoText.contains(it) } -> {
|
||||
status = parseStatus(descText)
|
||||
}
|
||||
|
||||
authorSelectorList.any { infoText.contains(it) } -> {
|
||||
author = descText
|
||||
}
|
||||
|
||||
artisSelectorList.any { infoText.contains(it) } -> {
|
||||
artist = descText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected open val chapterCategory = "Chapter"
|
||||
protected open val chapterCategory: String = "Chapter"
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
val document = response.asJsoup()
|
||||
|
@ -197,7 +262,7 @@ abstract class ZeistManga(
|
|||
return url.toString()
|
||||
}
|
||||
|
||||
open val pageListSelector = "div.check-box div.separator"
|
||||
protected open val pageListSelector = "div.check-box div.separator"
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
val document = response.asJsoup()
|
||||
|
@ -209,7 +274,9 @@ abstract class ZeistManga(
|
|||
|
||||
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Not used.")
|
||||
|
||||
open fun apiUrl(feed: String = "Series"): HttpUrl.Builder {
|
||||
protected open val mangaCategory: String = "Series"
|
||||
|
||||
open fun apiUrl(feed: String = mangaCategory): HttpUrl.Builder {
|
||||
return "$baseUrl/feeds/posts/default/-/".toHttpUrl().newBuilder()
|
||||
.addPathSegment(feed)
|
||||
.addQueryParameter("alt", "json")
|
||||
|
@ -229,6 +296,9 @@ abstract class ZeistManga(
|
|||
return FilterList(emptyList())
|
||||
}
|
||||
|
||||
filterList.add(Filter.Header(intl.filterWarning))
|
||||
filterList.add(Filter.Separator())
|
||||
|
||||
if (hasStatusFilter) filterList.add(StatusList(intl.statusFilterTitle, getStatusList()))
|
||||
if (hasTypeFilter) filterList.add(TypeList(intl.typeFilterTitle, getTypeList()))
|
||||
if (hasLanguageFilter) filterList.add(LanguageList(intl.languageFilterTitle, getLanguageList()))
|
||||
|
@ -306,6 +376,48 @@ abstract class ZeistManga(
|
|||
Language("English", "English"),
|
||||
)
|
||||
|
||||
protected open val statusOnGoingList = listOf(
|
||||
"ongoing",
|
||||
"en curso",
|
||||
"ativo",
|
||||
"lançando",
|
||||
"مستمر",
|
||||
)
|
||||
|
||||
protected open val statusCompletedList = listOf(
|
||||
"completed",
|
||||
"completo",
|
||||
)
|
||||
|
||||
protected open val statusHiatusList = listOf(
|
||||
"hiatus",
|
||||
)
|
||||
|
||||
protected open val statusCancelledList = listOf(
|
||||
"cancelled",
|
||||
"dropped",
|
||||
"dropado",
|
||||
"abandonado",
|
||||
"cancelado",
|
||||
)
|
||||
|
||||
protected open fun parseStatus(element: String): Int = when (element.lowercase().trim()) {
|
||||
in statusOnGoingList -> SManga.ONGOING
|
||||
in statusCompletedList -> SManga.COMPLETED
|
||||
in statusHiatusList -> SManga.ON_HIATUS
|
||||
in statusCancelledList -> SManga.CANCELLED
|
||||
else -> SManga.UNKNOWN
|
||||
}
|
||||
|
||||
private fun String.replaceLast(oldValue: String, newValue: String): String {
|
||||
val lastIndexOf = lastIndexOf(oldValue)
|
||||
return if (lastIndexOf == -1) {
|
||||
this
|
||||
} else {
|
||||
substring(0, lastIndexOf) + newValue + substring(lastIndexOf + oldValue.length)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val maxMangaResults = 20
|
||||
private const val maxChapterResults = 999999
|
||||
|
|
|
@ -9,18 +9,26 @@ class ZeistMangaGenerator : ThemeSourceGenerator {
|
|||
|
||||
override val themeClass = "ZeistManga"
|
||||
|
||||
override val baseVersionCode: Int = 7
|
||||
override val baseVersionCode: Int = 8
|
||||
|
||||
override val sources = listOf(
|
||||
SingleLang("AnimeXNovel", "https://www.animexnovel.com", "pt-BR"),
|
||||
SingleLang("Asupan Komik", "https://www.asupankomik.my.id", "id", overrideVersionCode = 1),
|
||||
SingleLang("Eleven Scanlator", "https://elevenscanlator.blogspot.com", "pt-BR"),
|
||||
SingleLang("Guilda Tier Draw", "https://www.guildatierdraw.com", "pt-BR", isNsfw = true),
|
||||
SingleLang("Hijala", "https://hijala.blogspot.com", "ar"),
|
||||
SingleLang("KLManhua", "https://klmanhua.blogspot.com", "id", isNsfw = true),
|
||||
SingleLang("Manga Ai Land", "https://manga-ai-land.blogspot.com", "ar"),
|
||||
SingleLang("Muslos No Sekai", "https://muslosnosekai.blogspot.com", "es"),
|
||||
SingleLang("ShiyuraSub", "https://shiyurasub.blogspot.com", "id"),
|
||||
SingleLang("Tooncubus", "https://www.tooncubus.top", "id", isNsfw = true),
|
||||
SingleLang("SobatManKu", "https://www.sobatmanku19.site", "id"),
|
||||
SingleLang("KomikRealm", "https://www.komikrealm.my.id", "id"),
|
||||
SingleLang("Loner Translations", "https://loner-tl.blogspot.com", "ar"),
|
||||
SingleLang("Manga Ai Land", "https://manga-ai-land.blogspot.com", "ar"),
|
||||
SingleLang("Manga Soul", "https://www.manga-soul.com", "ar", isNsfw = true),
|
||||
SingleLang("MikoRoku", "https://www.mikoroku.web.id", "id", isNsfw = true),
|
||||
SingleLang("Mikrokosmos Fansub", "https://mikrokosmosfb.blogspot.com", "tr", isNsfw = true),
|
||||
SingleLang("ShiyuraSub", "https://shiyurasub.blogspot.com", "id"),
|
||||
SingleLang("SobatManKu", "https://www.sobatmanku19.site", "id"),
|
||||
SingleLang("Tooncubus", "https://www.tooncubus.top", "id", isNsfw = true),
|
||||
SingleLang("Tyrant Scans", "https://www.tyrantscans.com", "pt-BR"),
|
||||
SingleLang("Yokai", "https://yokai-team.blogspot.com", "ar"),
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
|