From 026666bc38e2b305aaaf70340a620f2cfa3d5163 Mon Sep 17 00:00:00 2001 From: Chopper <156493704+choppeh@users.noreply.github.com> Date: Sun, 8 Jun 2025 23:12:42 -0300 Subject: [PATCH] ArgosScan: Fixes (#9135) * Fix * Use relative manga url --- src/pt/argosscan/build.gradle | 2 +- .../extension/pt/argosscan/ArgosScan.kt | 68 +++--- .../extension/pt/argosscan/ArgosScanDto.kt | 71 +++---- .../pt/argosscan/ArgosScanQueries.kt | 199 ------------------ 4 files changed, 68 insertions(+), 272 deletions(-) delete mode 100644 src/pt/argosscan/src/eu/kanade/tachiyomi/extension/pt/argosscan/ArgosScanQueries.kt diff --git a/src/pt/argosscan/build.gradle b/src/pt/argosscan/build.gradle index c88bac50f..b3ae17943 100644 --- a/src/pt/argosscan/build.gradle +++ b/src/pt/argosscan/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'Argos Scan' extClass = '.ArgosScan' - extVersionCode = 24 + extVersionCode = 25 } apply from: "$rootDir/common.gradle" diff --git a/src/pt/argosscan/src/eu/kanade/tachiyomi/extension/pt/argosscan/ArgosScan.kt b/src/pt/argosscan/src/eu/kanade/tachiyomi/extension/pt/argosscan/ArgosScan.kt index c65a6a5de..69bff8441 100644 --- a/src/pt/argosscan/src/eu/kanade/tachiyomi/extension/pt/argosscan/ArgosScan.kt +++ b/src/pt/argosscan/src/eu/kanade/tachiyomi/extension/pt/argosscan/ArgosScan.kt @@ -2,10 +2,14 @@ package eu.kanade.tachiyomi.extension.pt.argosscan import eu.kanade.tachiyomi.network.GET 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.ParsedHttpSource +import eu.kanade.tachiyomi.util.asJsoup +import keiyoushi.utils.parseAs +import keiyoushi.utils.tryParse import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.OkHttpClient import okhttp3.Request @@ -29,7 +33,7 @@ class ArgosScan : ParsedHttpSource() { override val client: OkHttpClient = network.cloudflareClient.newBuilder() .addInterceptor { chain -> val response = chain.proceed(chain.request()) - if (response.request.url.pathSegments.any { it.equals("pagina-de-login", true) }) { + if (response.request.url.pathSegments.any { it.equals("login", true) }) { throw IOException("Faça login na WebView") } @@ -43,18 +47,22 @@ class ArgosScan : ParsedHttpSource() { // ============================ Popular ====================================== override fun popularMangaRequest(page: Int) = GET(baseUrl, headers) - override fun popularMangaSelector() = ".card__main._grid:not(:has(a[href*=novel]))" - - override fun popularMangaFromElement(element: Element) = SManga.create().apply { - with(element.selectFirst("h3.card__title")!!) { - title = text() - setUrlWithoutDomain(selectFirst("a")!!.absUrl("href")) - } - thumbnail_url = element.selectFirst("img")?.absUrl("src") - } - + override fun popularMangaSelector() = throw UnsupportedOperationException() + override fun popularMangaFromElement(element: Element) = throw UnsupportedOperationException() override fun popularMangaNextPageSelector() = null + override fun popularMangaParse(response: Response): MangasPage { + val script = response.asJsoup().selectFirst("script:containsData(projects)")!!.data() + + val mangas = POPULAR_REGEX.find(script)?.groups?.get(1)?.value?.let { + it.parseAs>() + .filter { it.type != "novel" } + .map { it.toSManga(baseUrl) } + } ?: throw IOException("Não foi possivel encontrar os mangás") + + return MangasPage(mangas, false) + } + // ============================ Latest ====================================== override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException() @@ -83,40 +91,34 @@ class ArgosScan : ParsedHttpSource() { // ============================ Details ===================================== override fun mangaDetailsParse(document: Document) = SManga.create().apply { - title = document.selectFirst("h1")!!.text() - thumbnail_url = document.selectFirst("img.story__thumbnail-image")?.absUrl("src") - description = document.selectFirst(".story__summary p")?.text() - document.selectFirst(".story__status")?.let { - status = when (it.text().trim().lowercase()) { - "em andamento" -> SManga.ONGOING - else -> SManga.UNKNOWN + with(document) { + title = selectFirst(".content h2")!!.text() + thumbnail_url = selectFirst(".trailer-box img")?.absUrl("src") + description = selectFirst(".content p")?.text() + selectFirst("section[data-status]")?.attr("data-status")?.let { + status = it.toStatus() } + genre = select("h6:contains(Tags) + h6 > span").joinToString { it.text() } } setUrlWithoutDomain(document.location()) } // ============================ Chapter ===================================== - override fun chapterListSelector() = ".chapter-group__list li:has(a)" + override fun chapterListSelector() = ".manga-chapter" override fun chapterFromElement(element: Element) = SChapter.create().apply { - with(element.selectFirst("a")!!) { - name = text() - setUrlWithoutDomain(absUrl("href")) + name = element.selectFirst("h5")!!.text() + element.selectFirst("h6")?.let { + date_upload = dateFormat.tryParse(it.text()) } - element.selectFirst(".chapter-group__list-item-date")?.attr("datetime")?.let { - date_upload = it.parseDate() - } - } - - override fun chapterListParse(response: Response): List { - return super.chapterListParse(response).sortedByDescending(SChapter::chapter_number) + setUrlWithoutDomain(element.selectFirst("a")!!.absUrl("href")) } // ============================ Pages ======================================= override fun pageListParse(document: Document): List { - return document.select("#chapter-content img").mapIndexed { index, element -> + return document.select(".manga-page img").mapIndexed { index, element -> Page(index, imageUrl = element.absUrl("src")) } } @@ -125,10 +127,8 @@ class ArgosScan : ParsedHttpSource() { // ============================== Utilities ================================== - private fun String.parseDate(): Long { - return try { dateFormat.parse(this.trim())!!.time } catch (_: Exception) { 0L } - } companion object { - val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.ROOT) + val dateFormat = SimpleDateFormat("dd/MM/yyyy", Locale.ROOT) + val POPULAR_REGEX = """projects\s?=\s+([^;]+)""".toRegex() } } diff --git a/src/pt/argosscan/src/eu/kanade/tachiyomi/extension/pt/argosscan/ArgosScanDto.kt b/src/pt/argosscan/src/eu/kanade/tachiyomi/extension/pt/argosscan/ArgosScanDto.kt index 1daaa68ef..8af9d711f 100644 --- a/src/pt/argosscan/src/eu/kanade/tachiyomi/extension/pt/argosscan/ArgosScanDto.kt +++ b/src/pt/argosscan/src/eu/kanade/tachiyomi/extension/pt/argosscan/ArgosScanDto.kt @@ -1,47 +1,42 @@ package eu.kanade.tachiyomi.extension.pt.argosscan +import eu.kanade.tachiyomi.source.model.SManga import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable -data class ArgosResponseDto( - val data: Map? = null, -) +class MangaDto( + @SerialName("attributes") + val details: DetailsDto, + @SerialName("cover_image_url") + val thumbnailUrl: String, + val id: String, + val type: String, +) { + fun toSManga(baseUrl: String) = SManga.create().apply { + title = details.title.values.first() + description = details.description.values.first() + genre = details.genres.joinToString() + thumbnail_url = "$baseUrl/$thumbnailUrl" + status = details.status.toStatus() + url = "/projetos/${this@MangaDto.id}" + initialized = true + } +} + +fun String.toStatus(): Int = + when (lowercase()) { + "em-lancamento" -> SManga.ONGOING + "completa" -> SManga.COMPLETED + "em-pausa" -> SManga.ON_HIATUS + else -> SManga.UNKNOWN + } @Serializable -data class ArgosProjectListDto( - val count: Int = 0, - val currentPage: Int = 0, - val limit: Int = 0, - val projects: List = emptyList(), - val totalPages: Int = 0, -) - -@Serializable -data class ArgosProjectDto( - val adult: Boolean? = false, - val alternative: List? = emptyList(), - val authors: List? = emptyList(), - val cover: String? = "", - @SerialName("getChapters") val chapters: List = emptyList(), - val description: String? = "", - val id: Int = 0, - val name: String? = "", - @SerialName("getTags") val tags: List? = emptyList(), - val type: String? = "", -) - -@Serializable -data class ArgosChapterDto( - val createAt: String? = "", - val id: String = "", - val images: List? = emptyList(), - val number: Int? = 0, - val project: ArgosProjectDto? = null, - val title: String? = "", -) - -@Serializable -data class ArgosTagDto( - val name: String, +class DetailsDto( + val title: Map, + val description: Map = emptyMap(), + val status: String, + @SerialName("tags") + val genres: List = emptyList(), ) diff --git a/src/pt/argosscan/src/eu/kanade/tachiyomi/extension/pt/argosscan/ArgosScanQueries.kt b/src/pt/argosscan/src/eu/kanade/tachiyomi/extension/pt/argosscan/ArgosScanQueries.kt deleted file mode 100644 index 4bf477632..000000000 --- a/src/pt/argosscan/src/eu/kanade/tachiyomi/extension/pt/argosscan/ArgosScanQueries.kt +++ /dev/null @@ -1,199 +0,0 @@ -package eu.kanade.tachiyomi.extension.pt.argosscan - -import kotlinx.serialization.json.add -import kotlinx.serialization.json.addJsonObject -import kotlinx.serialization.json.buildJsonObject -import kotlinx.serialization.json.put -import kotlinx.serialization.json.putJsonArray -import kotlinx.serialization.json.putJsonObject - -private fun buildQuery(queryAction: () -> String) = queryAction().replace("%", "$") - -val LOGIN_MUTATION_QUERY = buildQuery { - """ - | mutation login(%email: String!, %password: String!) { - | login(loginInput: { email: %email, password: %password }) { - | token - | } - | } - """.trimMargin() -} - -fun buildLoginMutationQueryPayload(email: String, password: String) = buildJsonObject { - put("operationName", "login") - put("query", LOGIN_MUTATION_QUERY) - putJsonObject("variables") { - put("email", email) - put("password", password) - } -} - -val POPULAR_QUERY = buildQuery { - """ - | query getProjects( - | %filters: FiltersExpression!, - | %orders: OrdersExpression!, - | %pagination: PaginationInput - | ) { - | getProjects( - | orders: %orders, - | filters: %filters, - | pagination: %pagination - | ) { - | projects { - | id - | name - | cover - | type - | updateAt - | getChapters(order: { id: DESC }, skip: 0, take: 1) { - | id - | title - | number - | } - | } - | count - | currentPage - | limit - | totalPages - | } - | } - """.trimMargin() -} - -fun buildPopularQueryPayload(page: Int) = buildJsonObject { - put("operationName", "getProjects") - put("query", POPULAR_QUERY) - putJsonObject("variables") { - putJsonObject("filters") { - putJsonObject("childExpressions") { - putJsonObject("filters") { - put("field", "Project.id") - put("op", "GE") - putJsonArray("values") { - add("1") - } - } - put("operator", "AND") - } - put("operator", "AND") - } - putJsonObject("orders") { - putJsonArray("orders") { - addJsonObject { - put("field", "Project.views") - put("or", "DESC") - } - } - } - putJsonObject("pagination") { - put("limit", 12) - put("page", page) - } - } -} - -fun buildSearchQueryPayload(query: String, page: Int) = buildJsonObject { - put("operationName", "getProjects") - put("query", POPULAR_QUERY) - putJsonObject("variables") { - putJsonObject("filters") { - putJsonArray("filters") { - addJsonObject { - put("field", "Project.name") - put("op", "LIKE") - putJsonArray("values") { - add(query) - } - } - } - put("operator", "AND") - } - putJsonObject("orders") { - putJsonArray("orders") { - addJsonObject { - put("field", "Project.views") - put("or", "DESC") - } - } - } - putJsonObject("pagination") { - put("limit", 10) - put("page", page) - } - } -} - -val MANGA_DETAILS_QUERY = buildQuery { - """ - | query project(%id: Int!) { - | project(id: %id) { - | id - | name - | type - | description - | authors - | cover - | getChapters(order: { number: DESC }) { - | id - | number - | title - | createAt - | } - | getTags(order: { id: ASC }) { - | id - | name - | } - | } - | } - """.trimMargin() -} - -fun buildMangaDetailsQueryPayload(id: Int) = buildJsonObject { - put("operationName", "project") - put("query", MANGA_DETAILS_QUERY) - putJsonObject("variables") { - put("id", id) - } -} - -val PAGES_QUERY = buildQuery { - """ - | query getChapter(%id: String!) { - | getChapters( - | orders: { - | orders: { or: ASC, field: "Chapter.id" } - | } - | filters: { - | operator: AND, - | filters: [ - | { op: EQ, field: "Chapter.id", values: [%id] } - | ], - | childExpressions: { - | operator: AND, - | filters: { - | op: GE, - | field: "Project.id", - | relationField: "Chapter.project", - | values: ["1"] - | } - | } - | } - | ) { - | chapters { - | id - | images - | project { id } - | } - | } - | } - """.trimMargin() -} - -fun buildPagesQueryPayload(id: String) = buildJsonObject { - put("operationName", "getChapter") - put("query", PAGES_QUERY) - putJsonObject("variables") { - put("id", id) - } -}