parent
d73a90d970
commit
026666bc38
@ -1,7 +1,7 @@
|
||||
ext {
|
||||
extName = 'Argos Scan'
|
||||
extClass = '.ArgosScan'
|
||||
extVersionCode = 24
|
||||
extVersionCode = 25
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
@ -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<List<MangaDto>>()
|
||||
.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<SChapter> {
|
||||
return super.chapterListParse(response).sortedByDescending(SChapter::chapter_number)
|
||||
setUrlWithoutDomain(element.selectFirst("a")!!.absUrl("href"))
|
||||
}
|
||||
|
||||
// ============================ Pages =======================================
|
||||
|
||||
override fun pageListParse(document: Document): List<Page> {
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
@ -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<T>(
|
||||
val data: Map<String, T>? = 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<ArgosProjectDto> = emptyList(),
|
||||
val totalPages: Int = 0,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ArgosProjectDto(
|
||||
val adult: Boolean? = false,
|
||||
val alternative: List<String>? = emptyList(),
|
||||
val authors: List<String>? = emptyList(),
|
||||
val cover: String? = "",
|
||||
@SerialName("getChapters") val chapters: List<ArgosChapterDto> = emptyList(),
|
||||
val description: String? = "",
|
||||
val id: Int = 0,
|
||||
val name: String? = "",
|
||||
@SerialName("getTags") val tags: List<ArgosTagDto>? = emptyList(),
|
||||
val type: String? = "",
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ArgosChapterDto(
|
||||
val createAt: String? = "",
|
||||
val id: String = "",
|
||||
val images: List<String>? = emptyList(),
|
||||
val number: Int? = 0,
|
||||
val project: ArgosProjectDto? = null,
|
||||
val title: String? = "",
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ArgosTagDto(
|
||||
val name: String,
|
||||
class DetailsDto(
|
||||
val title: Map<String, String>,
|
||||
val description: Map<String, String> = emptyMap(),
|
||||
val status: String,
|
||||
@SerialName("tags")
|
||||
val genres: List<String> = emptyList(),
|
||||
)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user