Remove MM and add SM, MU on MangaSar (#14615)
* Remove MM and add SM on MangaSar. * Add MU as source as well.
This commit is contained in:
parent
00099ca121
commit
df8f6857f9
|
@ -0,0 +1,32 @@
|
|||
package eu.kanade.tachiyomi.extension.pt.mangasup
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.mangasar.MangaSar
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class MangasUp : MangaSar(
|
||||
"MangásUp",
|
||||
"https://mangasup.net",
|
||||
"pt-BR"
|
||||
) {
|
||||
|
||||
override fun chapterListPaginatedRequest(mangaUrl: String, page: Int): Request {
|
||||
return GET(baseUrl + mangaUrl, headers)
|
||||
}
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
return response.asJsoup()
|
||||
.select("ul.full-chapters-list > li > a")
|
||||
.map(::chapterFromElement)
|
||||
}
|
||||
|
||||
private fun chapterFromElement(element: Element): SChapter = SChapter.create().apply {
|
||||
name = element.selectFirst("span.cap-text")!!.text()
|
||||
date_upload = element.selectFirst("span.chapter-date")?.text()?.toDate() ?: 0L
|
||||
setUrlWithoutDomain(element.attr("href"))
|
||||
}
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
package eu.kanade.tachiyomi.extension.pt.meusmangas
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.mangasar.MangaSar
|
||||
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
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class MeusMangas : MangaSar(
|
||||
"Meus Mangás",
|
||||
"https://meusmangas.net",
|
||||
"pt-BR"
|
||||
) {
|
||||
|
||||
override fun popularMangaSelector() = "ul.sidebar-popular li.popular-treending"
|
||||
|
||||
override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply {
|
||||
title = element.selectFirst("h4.title").text()
|
||||
thumbnail_url = element.selectFirst("div.tumbl img").attr("src")
|
||||
setUrlWithoutDomain(element.selectFirst("a").attr("abs:href"))
|
||||
}
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request {
|
||||
val newHeaders = headersBuilder()
|
||||
.add("X-Requested-With", "XMLHttpRequest")
|
||||
.build()
|
||||
|
||||
val pagePath = if (page > 1) "page/$page" else ""
|
||||
|
||||
return GET("$baseUrl/$pagePath", newHeaders)
|
||||
}
|
||||
|
||||
override fun latestUpdatesParse(response: Response): MangasPage {
|
||||
val document = response.asJsoup()
|
||||
|
||||
val mangaList = document.select("li.item_news-manga")
|
||||
.map(::latestMangaFromElement)
|
||||
|
||||
val hasNextPage = document.select("div.loadmore.morepage").firstOrNull() != null
|
||||
|
||||
return MangasPage(mangaList, hasNextPage)
|
||||
}
|
||||
|
||||
private fun latestMangaFromElement(element: Element): SManga = SManga.create().apply {
|
||||
title = element.select("h3.entry-title a").text()
|
||||
thumbnail_url = element.select("img.manga").attr("src")
|
||||
setUrlWithoutDomain(element.select("a").first().attr("abs:href"))
|
||||
}
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
val document = response.asJsoup()
|
||||
val infoElement = document.selectFirst("div.box-single:has(div.mangapage)")
|
||||
|
||||
return SManga.create().apply {
|
||||
title = infoElement.selectFirst("h1.kw-title").text()
|
||||
author = infoElement.selectFirst("div.mdq.author").text().trim()
|
||||
description = infoElement.selectFirst("div.sinopse-page").text()
|
||||
genre = infoElement.select("div.generos a.widget-btn").joinToString { it.text() }
|
||||
status = infoElement.selectFirst("span.mdq").text().toStatus()
|
||||
thumbnail_url = infoElement.selectFirst("div.thumb img").attr("abs:src")
|
||||
}
|
||||
}
|
||||
|
||||
override fun chapterListPaginatedRequest(mangaUrl: String, page: Int): Request {
|
||||
val newHeaders = headersBuilder()
|
||||
.add("X-Requested-With", "XMLHttpRequest")
|
||||
.build()
|
||||
|
||||
return GET("$baseUrl$mangaUrl/page/$page", newHeaders)
|
||||
}
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
var document = response.asJsoup()
|
||||
|
||||
val chapterList = document.select(chapterListSelector())
|
||||
.map(::chapterFromElement)
|
||||
.toMutableList()
|
||||
|
||||
val mangaUrl = response.request.url.toString()
|
||||
.substringAfter(baseUrl)
|
||||
.substringBefore("/page")
|
||||
var hasNextPage = document.select(chapterListNextPageSelector())
|
||||
.firstOrNull()
|
||||
|
||||
while (hasNextPage != null) {
|
||||
val page = hasNextPage.attr("href")
|
||||
.substringAfter("page/")
|
||||
.toInt()
|
||||
|
||||
val nextRequest = chapterListPaginatedRequest(mangaUrl, page)
|
||||
val nextResponse = client.newCall(nextRequest).execute()
|
||||
document = nextResponse.asJsoup()
|
||||
|
||||
chapterList += document.select(chapterListSelector())
|
||||
.map(::chapterFromElement)
|
||||
|
||||
hasNextPage = document.select(chapterListNextPageSelector())
|
||||
.firstOrNull()
|
||||
}
|
||||
|
||||
return chapterList
|
||||
}
|
||||
|
||||
private fun chapterListSelector() = "ul.list-of-chapters li > a"
|
||||
|
||||
private fun chapterListNextPageSelector() = "ul.content-pagination li.active + li:not(.next) a"
|
||||
|
||||
private fun chapterFromElement(element: Element): SChapter = SChapter.create().apply {
|
||||
name = element.select("span.cap-text").text()
|
||||
date_upload = element.select("span.chapter-date").text().toDate()
|
||||
setUrlWithoutDomain(element.attr("abs:href"))
|
||||
}
|
||||
|
||||
private fun String.toStatus(): Int = when (this) {
|
||||
"Em andamento" -> SManga.ONGOING
|
||||
"Completo" -> SManga.COMPLETED
|
||||
else -> SManga.UNKNOWN
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
package eu.kanade.tachiyomi.extension.pt.seemangas
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.mangasar.MangaSar
|
||||
import eu.kanade.tachiyomi.multisrc.mangasar.MangaSarLatestDto
|
||||
import eu.kanade.tachiyomi.multisrc.mangasar.MangaSarReaderDto
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
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.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class Seemangas : MangaSar(
|
||||
"Seemangas",
|
||||
"https://seemangas.com",
|
||||
"pt-BR"
|
||||
) {
|
||||
|
||||
override fun popularMangaSelector() = "ul.sidebar-popular li.popular-treending"
|
||||
|
||||
override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply {
|
||||
title = element.selectFirst("h4.title").text()
|
||||
thumbnail_url = element.selectFirst("div.tumbl img").attr("data-lazy-src")
|
||||
setUrlWithoutDomain(element.selectFirst("a").attr("abs:href"))
|
||||
}
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request {
|
||||
val payload = FormBody.Builder()
|
||||
.add("action", "get_lancamentos")
|
||||
.add("pagina", page.toString())
|
||||
.build()
|
||||
|
||||
val newHeaders = headersBuilder()
|
||||
.add("Content-Length", payload.contentLength().toString())
|
||||
.add("Content-Type", payload.contentType().toString())
|
||||
.add("X-Requested-With", "XMLHttpRequest")
|
||||
.build()
|
||||
|
||||
return POST("$baseUrl/wp-admin/admin-ajax.php", newHeaders, payload)
|
||||
}
|
||||
|
||||
override fun latestUpdatesParse(response: Response): MangasPage {
|
||||
val result = response.parseAs<MangaSarLatestDto>()
|
||||
|
||||
val latestMangas = result.releases
|
||||
.map(::latestUpdatesFromObject)
|
||||
.distinctBy { it.url }
|
||||
|
||||
return MangasPage(latestMangas, hasNextPage = result.releases.isNotEmpty())
|
||||
}
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
val document = response.asJsoup()
|
||||
val infoElement = document.selectFirst("div.box-single:has(div.mangapage)")
|
||||
|
||||
return SManga.create().apply {
|
||||
title = infoElement.selectFirst("h1.kw-title").text()
|
||||
author = infoElement.selectFirst("div.mdq.author").text().trim()
|
||||
description = infoElement.selectFirst("div.sinopse-page").text()
|
||||
genre = infoElement.select("div.generos a.widget-btn").joinToString { it.text() }
|
||||
status = infoElement.selectFirst("span.mdq").text().toStatus()
|
||||
thumbnail_url = infoElement.selectFirst("div.thumb img").attr("abs:data-lazy-src")
|
||||
}
|
||||
}
|
||||
override fun chapterListPaginatedRequest(mangaUrl: String, page: Int): Request {
|
||||
return GET(baseUrl + mangaUrl, headers)
|
||||
}
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
return response.asJsoup()
|
||||
.select("ul.full-chapters-list > li > a")
|
||||
.map(::chapterFromElement)
|
||||
}
|
||||
|
||||
private fun chapterFromElement(element: Element): SChapter = SChapter.create().apply {
|
||||
name = element.selectFirst("span.cap-text")!!.text()
|
||||
date_upload = element.selectFirst("span.chapter-date")?.text()?.toDate() ?: 0L
|
||||
setUrlWithoutDomain(element.attr("href"))
|
||||
}
|
||||
|
||||
override fun pageListApiRequest(chapterUrl: String, serieId: String, token: String): Request {
|
||||
val chapterId = CHAPTER_ID_REGEX.find(chapterUrl)!!.groupValues[1]
|
||||
|
||||
val payload = FormBody.Builder()
|
||||
.add("action", "get_image_list")
|
||||
.add("id_serie", chapterId)
|
||||
.add("secury", token)
|
||||
.build()
|
||||
|
||||
val newHeaders = apiHeadersBuilder()
|
||||
.add("Content-Length", payload.contentLength().toString())
|
||||
.add("Content-Type", payload.contentType().toString())
|
||||
.set("Referer", chapterUrl)
|
||||
.build()
|
||||
|
||||
return POST("$baseUrl/wp-admin/admin-ajax.php", newHeaders, payload)
|
||||
}
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
val document = response.asJsoup()
|
||||
val apiParams = document.selectFirst("script:containsData(id_serie)")?.data()
|
||||
?: throw Exception(TOKEN_NOT_FOUND)
|
||||
|
||||
val chapterUrl = response.request.url.toString()
|
||||
val infoReader = apiParams
|
||||
.substringAfter("{")
|
||||
.substringBeforeLast("}")
|
||||
val readerParams = json.parseToJsonElement("{$infoReader}").jsonObject
|
||||
val serieId = readerParams["id_serie"]!!.jsonPrimitive.content
|
||||
val token = readerParams["token"]!!.jsonPrimitive.content
|
||||
|
||||
val apiRequest = pageListApiRequest(chapterUrl, serieId, token)
|
||||
val apiResponse = client.newCall(apiRequest).execute().parseAs<MangaSarReaderDto>()
|
||||
|
||||
return apiResponse.images
|
||||
.filter { it.url.startsWith("http") }
|
||||
.mapIndexed { i, page -> Page(i, chapterUrl, page.url) }
|
||||
}
|
||||
|
||||
private fun String.toStatus(): Int = when (this) {
|
||||
"Em andamento" -> SManga.ONGOING
|
||||
"Completo" -> SManga.COMPLETED
|
||||
else -> SManga.UNKNOWN
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val CHAPTER_ID_REGEX = "(\\d+)$".toRegex()
|
||||
}
|
||||
}
|
|
@ -50,7 +50,7 @@ abstract class MangaSar(
|
|||
.add("Accept-Language", ACCEPT_LANGUAGE)
|
||||
.add("Referer", "$baseUrl/")
|
||||
|
||||
private fun apiHeadersBuilder(): Headers.Builder = headersBuilder()
|
||||
protected fun apiHeadersBuilder(): Headers.Builder = headersBuilder()
|
||||
.set("Accept", ACCEPT)
|
||||
.add("X-Requested-With", "XMLHttpRequest")
|
||||
|
||||
|
@ -100,12 +100,12 @@ abstract class MangaSar(
|
|||
.map(::latestUpdatesFromObject)
|
||||
.distinctBy { it.url }
|
||||
|
||||
val hasNextPage = result.page.toInt() < result.totalPage
|
||||
val hasNextPage = result.page.toInt() < result.totalPage!!
|
||||
|
||||
return MangasPage(latestMangas, hasNextPage)
|
||||
}
|
||||
|
||||
private fun latestUpdatesFromObject(release: MangaSarReleaseDto) = SManga.create().apply {
|
||||
protected fun latestUpdatesFromObject(release: MangaSarReleaseDto) = SManga.create().apply {
|
||||
title = release.name.withoutEntities()
|
||||
thumbnail_url = release.image
|
||||
url = release.link
|
||||
|
@ -200,7 +200,7 @@ abstract class MangaSar(
|
|||
setUrlWithoutDomain(chapter.link)
|
||||
}
|
||||
|
||||
private fun pageListApiRequest(chapterUrl: String, serieId: String, token: String): Request {
|
||||
protected open fun pageListApiRequest(chapterUrl: String, serieId: String, token: String): Request {
|
||||
val newHeaders = apiHeadersBuilder()
|
||||
.set("Referer", chapterUrl)
|
||||
.build()
|
||||
|
@ -296,6 +296,6 @@ abstract class MangaSar(
|
|||
|
||||
private val DATE_FORMATTER by lazy { SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH) }
|
||||
|
||||
private const val TOKEN_NOT_FOUND = "Não foi possível obter o token de leitura."
|
||||
const val TOKEN_NOT_FOUND = "Não foi possível obter o token de leitura."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,14 @@ package eu.kanade.tachiyomi.multisrc.mangasar
|
|||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonNames
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
|
||||
@Serializable
|
||||
data class MangaSarLatestDto(
|
||||
val page: String,
|
||||
val releases: List<MangaSarReleaseDto> = emptyList(),
|
||||
@SerialName("total_page") val totalPage: Int
|
||||
@JsonNames("lancamentos") val releases: List<MangaSarReleaseDto> = emptyList(),
|
||||
@SerialName("total_page") val totalPage: Int? = 0
|
||||
)
|
||||
|
||||
@Serializable
|
||||
|
|
|
@ -14,7 +14,8 @@ class MangaSarGenerator : ThemeSourceGenerator {
|
|||
override val sources = listOf(
|
||||
SingleLang("Fire Mangás", "https://firemangas.com", "pt-BR", className = "FireMangas"),
|
||||
SingleLang("Mangazim", "https://mangazim.com", "pt-BR"),
|
||||
SingleLang("Meus Mangás", "https://meusmangas.net", "pt-BR", isNsfw = true, className = "MeusMangas", overrideVersionCode = 2)
|
||||
SingleLang("MangásUp", "https://mangasup.net", "pt-BR", className = "MangasUp"),
|
||||
SingleLang("Seemangas", "https://seemangas.com", "pt-BR", isNsfw = true)
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
|
Loading…
Reference in New Issue