Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/pt/remangas/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ plugins {

keiyoushi {
name = "NoxManga"
versionCode = 53
contentWarning = ContentWarning.SAFE
libVersion = "1.4"
versionCode = 54
contentWarning = ContentWarning.MIXED
libVersion = "1.6"

source {
lang = "pt-BR"
baseUrl = "https://noxtoons.com"
baseUrl = "https://noxmangas.org"
id = 7462657023971681136
}
}
126 changes: 103 additions & 23 deletions src/pt/remangas/src/eu/kanade/tachiyomi/extension/pt/remangas/Dto.kt
Original file line number Diff line number Diff line change
@@ -1,53 +1,133 @@
package eu.kanade.tachiyomi.extension.pt.remangas

import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import keiyoushi.utils.tryParse
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonNames
import java.text.SimpleDateFormat
import java.util.Locale
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
import kotlin.time.Instant

@Serializable
class PageableDto<T>(
@JsonNames("chapters", "comics")
val list: List<T>,
private val page: Long,
@SerialName("total_pages")
private val totalPages: Long = 0,
class MangaListDto(
val comics: List<MangaDto> = emptyList(),
private val page: Int = 1,
@SerialName("total_pages") private val totalPages: Int = 1,
) {
fun hasNextPage() = page < totalPages
val hasNextPage get() = page < totalPages
}

@Serializable
class MangaDto(
val slug: String,
val title: String,
val cover: String? = null,
private val title: String,
@SerialName("title_alt") private val alternativeTitles: List<String>? = null,
private val synopsis: String? = null,
private val cover: String? = null,
private val type: String? = null,
private val status: String? = null,
private val genres: List<GenreDto> = emptyList(),
) {
fun toSManga() = SManga.create().apply {
url = "/manga/$slug"
title = this@MangaDto.title
thumbnail_url = cover
url = "/manga/$slug"
genre = (listOfNotNull(type?.replaceFirstChar(Char::uppercase)) + genres.map(GenreDto::name)).joinToString()
status = when (this@MangaDto.status) {
"ongoing" -> SManga.ONGOING
"completed" -> SManga.COMPLETED
"hiatus" -> SManga.ON_HIATUS
"cancelled" -> SManga.CANCELLED
else -> SManga.UNKNOWN
}
description = buildString {
synopsis?.takeIf(String::isNotBlank)?.let(::appendLine)
alternativeTitles?.filter(String::isNotBlank)?.takeIf(List<String>::isNotEmpty)?.let {
appendLine()
append("Títulos alternativos: ", it.joinToString())
}
}.trim()
}
}

@Serializable
class GenreDto(
val name: String,
val slug: String = "",
)

@Serializable
class GenreListDto(
val data: List<GenreDto> = emptyList(),
)

@Serializable
class ChapterUpdateListDto(
private val data: List<ChapterUpdateDto> = emptyList(),
private val page: Int = 1,
@SerialName("total_pages") private val totalPages: Int = 1,
) {
val mangas get() = data.distinctBy(ChapterUpdateDto::comicSlug).map(ChapterUpdateDto::toSManga)
val hasNextPage get() = page < totalPages
}

@Serializable
class ChapterUpdateDto(
@SerialName("comic_slug") val comicSlug: String,
@SerialName("comic_title") private val comicTitle: String,
@SerialName("comic_cover") private val comicCover: String? = null,
) {
fun toSManga() = SManga.create().apply {
url = "/manga/$comicSlug"
title = comicTitle
thumbnail_url = comicCover
}
}

@Serializable
class ChapterListDto(
val chapters: List<ChapterDto> = emptyList(),
)

@Serializable
class ChapterDto(
val number: Float,
val slug: String,
@SerialName("created_at")
val createdAt: String,
private val id: String,
private val number: Float,
private val slug: String,
private val title: String? = null,
@SerialName("published_at") private val publishedAt: String? = null,
) {
fun toSChapter(mangaSlug: String) = SChapter.create().apply {
name = "Capítulo ${number.toString().replace(".0", "")}"
url = id
name = buildString {
append("Capítulo ", number.formatted())
title?.trim()
?.takeIf { it.isNotEmpty() && it != number.formatted() && !it.startsWith("Capítulo", ignoreCase = true) }
?.let { append(" - ", it) }
}
chapter_number = number
url = "/ler/$mangaSlug/$slug"
date_upload = dateFormat.tryParse(createdAt)
date_upload = Instant.tryParse(publishedAt)
memo = buildJsonObject {
put("mangaSlug", mangaSlug)
put("slug", slug)
}
}

companion object {
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ROOT)
}
private fun Float.formatted(): String = toString().removeSuffix(".0")
}

@Serializable
class ChapterPagesDto(
private val pages: List<PageDto> = emptyList(),
) {
fun toPageList() = pages.sortedBy(PageDto::number)
.mapIndexed { index, page -> Page(index, imageUrl = page.imageUrl) }
}

@Serializable
class PageDto(
val number: Int = 0,
@SerialName("image_url") val imageUrl: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package eu.kanade.tachiyomi.extension.pt.remangas

import eu.kanade.tachiyomi.source.model.Filter
import okhttp3.HttpUrl

interface UrlFilter {
fun addToUrl(builder: HttpUrl.Builder)
}

open class SelectFilter(
name: String,
private val parameter: String,
private val options: List<Pair<String, String>>,
) : Filter.Select<String>(name, options.map { it.first }.toTypedArray()),
UrlFilter {
val selectedValue get() = options[state].second

override fun addToUrl(builder: HttpUrl.Builder) {
selectedValue.takeIf(String::isNotEmpty)?.let { builder.addQueryParameter(parameter, it) }
}
}

class SortFilter :
SelectFilter(
"Ordenar por",
"sort",
listOf(
"Populares" to "popular",
"Atualizados recentemente" to "latest",
"Adicionados recentemente" to "newest",
"Melhor avaliados" to "rating",
"Mais seguidos" to "followers",
"Mais vistos" to "views",
),
)

class TypeFilter :
SelectFilter(
"Tipo",
"type",
listOf(
"Todos" to "",
"Mangá" to "manga",
"Manhwa" to "manhwa",
"Manhua" to "manhua",
"Webtoon" to "webtoon",
"Pornhwa" to "pornhwa",
"Novel" to "novel",
),
)

class StatusFilter :
SelectFilter(
"Status",
"status",
listOf(
"Todos" to "",
"Em andamento" to "ongoing",
"Completo" to "completed",
"Hiato" to "hiatus",
"Cancelado" to "cancelled",
),
)

class DemographicFilter :
SelectFilter(
"Demografia",
"demographic",
listOf(
"Todas" to "",
"Shounen" to "shounen",
"Seinen" to "seinen",
"Shoujo" to "shoujo",
"Josei" to "josei",
),
)

class ContentFilter :
SelectFilter(
"Conteúdo",
"adult",
listOf(
"Todos" to "",
"Sem conteúdo adulto" to "false",
"Apenas conteúdo adulto" to "true",
),
)

class GenreFilter(genres: List<GenreDto>) :
SelectFilter(
"Gênero",
"genre",
listOf("Todos" to "") + genres.map { it.name to it.slug },
)
Loading