Remove YomuMangas (#3803)

This commit is contained in:
Chopper 2024-06-29 04:11:55 -03:00 committed by Draff
parent c26616dfc5
commit 96cde60458
No known key found for this signature in database
GPG Key ID: E8A89F3211677653
9 changed files with 0 additions and 385 deletions

View File

@ -1,8 +0,0 @@
ext {
extName = 'Yomu Mangás'
extClass = '.YomuMangas'
extVersionCode = 3
isNsfw = true
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,208 +0,0 @@
package eu.kanade.tachiyomi.extension.pt.yomumangas
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
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.source.online.HttpSource
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import rx.Observable
import uy.kohesive.injekt.injectLazy
import java.util.concurrent.TimeUnit
class YomuMangas : HttpSource() {
override val name = "Yomu Mangás"
override val baseUrl = "https://yomumangas.com"
override val lang = "pt-BR"
override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.rateLimitHost(baseUrl.toHttpUrl(), 1, 1, TimeUnit.SECONDS)
.rateLimitHost(API_URL.toHttpUrl(), 1, 1, TimeUnit.SECONDS)
.rateLimitHost(CDN_URL.toHttpUrl(), 1, 2, TimeUnit.SECONDS)
.build()
private val json: Json by injectLazy()
private val apiHeaders: Headers by lazy { apiHeadersBuilder().build() }
override fun headersBuilder(): Headers.Builder = Headers.Builder()
.add("Origin", baseUrl)
.add("Referer", baseUrl)
private fun apiHeadersBuilder(): Headers.Builder = headersBuilder()
.add("Accept", ACCEPT_JSON)
override fun popularMangaRequest(page: Int): Request {
return GET("$API_URL/mangas/home", apiHeaders)
}
override fun popularMangaParse(response: Response): MangasPage {
val result = response.parseAs<YomuMangasHomeDto>()
val seriesList = result.votes.map(YomuMangasSeriesDto::toSManga)
return MangasPage(seriesList, hasNextPage = false)
}
override fun latestUpdatesRequest(page: Int) = popularMangaRequest(page)
override fun latestUpdatesParse(response: Response): MangasPage {
val result = response.parseAs<YomuMangasHomeDto>()
val seriesList = result.updates.map(YomuMangasSeriesDto::toSManga)
return MangasPage(seriesList, hasNextPage = false)
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val apiUrl = "$API_URL/mangas/search".toHttpUrl().newBuilder()
.addQueryParameter("query", query)
.addQueryParameter("page", page.toString())
filters.filterIsInstance<UrlQueryFilter>()
.forEach { it.addQueryParameter(apiUrl) }
return GET(apiUrl.build(), apiHeaders)
}
override fun searchMangaParse(response: Response): MangasPage {
val result = response.parseAs<YomuMangasSearchDto>()
val seriesList = result.mangas.map(YomuMangasSeriesDto::toSManga)
return MangasPage(seriesList, result.hasNextPage)
}
override fun getMangaUrl(manga: SManga): String = baseUrl + manga.url
override fun mangaDetailsRequest(manga: SManga): Request {
val id = manga.url
.substringAfter("/manga/")
.substringBefore("/")
return GET("$API_URL/mangas/$id", apiHeaders)
}
override fun mangaDetailsParse(response: Response): SManga {
return response.parseAs<YomuMangasDetailsDto>().manga.toSManga()
}
override fun chapterListRequest(manga: SManga) = mangaDetailsRequest(manga)
private fun chapterListApiRequest(mangaId: Int): Request {
return GET("$API_URL/mangas/$mangaId/chapters", apiHeaders)
}
override fun chapterListParse(response: Response): List<SChapter> {
val series = response.parseAs<YomuMangasDetailsDto>().manga
return client.newCall(chapterListApiRequest(series.id)).execute()
.parseAs<YomuMangasChaptersDto>().chapters
.sortedByDescending(YomuMangasChapterDto::chapter)
.map { it.toSChapter(series) }
}
override fun getChapterUrl(chapter: SChapter): String = baseUrl + chapter.url
override fun pageListRequest(chapter: SChapter): Request {
val urlParts = chapter.url.split("/", "#")
val seriesId = urlParts[2]
val chapterNumber = urlParts[6]
return GET("$API_URL/mangas/$seriesId/chapters/$chapterNumber", apiHeaders)
}
override fun pageListParse(response: Response): List<Page> {
return response.parseAs<YomuMangasChapterDetailsDto>()
.chapter.images.orEmpty()
.mapIndexed { i, image -> Page(i, "", "$CDN_URL/${image.uri}") }
}
override fun fetchImageUrl(page: Page): Observable<String> = Observable.just(page.imageUrl!!)
override fun imageUrlParse(response: Response): String = ""
override fun imageRequest(page: Page): Request {
val newHeaders = headersBuilder()
.add("Accept", ACCEPT_IMAGE)
.build()
return GET(page.imageUrl!!, newHeaders)
}
override fun getFilterList(): FilterList = FilterList(
StatusFilter(getStatusList()),
TypeFilter(getTypesList()),
NsfwContentFilter(),
AdultContentFilter(),
GenreFilter(getGenresList()),
)
private fun getStatusList(): List<Status> = listOf(
Status("Todos", ""),
Status("Lançando", "RELEASING"),
Status("Finalizado", "FINISHED"),
Status("Cancelado", "CANCELLED"),
Status("Hiato", "HIATUS"),
Status("Não lançado", "NOT_YET_RELEASED"),
Status("Traduzindo", "TRANSLATING"),
Status("Desconhecido", "UNKNOWN"),
)
private fun getTypesList(): List<Type> = listOf(
Type("Todos", ""),
Type("Mangá", "MANGA"),
Type("Manhwa", "MANHWA"),
Type("Mangá em hiato", "MANGA_HIATUS"),
Type("Webcomic", "WEBCOMIC"),
Type("Webtoon", "WEBTOON"),
Type("Hentai", "HENTAI"),
Type("Doujinshi", "DOUJIN"),
Type("One-shot", "ONESHOT"),
)
private fun getGenresList(): List<Genre> = listOf(
Genre("Ação", "1"),
Genre("Aventura", "8"),
Genre("Comédia", "2"),
Genre("Drama", "3"),
Genre("Ecchi", "15"),
Genre("Esportes", "14"),
Genre("Fantasia", "6"),
Genre("Hentai", "19"),
Genre("Horror", "4"),
Genre("Mahou shoujo", "18"),
Genre("Mecha", "17"),
Genre("Mistério", "7"),
Genre("Música", "16"),
Genre("Psicológico", "9"),
Genre("Romance", "13"),
Genre("Sci-fi", "11"),
Genre("Slice of life", "10"),
Genre("Sobrenatural", "5"),
Genre("Suspense", "12"),
)
private inline fun <reified T> Response.parseAs(): T = use {
json.decodeFromString(it.body.string())
}
companion object {
private const val ACCEPT_IMAGE = "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8"
private const val ACCEPT_JSON = "application/json"
private const val API_URL = "https://api.yomumangas.com"
const val CDN_URL = "https://images.yomumangas.com"
}
}

View File

@ -1,96 +0,0 @@
package eu.kanade.tachiyomi.extension.pt.yomumangas
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.text.SimpleDateFormat
import java.util.Locale
@Serializable
data class YomuMangasHomeDto(
val updates: List<YomuMangasSeriesDto> = emptyList(),
val votes: List<YomuMangasSeriesDto> = emptyList(),
)
@Serializable
data class YomuMangasSearchDto(
val mangas: List<YomuMangasSeriesDto> = emptyList(),
val page: Int,
val pages: Int,
) {
val hasNextPage: Boolean
get() = page < pages
}
@Serializable
data class YomuMangasDetailsDto(val manga: YomuMangasSeriesDto)
@Serializable
data class YomuMangasSeriesDto(
val id: Int,
val slug: String,
val title: String,
val cover: String? = null,
val status: String,
val authors: List<String>? = emptyList(),
val artists: List<String>? = emptyList(),
val genres: List<YomuMangasGenreDto>? = emptyList(),
val description: String? = null,
) {
fun toSManga(): SManga = SManga.create().apply {
title = this@YomuMangasSeriesDto.title
author = authors.orEmpty().joinToString { it.trim() }
artist = artists.orEmpty().joinToString { it.trim() }
genre = genres.orEmpty()
.sortedBy { it.name }
.joinToString { it.name.trim() }
description = this@YomuMangasSeriesDto.description?.trim()
status = when (this@YomuMangasSeriesDto.status) {
"RELEASING" -> SManga.ONGOING
"FINISHED" -> SManga.COMPLETED
"HIATUS" -> SManga.ON_HIATUS
"CANCELLED" -> SManga.CANCELLED
"TRANSLATING" -> SManga.PUBLISHING_FINISHED
else -> SManga.UNKNOWN
}
thumbnail_url = cover?.let { "${YomuMangas.CDN_URL}/$it" }
url = "/manga/$id/$slug"
}
}
@Serializable
data class YomuMangasGenreDto(val name: String)
@Serializable
data class YomuMangasChaptersDto(val chapters: List<YomuMangasChapterDto> = emptyList())
@Serializable
data class YomuMangasChapterDto(
val id: Int,
val chapter: Float,
@SerialName("uploaded_at") val uploadedAt: String,
val images: List<YomuMangasImageDto>? = emptyList(),
) {
fun toSChapter(series: YomuMangasSeriesDto): SChapter = SChapter.create().apply {
name = "Capítulo ${chapter.toString().removeSuffix(".0")}"
date_upload = runCatching { DATE_FORMATTER.parse(uploadedAt)?.time }
.getOrNull() ?: 0L
url = "/manga/${series.id}/${series.slug}/chapter/$id#$chapter"
}
companion object {
private val DATE_FORMATTER by lazy {
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US)
}
}
}
@Serializable
data class YomuMangasChapterDetailsDto(val chapter: YomuMangasChapterDto)
@Serializable
data class YomuMangasImageDto(val uri: String)

View File

@ -1,73 +0,0 @@
package eu.kanade.tachiyomi.extension.pt.yomumangas
import eu.kanade.tachiyomi.source.model.Filter
import okhttp3.HttpUrl
interface UrlQueryFilter {
fun addQueryParameter(url: HttpUrl.Builder)
}
class NsfwContentFilter : Filter.CheckBox("Conteúdo NSFW"), UrlQueryFilter {
override fun addQueryParameter(url: HttpUrl.Builder) {
if (state) {
url.addQueryParameter("nsfw", "true")
}
}
}
class AdultContentFilter : Filter.CheckBox("Conteúdo adulto"), UrlQueryFilter {
override fun addQueryParameter(url: HttpUrl.Builder) {
if (state) {
url.addQueryParameter("hentai", "true")
}
}
}
open class EnhancedSelect<T>(name: String, values: Array<T>) : Filter.Select<T>(name, values) {
val selected: T
get() = values[state]
}
data class Status(val name: String, val value: String) {
override fun toString() = name
}
class StatusFilter(statusList: List<Status>) :
EnhancedSelect<Status>("Status", statusList.toTypedArray()),
UrlQueryFilter {
override fun addQueryParameter(url: HttpUrl.Builder) {
if (state > 0) {
url.addQueryParameter("status", selected.value)
}
}
}
data class Type(val name: String, val value: String) {
override fun toString() = name
}
class TypeFilter(typesList: List<Type>) :
EnhancedSelect<Type>("Tipo", typesList.toTypedArray()),
UrlQueryFilter {
override fun addQueryParameter(url: HttpUrl.Builder) {
if (state > 0) {
url.addQueryParameter("type", selected.value)
}
}
}
class Genre(name: String, val id: String) : Filter.CheckBox(name) {
override fun toString() = name
}
class GenreFilter(genres: List<Genre>) :
Filter.Group<Genre>("Gêneros", genres),
UrlQueryFilter {
override fun addQueryParameter(url: HttpUrl.Builder) {
state.filter(Genre::state)
.forEach { url.addQueryParameter("genres[]", it.id) }
}
}