MangaEsp: Update domain and add alternative names (#1470)
* Update domain * Get comics from next data (api has old results) * Add alternative names * Change name creation logic Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com> * Missing replace --------- Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									942ca100d8
								
							
						
					
					
						commit
						d6f01fea0b
					
				| @ -1,7 +1,7 @@ | |||||||
| ext { | ext { | ||||||
|     extName = 'MangaEsp' |     extName = 'MangaEsp' | ||||||
|     extClass = '.MangaEsp' |     extClass = '.MangaEsp' | ||||||
|     extVersionCode = 1 |     extVersionCode = 2 | ||||||
|     isNsfw = false |     isNsfw = false | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -29,9 +29,9 @@ class MangaEsp : HttpSource() { | |||||||
| 
 | 
 | ||||||
|     override val name = "MangaEsp" |     override val name = "MangaEsp" | ||||||
| 
 | 
 | ||||||
|     override val baseUrl = "https://mangaesp.co" |     override val baseUrl = "https://mangaesp.net" | ||||||
| 
 | 
 | ||||||
|     private val apiBaseUrl = "https://apis.mangaesp.co" |     private val apiBaseUrl = "https://apis.mangaesp.net" | ||||||
| 
 | 
 | ||||||
|     override val lang = "es" |     override val lang = "es" | ||||||
| 
 | 
 | ||||||
| @ -57,13 +57,7 @@ class MangaEsp : HttpSource() { | |||||||
|         val topWeekly = responseData.response.topWeekly.flatten().map { it.data } |         val topWeekly = responseData.response.topWeekly.flatten().map { it.data } | ||||||
|         val topMonthly = responseData.response.topMonthly.flatten().map { it.data } |         val topMonthly = responseData.response.topMonthly.flatten().map { it.data } | ||||||
| 
 | 
 | ||||||
|         val mangas = (topDaily + topWeekly + topMonthly).distinctBy { it.slug }.map { series -> |         val mangas = (topDaily + topWeekly + topMonthly).distinctBy { it.slug }.map { it.toSManga() } | ||||||
|             SManga.create().apply { |  | ||||||
|                 title = series.name |  | ||||||
|                 thumbnail_url = series.thumbnail |  | ||||||
|                 url = "/ver/${series.slug}" |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         return MangasPage(mangas, false) |         return MangasPage(mangas, false) | ||||||
|     } |     } | ||||||
| @ -73,13 +67,7 @@ class MangaEsp : HttpSource() { | |||||||
|     override fun latestUpdatesParse(response: Response): MangasPage { |     override fun latestUpdatesParse(response: Response): MangasPage { | ||||||
|         val responseData = json.decodeFromString<LastUpdatesDto>(response.body.string()) |         val responseData = json.decodeFromString<LastUpdatesDto>(response.body.string()) | ||||||
| 
 | 
 | ||||||
|         val mangas = responseData.response.map { series -> |         val mangas = responseData.response.map { it.toSManga() } | ||||||
|             SManga.create().apply { |  | ||||||
|                 title = series.name |  | ||||||
|                 thumbnail_url = series.thumbnail |  | ||||||
|                 url = "/ver/${series.slug}" |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         return MangasPage(mangas, false) |         return MangasPage(mangas, false) | ||||||
|     } |     } | ||||||
| @ -100,13 +88,17 @@ class MangaEsp : HttpSource() { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = GET("$baseUrl/api/comics", headers) |     override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = GET("$baseUrl/comics", headers) | ||||||
| 
 | 
 | ||||||
|     override fun searchMangaParse(response: Response): MangasPage = throw UnsupportedOperationException() |     override fun searchMangaParse(response: Response): MangasPage = throw UnsupportedOperationException() | ||||||
| 
 | 
 | ||||||
|     private fun searchMangaParse(response: Response, page: Int, query: String, filters: FilterList): MangasPage { |     private fun searchMangaParse(response: Response, page: Int, query: String, filters: FilterList): MangasPage { | ||||||
|         val responseData = json.decodeFromString<ComicsDto>(response.body.string()) |         val document = response.asJsoup() | ||||||
|         comicsList = responseData.response.toMutableList() |         val script = document.select("script:containsData(self.__next_f.push)").joinToString { it.data() } | ||||||
|  |         val jsonString = MANGA_LIST_REGEX.find(script)?.groupValues?.get(1) | ||||||
|  |             ?: throw Exception("No se pudo encontrar la lista de comics") | ||||||
|  |         val unescapedJson = jsonString.unescape() | ||||||
|  |         comicsList = json.decodeFromString<List<SeriesDto>>(unescapedJson).toMutableList() | ||||||
|         return parseComicsList(page, query, filters) |         return parseComicsList(page, query, filters) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -118,7 +110,11 @@ class MangaEsp : HttpSource() { | |||||||
| 
 | 
 | ||||||
|             if (query.isNotBlank()) { |             if (query.isNotBlank()) { | ||||||
|                 if (query.length < 2) throw Exception("La búsqueda debe tener al menos 2 caracteres") |                 if (query.length < 2) throw Exception("La búsqueda debe tener al menos 2 caracteres") | ||||||
|                 filteredList.addAll(comicsList.filter { it.name.contains(query, ignoreCase = true) }) |                 filteredList.addAll( | ||||||
|  |                     comicsList.filter { | ||||||
|  |                         it.name.contains(query, ignoreCase = true) || it.alternativeName?.contains(query, ignoreCase = true) == true | ||||||
|  |                     }, | ||||||
|  |                 ) | ||||||
|             } else { |             } else { | ||||||
|                 filteredList.addAll(comicsList) |                 filteredList.addAll(comicsList) | ||||||
|             } |             } | ||||||
| @ -154,7 +150,7 @@ class MangaEsp : HttpSource() { | |||||||
| 
 | 
 | ||||||
|         return MangasPage( |         return MangasPage( | ||||||
|             filteredList.subList((page - 1) * MANGAS_PER_PAGE, min(page * MANGAS_PER_PAGE, filteredList.size)) |             filteredList.subList((page - 1) * MANGAS_PER_PAGE, min(page * MANGAS_PER_PAGE, filteredList.size)) | ||||||
|                 .map { it.toSimpleSManga() }, |                 .map { it.toSManga() }, | ||||||
|             hasNextPage, |             hasNextPage, | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
| @ -163,42 +159,24 @@ class MangaEsp : HttpSource() { | |||||||
|         val responseBody = response.body.string() |         val responseBody = response.body.string() | ||||||
|         val mangaDetailsJson = MANGA_DETAILS_REGEX.find(responseBody)?.groupValues?.get(1) |         val mangaDetailsJson = MANGA_DETAILS_REGEX.find(responseBody)?.groupValues?.get(1) | ||||||
|             ?: throw Exception("No se pudo encontrar los detalles del manga") |             ?: throw Exception("No se pudo encontrar los detalles del manga") | ||||||
|         val unescapedJson = mangaDetailsJson.replace("\\", "") |         val unescapedJson = mangaDetailsJson.unescape() | ||||||
| 
 | 
 | ||||||
|         val series = json.decodeFromString<SeriesDto>(unescapedJson) |         return json.decodeFromString<SeriesDto>(unescapedJson).toSMangaDetails() | ||||||
|         return SManga.create().apply { |  | ||||||
|             title = series.name |  | ||||||
|             thumbnail_url = series.thumbnail |  | ||||||
|             description = series.synopsis |  | ||||||
|             genre = series.genders.joinToString { it.gender.name } |  | ||||||
|             author = series.authors.joinToString { it.author.name } |  | ||||||
|             artist = series.artists.joinToString { it.artist.name } |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override fun chapterListParse(response: Response): List<SChapter> { |     override fun chapterListParse(response: Response): List<SChapter> { | ||||||
|         val responseBody = response.body.string() |         val responseBody = response.body.string() | ||||||
|         val mangaDetailsJson = MANGA_DETAILS_REGEX.find(responseBody)?.groupValues?.get(1) |         val mangaDetailsJson = MANGA_DETAILS_REGEX.find(responseBody)?.groupValues?.get(1) | ||||||
|             ?: throw Exception("No se pudo encontrar la lista de capítulos") |             ?: throw Exception("No se pudo encontrar la lista de capítulos") | ||||||
|         val unescapedJson = mangaDetailsJson.replace("\\", "") |         val unescapedJson = mangaDetailsJson.unescape() | ||||||
|         val series = json.decodeFromString<SeriesDto>(unescapedJson) |         val series = json.decodeFromString<SeriesDto>(unescapedJson) | ||||||
|         return series.chapters.map { chapter -> |         return series.chapters.map { it.toSChapter(series.slug, dateFormat) } | ||||||
|             SChapter.create().apply { |  | ||||||
|                 name = if (chapter.name.isNullOrBlank()) { |  | ||||||
|                     "Capítulo ${chapter.number.toString().removeSuffix(".0")}" |  | ||||||
|                 } else { |  | ||||||
|                     "Capítulo ${chapter.number.toString().removeSuffix(".0")} - ${chapter.name}" |  | ||||||
|                 } |  | ||||||
|                 date_upload = runCatching { dateFormat.parse(chapter.date)?.time }.getOrNull() ?: 0L |  | ||||||
|                 url = "/ver/${series.slug}/${chapter.slug}" |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override fun pageListParse(response: Response): List<Page> { |     override fun pageListParse(response: Response): List<Page> { | ||||||
|         val document = response.asJsoup() |         val document = response.asJsoup() | ||||||
|         return document.select("main.contenedor.read img").mapIndexed { i, img -> |         return document.select("main.contenedor.read img").mapIndexed { i, img -> | ||||||
|             Page(i, "", img.imgAttr()) |             Page(i, imageUrl = img.imgAttr()) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -254,8 +232,14 @@ class MangaEsp : HttpSource() { | |||||||
|         else -> attr("abs:src") |         else -> attr("abs:src") | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private fun String.unescape(): String { | ||||||
|  |         return UNESCAPE_REGEX.replace(this, "$1") | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     companion object { |     companion object { | ||||||
|         private val MANGA_DETAILS_REGEX = """self.__next_f.push\(.*data\\":(\{.*lastChapters.*\}).*numFollow""".toRegex() |         private val UNESCAPE_REGEX = """\\(.)""".toRegex() | ||||||
|  |         private val MANGA_LIST_REGEX = """self\.__next_f\.push\(.*data\\":(\[.*trending.*])\}""".toRegex() | ||||||
|  |         private val MANGA_DETAILS_REGEX = """self\.__next_f\.push\(.*data\\":(\{.*lastChapters.*\}).*numFollow""".toRegex() | ||||||
|         private const val MANGAS_PER_PAGE = 15 |         private const val MANGAS_PER_PAGE = 15 | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,91 +1,118 @@ | |||||||
| package eu.kanade.tachiyomi.extension.es.mangaesp | package eu.kanade.tachiyomi.extension.es.mangaesp | ||||||
| 
 | 
 | ||||||
|  | import eu.kanade.tachiyomi.source.model.SChapter | ||||||
| import eu.kanade.tachiyomi.source.model.SManga | import eu.kanade.tachiyomi.source.model.SManga | ||||||
| import kotlinx.serialization.SerialName | import kotlinx.serialization.SerialName | ||||||
| import kotlinx.serialization.Serializable | import kotlinx.serialization.Serializable | ||||||
|  | import java.text.SimpleDateFormat | ||||||
| 
 | 
 | ||||||
| @Serializable | @Serializable | ||||||
| data class TopSeriesDto( | class TopSeriesDto( | ||||||
|     val response: TopSeriesResponseDto, |     val response: TopSeriesResponseDto, | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @Serializable | @Serializable | ||||||
| data class LastUpdatesDto( | class LastUpdatesDto( | ||||||
|     val response: List<SeriesDto>, |     val response: List<SeriesDto>, | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @Serializable | @Serializable | ||||||
| data class ComicsDto( | class TopSeriesResponseDto( | ||||||
|     val response: List<SeriesDto>, |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| @Serializable |  | ||||||
| data class TopSeriesResponseDto( |  | ||||||
|     @SerialName("mensual") val topMonthly: List<List<PayloadSeriesDto>>, |     @SerialName("mensual") val topMonthly: List<List<PayloadSeriesDto>>, | ||||||
|     @SerialName("semanal") val topWeekly: List<List<PayloadSeriesDto>>, |     @SerialName("semanal") val topWeekly: List<List<PayloadSeriesDto>>, | ||||||
|     @SerialName("diario") val topDaily: List<List<PayloadSeriesDto>>, |     @SerialName("diario") val topDaily: List<List<PayloadSeriesDto>>, | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @Serializable | @Serializable | ||||||
| data class PayloadSeriesDto( | class PayloadSeriesDto( | ||||||
|     @SerialName("project") val data: SeriesDto, |     @SerialName("project") val data: SeriesDto, | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @Serializable | @Serializable | ||||||
| data class SeriesDto( | class SeriesDto( | ||||||
|     val name: String, |     val name: String, | ||||||
|  |     val alternativeName: String? = null, | ||||||
|     val slug: String, |     val slug: String, | ||||||
|     @SerialName("sinopsis") val synopsis: String? = null, |     @SerialName("sinopsis") private val synopsis: String? = null, | ||||||
|     @SerialName("urlImg") val thumbnail: String? = null, |     @SerialName("urlImg") private val thumbnail: String? = null, | ||||||
|     val isVisible: Boolean, |  | ||||||
|     @SerialName("actualizacionCap") val lastChapterDate: String? = null, |     @SerialName("actualizacionCap") val lastChapterDate: String? = null, | ||||||
|     @SerialName("created_at") val createdAt: String? = null, |     @SerialName("created_at") val createdAt: String? = null, | ||||||
|     @SerialName("state_id") val status: Int? = 0, |     @SerialName("state_id") val status: Int? = 0, | ||||||
|     val genders: List<SeriesGenderDto> = emptyList(), |     private val genders: List<GenderDto> = emptyList(), | ||||||
|     @SerialName("lastChapters") val chapters: List<SeriesChapterDto> = emptyList(), |     @SerialName("lastChapters") val chapters: List<ChapterDto> = emptyList(), | ||||||
|     val trending: SeriesTrendingDto? = null, |     val trending: TrendingDto? = null, | ||||||
|     @SerialName("autors") val authors: List<SeriesAuthorDto> = emptyList(), |     @SerialName("autors") private val authors: List<AuthorDto> = emptyList(), | ||||||
|     val artists: List<SeriesArtistDto> = emptyList(), |     private val artists: List<ArtistDto> = emptyList(), | ||||||
| 
 | 
 | ||||||
| ) { | ) { | ||||||
|     fun toSimpleSManga(): SManga { |     fun toSManga(): SManga { | ||||||
|         return SManga.create().apply { |         return SManga.create().apply { | ||||||
|             title = name |             title = name | ||||||
|             thumbnail_url = thumbnail |             thumbnail_url = thumbnail | ||||||
|             url = "/ver/$slug" |             url = "/ver/$slug" | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     fun toSMangaDetails(): SManga { | ||||||
|  |         return SManga.create().apply { | ||||||
|  |             title = name | ||||||
|  |             thumbnail_url = thumbnail | ||||||
|  |             description = synopsis | ||||||
|  |             if (!alternativeName.isNullOrBlank()) { | ||||||
|  |                 if (!description.isNullOrBlank()) description += "\n\n" | ||||||
|  |                 description += "Nombres alternativos: $alternativeName" | ||||||
|  |             } | ||||||
|  |             genre = genders.joinToString { it.gender.name } | ||||||
|  |             author = authors.joinToString { it.author.name } | ||||||
|  |             artist = artists.joinToString { it.artist.name } | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @Serializable | @Serializable | ||||||
| data class SeriesTrendingDto( | class TrendingDto( | ||||||
|     @SerialName("visitas") val views: Int? = 0, |     @SerialName("visitas") val views: Int? = 0, | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @Serializable | @Serializable | ||||||
| data class SeriesGenderDto( | class GenderDto( | ||||||
|     val gender: SeriesDetailDataNameDto, |     val gender: DetailDataNameDto, | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @Serializable | @Serializable | ||||||
| data class SeriesAuthorDto( | class AuthorDto( | ||||||
|     @SerialName("autor") val author: SeriesDetailDataNameDto, |     @SerialName("autor") val author: DetailDataNameDto, | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @Serializable | @Serializable | ||||||
| data class SeriesArtistDto( | class ArtistDto( | ||||||
|     val artist: SeriesDetailDataNameDto, |     val artist: DetailDataNameDto, | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @Serializable | @Serializable | ||||||
| data class SeriesDetailDataNameDto( | class DetailDataNameDto( | ||||||
|     val name: String, |     val name: String, | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @Serializable | @Serializable | ||||||
| data class SeriesChapterDto( | class ChapterDto( | ||||||
|     @SerialName("num") val number: Float, |     @SerialName("num") private val number: Float, | ||||||
|     val name: String? = null, |     private val name: String? = null, | ||||||
|     val slug: String, |     private val slug: String, | ||||||
|     @SerialName("created_at") val date: String, |     @SerialName("created_at") private val date: String, | ||||||
| ) | ) { | ||||||
|  |     fun toSChapter(seriesSlug: String, dateFormat: SimpleDateFormat): SChapter { | ||||||
|  |         return SChapter.create().apply { | ||||||
|  |             name = "Capítulo ${number.toString().removeSuffix(".0")}" | ||||||
|  |             if (!this@ChapterDto.name.isNullOrBlank()) { | ||||||
|  |                 name += " - ${this@ChapterDto.name}" | ||||||
|  |             } | ||||||
|  |             date_upload = try { | ||||||
|  |                 dateFormat.parse(date)?.time ?: 0L | ||||||
|  |             } catch (e: Exception) { | ||||||
|  |                 0L | ||||||
|  |             } | ||||||
|  |             url = "/ver/$seriesSlug/$slug" | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 bapeey
						bapeey