From 927507b7ac63f3144d4688389623f30472bbdec4 Mon Sep 17 00:00:00 2001 From: kanoou <90949336+kanoou@users.noreply.github.com> Date: Sun, 20 Jul 2025 13:23:13 -0500 Subject: [PATCH] Add LectorMOnline and MangasX (#9665) * add lectormonline * add webview methods * review * move to factory * wut * move to multisrc * move iconcs to multisrc --- lib-multisrc/lectormonline/build.gradle.kts | 5 + .../res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2813 bytes .../res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1602 bytes .../res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 3750 bytes .../res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6560 bytes .../res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9260 bytes .../multisrc/lectormonline/LectorMOnline.kt | 193 ++++++++++++++++++ .../lectormonline/LectorMOnlineDto.kt | 93 +++++++++ .../lectormonline/LectorMOnlineFilters.kt | 29 +++ src/es/lectormonline/build.gradle | 10 + .../es/lectormonline/LectorMOnline.kt | 15 ++ src/es/mangasx/build.gradle | 10 + .../tachiyomi/extension/es/mangasx/MangasX.kt | 15 ++ 13 files changed, 370 insertions(+) create mode 100644 lib-multisrc/lectormonline/build.gradle.kts create mode 100644 lib-multisrc/lectormonline/res/mipmap-hdpi/ic_launcher.png create mode 100644 lib-multisrc/lectormonline/res/mipmap-mdpi/ic_launcher.png create mode 100644 lib-multisrc/lectormonline/res/mipmap-xhdpi/ic_launcher.png create mode 100644 lib-multisrc/lectormonline/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 lib-multisrc/lectormonline/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 lib-multisrc/lectormonline/src/eu/kanade/tachiyomi/multisrc/lectormonline/LectorMOnline.kt create mode 100644 lib-multisrc/lectormonline/src/eu/kanade/tachiyomi/multisrc/lectormonline/LectorMOnlineDto.kt create mode 100644 lib-multisrc/lectormonline/src/eu/kanade/tachiyomi/multisrc/lectormonline/LectorMOnlineFilters.kt create mode 100644 src/es/lectormonline/build.gradle create mode 100644 src/es/lectormonline/src/eu/kanade/tachiyomi/extension/es/lectormonline/LectorMOnline.kt create mode 100644 src/es/mangasx/build.gradle create mode 100644 src/es/mangasx/src/eu/kanade/tachiyomi/extension/es/mangasx/MangasX.kt diff --git a/lib-multisrc/lectormonline/build.gradle.kts b/lib-multisrc/lectormonline/build.gradle.kts new file mode 100644 index 000000000..dc076cc37 --- /dev/null +++ b/lib-multisrc/lectormonline/build.gradle.kts @@ -0,0 +1,5 @@ +plugins { + id("lib-multisrc") +} + +baseVersionCode = 1 diff --git a/lib-multisrc/lectormonline/res/mipmap-hdpi/ic_launcher.png b/lib-multisrc/lectormonline/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..e6f06f5c48af080a61c495cbf5ae994680efcc7f GIT binary patch literal 2813 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 P00000NkvXXu0mjfSim=i literal 0 HcmV?d00001 diff --git a/lib-multisrc/lectormonline/res/mipmap-mdpi/ic_launcher.png b/lib-multisrc/lectormonline/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..7904a7316c47190090730765d5168b38dcc40310 GIT binary patch literal 1602 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 literal 0 HcmV?d00001 diff --git a/lib-multisrc/lectormonline/res/mipmap-xxxhdpi/ic_launcher.png b/lib-multisrc/lectormonline/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..1aa42722664df569daf80051466d1d90fbb2d913 GIT binary patch literal 9260 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 + when (filter) { + is SortByFilter -> { + if (filter.selected == "views") { + url.addQueryParameter("sort", "views") + } + if (filter.state!!.ascending) { + url.addQueryParameter("isDesc", "false") + } + } + is GenreFilter -> { + val selectedGenre = filter.toUriPart() + if (selectedGenre.isNotEmpty()) { + return GET("$baseUrl/genres/$selectedGenre?page=$page", headers) + } + } + else -> { } + } + } + + return GET(url.build(), headers) + } + + override fun searchMangaParse(response: Response): MangasPage { + val document = response.asJsoup() + if (response.request.url.pathSegments[0] == "genres") { + return searchMangaGenreParse(document) + } + val script = document.select("script:containsData(self.__next_f.push)").joinToString { it.data() } + val jsonData = COMICS_LIST_REGEX.find(script)?.groupValues?.get(1)?.unescape() + ?: throw Exception("No se pudo encontrar la lista de cómics") + val data = jsonData.parseAs() + return MangasPage(data.comics.map { it.toSManga() }, data.hasNextPage()) + } + + private fun searchMangaGenreParse(document: Document): MangasPage { + val mangas = document.select("div.grid.relative > a.group.relative").map { element -> + SManga.create().apply { + setUrlWithoutDomain(element.attr("href").substringAfter("/comics/").substringBefore("?")) + title = element.selectFirst("h3")!!.text() + thumbnail_url = element.selectFirst("img")?.attr("abs:src") + } + } + val hasNextPage = document.selectFirst("div.flex.items-center > a:has(> svg):last-child:not(.pointer-events-none)") != null + return MangasPage(mangas, hasNextPage) + } + + override fun getMangaUrl(manga: SManga) = "$baseUrl/comics/${manga.url}" + + override fun mangaDetailsRequest(manga: SManga): Request { + return GET("$baseUrl/api/app/comic/${manga.url}", headers) + } + + override fun mangaDetailsParse(response: Response): SManga { + return response.parseAs().toSMangaDetails() + } + + override fun getChapterUrl(chapter: SChapter): String { + val mangaSlug = chapter.url.substringBefore("/") + val chapterNumber = chapter.url.substringAfter("/") + return "$baseUrl/comics/$mangaSlug/chapters/$chapterNumber" + } + + override fun chapterListRequest(manga: SManga) = mangaDetailsRequest(manga) + + override fun chapterListParse(response: Response): List { + return response.parseAs().getChapters() + } + + override fun pageListRequest(chapter: SChapter): Request { + val mangaSlug = chapter.url.substringBefore("/") + val chapterNumber = chapter.url.substringAfter("/") + return GET("$baseUrl/api/app/comic/$mangaSlug/chapter/$chapterNumber", headers) + } + + override fun pageListParse(response: Response): List { + val data = response.parseAs() + return data.chapter.urlImagesChapter.mapIndexed { index, image -> + Page(index, imageUrl = image) + } + } + + private var genresList: List> = emptyList() + private var fetchFiltersAttempts = 0 + private var filtersState = FiltersState.NOT_FETCHED + + private fun fetchFilters() { + if (filtersState != FiltersState.NOT_FETCHED || fetchFiltersAttempts >= 3) return + filtersState = FiltersState.FETCHING + fetchFiltersAttempts++ + thread { + try { + val response = client.newCall(GET("$baseUrl/api/app/genres", headers)).execute() + val filters = response.parseAs() + + genresList = filters.genres.map { genre -> genre.name.lowercase().replaceFirstChar { it.uppercase() } to genre.name } + + filtersState = FiltersState.FETCHED + } catch (_: Throwable) { + filtersState = FiltersState.NOT_FETCHED + } + } + } + + override fun getFilterList(): FilterList { + fetchFilters() + + val filters = mutableListOf>( + Filter.Header("El filtro por género no funciona con los demas filtros"), + Filter.Separator(), + SortByFilter( + "Ordenar por", + listOf( + SortProperty("Más vistos", "views"), + SortProperty("Más recientes", "created_at"), + ), + 1, + ), + ) + + filters += if (filtersState == FiltersState.FETCHED) { + listOf( + Filter.Separator(), + Filter.Header("Filtrar por género"), + GenreFilter(genresList), + ) + } else { + listOf( + Filter.Separator(), + Filter.Header("Presione 'Reiniciar' para intentar cargar los filtros"), + ) + } + + return FilterList(filters) + } + + private enum class FiltersState { NOT_FETCHED, FETCHING, FETCHED } + + override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException() + + private fun String.unescape(): String { + return UNESCAPE_REGEX.replace(this, "$1") + } + + companion object { + private val UNESCAPE_REGEX = """\\(.)""".toRegex() + private val COMICS_LIST_REGEX = """\\"comicsData\\":(\{.*?\}),\\"searchParams""".toRegex() + } +} diff --git a/lib-multisrc/lectormonline/src/eu/kanade/tachiyomi/multisrc/lectormonline/LectorMOnlineDto.kt b/lib-multisrc/lectormonline/src/eu/kanade/tachiyomi/multisrc/lectormonline/LectorMOnlineDto.kt new file mode 100644 index 000000000..16f8c0802 --- /dev/null +++ b/lib-multisrc/lectormonline/src/eu/kanade/tachiyomi/multisrc/lectormonline/LectorMOnlineDto.kt @@ -0,0 +1,93 @@ +package eu.kanade.tachiyomi.multisrc.lectormonline + +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.source.model.SManga +import keiyoushi.utils.tryParse +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonPrimitive +import java.text.SimpleDateFormat +import java.util.Locale +import java.util.TimeZone + +@Serializable +class ComicListDataDto( + val comics: List, + private val page: Int, + private val totalPages: Int, +) { + fun hasNextPage() = page < totalPages +} + +@Serializable +class ComicDto( + private val slug: String, + private val name: String, + private val state: String?, + private val urlCover: String, + private val description: String?, + private val author: String?, + private val chapters: List = emptyList(), +) { + fun toSManga() = SManga.create().apply { + url = slug + title = name.substringBeforeLast("-").trim() + thumbnail_url = urlCover + status = state.parseStatus() + } + + fun toSMangaDetails() = SManga.create().apply { + url = slug + title = name.substringBeforeLast("-").trim() + thumbnail_url = urlCover + description = this@ComicDto.description + status = state.parseStatus() + author = this@ComicDto.author + } + + fun getChapters(): List { + return chapters.map { it.toSChapter(slug) } + } + + private fun String?.parseStatus(): Int { + return when (this?.lowercase()) { + "ongoing" -> SManga.ONGOING + else -> SManga.UNKNOWN + } + } +} + +val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ROOT).apply { + timeZone = TimeZone.getTimeZone("UTC") +} + +@Serializable +class ChapterDto( + private val number: JsonPrimitive, + private val createdAt: String, +) { + fun toSChapter(mangaSlug: String) = SChapter.create().apply { + url = "$mangaSlug/$number" + name = "Capítulo $number" + date_upload = dateFormat.tryParse(createdAt) + } +} + +@Serializable +class ChapterPagesDataDto( + val chapter: ChapterPagesDto, +) + +@Serializable +class ChapterPagesDto( + val urlImagesChapter: List = emptyList(), +) + +@Serializable +class GenreListDto( + val genres: List, +) + +@Serializable +class GenreDto( + val name: String, +) diff --git a/lib-multisrc/lectormonline/src/eu/kanade/tachiyomi/multisrc/lectormonline/LectorMOnlineFilters.kt b/lib-multisrc/lectormonline/src/eu/kanade/tachiyomi/multisrc/lectormonline/LectorMOnlineFilters.kt new file mode 100644 index 000000000..6f2ac9078 --- /dev/null +++ b/lib-multisrc/lectormonline/src/eu/kanade/tachiyomi/multisrc/lectormonline/LectorMOnlineFilters.kt @@ -0,0 +1,29 @@ +package eu.kanade.tachiyomi.multisrc.lectormonline + +import eu.kanade.tachiyomi.source.model.Filter + +class SortByFilter(title: String, private val sortProperties: List, defaultIndex: Int) : Filter.Sort( + title, + sortProperties.map { it.name }.toTypedArray(), + Selection(defaultIndex, ascending = false), +) { + val selected: String + get() = sortProperties[state!!.index].value +} + +class SortProperty(val name: String, val value: String) { + override fun toString(): String = name +} + +class GenreFilter(genres: List>) : UriPartFilter( + "Género", + arrayOf( + Pair("Todos", ""), + *genres.toTypedArray(), + ), +) + +open class UriPartFilter(displayName: String, private val vals: Array>) : + Filter.Select(displayName, vals.map { it.first }.toTypedArray()) { + fun toUriPart() = vals[state].second +} diff --git a/src/es/lectormonline/build.gradle b/src/es/lectormonline/build.gradle new file mode 100644 index 000000000..def292afe --- /dev/null +++ b/src/es/lectormonline/build.gradle @@ -0,0 +1,10 @@ +ext { + extName = 'Lector MOnline' + extClass = '.LectorMOnline' + themePkg = 'lectormonline' + baseUrl = 'https://www.lectormangas.online' + overrideVersionCode = 0 + isNsfw = false +} + +apply from: "$rootDir/common.gradle" diff --git a/src/es/lectormonline/src/eu/kanade/tachiyomi/extension/es/lectormonline/LectorMOnline.kt b/src/es/lectormonline/src/eu/kanade/tachiyomi/extension/es/lectormonline/LectorMOnline.kt new file mode 100644 index 000000000..97cc596e9 --- /dev/null +++ b/src/es/lectormonline/src/eu/kanade/tachiyomi/extension/es/lectormonline/LectorMOnline.kt @@ -0,0 +1,15 @@ +package eu.kanade.tachiyomi.extension.es.lectormonline + +import eu.kanade.tachiyomi.multisrc.lectormonline.LectorMOnline +import eu.kanade.tachiyomi.network.interceptor.rateLimit +import java.util.concurrent.TimeUnit + +class LectorMOnline : LectorMOnline( + name = "Lector MOnline", + baseUrl = "https://www.lectormangas.online", + lang = "es", +) { + override val client = network.cloudflareClient.newBuilder() + .rateLimit(3, 1, TimeUnit.SECONDS) + .build() +} diff --git a/src/es/mangasx/build.gradle b/src/es/mangasx/build.gradle new file mode 100644 index 000000000..8f96ae2d3 --- /dev/null +++ b/src/es/mangasx/build.gradle @@ -0,0 +1,10 @@ +ext { + extName = 'MangasX' + extClass = '.MangasX' + themePkg = 'lectormonline' + baseUrl = 'https://mangasx.online' + overrideVersionCode = 0 + isNsfw = true +} + +apply from: "$rootDir/common.gradle" diff --git a/src/es/mangasx/src/eu/kanade/tachiyomi/extension/es/mangasx/MangasX.kt b/src/es/mangasx/src/eu/kanade/tachiyomi/extension/es/mangasx/MangasX.kt new file mode 100644 index 000000000..d24e15b83 --- /dev/null +++ b/src/es/mangasx/src/eu/kanade/tachiyomi/extension/es/mangasx/MangasX.kt @@ -0,0 +1,15 @@ +package eu.kanade.tachiyomi.extension.es.mangasx + +import eu.kanade.tachiyomi.multisrc.lectormonline.LectorMOnline +import eu.kanade.tachiyomi.network.interceptor.rateLimit +import java.util.concurrent.TimeUnit + +class MangasX : LectorMOnline( + name = "MangasX", + baseUrl = "https://mangasx.online", + lang = "es", +) { + override val client = network.cloudflareClient.newBuilder() + .rateLimit(3, 1, TimeUnit.SECONDS) + .build() +}