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
					
				
							
								
								
									
										32
									
								
								multisrc/overrides/mangasar/mangasup/src/MangasUp.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								multisrc/overrides/mangasar/mangasup/src/MangasUp.kt
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										136
									
								
								multisrc/overrides/mangasar/seemangas/src/Seemangas.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								multisrc/overrides/mangasar/seemangas/src/Seemangas.kt
									
									
									
									
									
										Normal file
									
								
							@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user