Update SS URL. (#15145)
This commit is contained in:
parent
6a80b09a08
commit
0cd77b194d
|
@ -6,7 +6,7 @@ ext {
|
||||||
extName = 'Saikai Scan'
|
extName = 'Saikai Scan'
|
||||||
pkgNameSuffix = 'pt.saikaiscan'
|
pkgNameSuffix = 'pt.saikaiscan'
|
||||||
extClass = '.SaikaiScan'
|
extClass = '.SaikaiScan'
|
||||||
extVersionCode = 9
|
extVersionCode = 10
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
apply from: "$rootDir/common.gradle"
|
||||||
|
|
|
@ -16,17 +16,14 @@ import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import org.jsoup.Jsoup
|
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.Locale
|
|
||||||
|
|
||||||
class SaikaiScan : HttpSource() {
|
class SaikaiScan : HttpSource() {
|
||||||
|
|
||||||
override val name = "Saikai Scan"
|
override val name = SOURCE_NAME
|
||||||
|
|
||||||
override val baseUrl = "https://saikaiscan.com.br"
|
override val baseUrl = "https://saikai.com.br"
|
||||||
|
|
||||||
override val lang = "pt-BR"
|
override val lang = "pt-BR"
|
||||||
|
|
||||||
|
@ -63,18 +60,12 @@ class SaikaiScan : HttpSource() {
|
||||||
override fun popularMangaParse(response: Response): MangasPage {
|
override fun popularMangaParse(response: Response): MangasPage {
|
||||||
val result = response.parseAs<SaikaiScanPaginatedStoriesDto>()
|
val result = response.parseAs<SaikaiScanPaginatedStoriesDto>()
|
||||||
|
|
||||||
val mangaList = result.data!!.map(::popularMangaFromObject)
|
val mangaList = result.data!!.map(SaikaiScanStoryDto::toSManga)
|
||||||
val hasNextPage = result.meta!!.currentPage < result.meta.lastPage
|
val hasNextPage = result.meta!!.currentPage < result.meta.lastPage
|
||||||
|
|
||||||
return MangasPage(mangaList, hasNextPage)
|
return MangasPage(mangaList, hasNextPage)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun popularMangaFromObject(obj: SaikaiScanStoryDto): SManga = SManga.create().apply {
|
|
||||||
title = obj.title
|
|
||||||
thumbnail_url = "$IMAGE_SERVER_URL/${obj.image}"
|
|
||||||
url = "/comics/${obj.slug}"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int): Request {
|
override fun latestUpdatesRequest(page: Int): Request {
|
||||||
val apiHeaders = headersBuilder()
|
val apiHeaders = headersBuilder()
|
||||||
.add("Accept", ACCEPT_JSON)
|
.add("Accept", ACCEPT_JSON)
|
||||||
|
@ -106,35 +97,8 @@ class SaikaiScan : HttpSource() {
|
||||||
.addQueryParameter("per_page", PER_PAGE)
|
.addQueryParameter("per_page", PER_PAGE)
|
||||||
.addQueryParameter("relationships", "language,type,format")
|
.addQueryParameter("relationships", "language,type,format")
|
||||||
|
|
||||||
filters.forEach { filter ->
|
filters.filterIsInstance<UrlQueryFilter>()
|
||||||
when (filter) {
|
.forEach { it.addQueryParameter(apiEndpointUrl) }
|
||||||
is GenreFilter -> {
|
|
||||||
val genresParameter = filter.state
|
|
||||||
.filter { it.state }
|
|
||||||
.joinToString(",") { it.id.toString() }
|
|
||||||
apiEndpointUrl.addQueryParameter("genres", genresParameter)
|
|
||||||
}
|
|
||||||
|
|
||||||
is CountryFilter -> {
|
|
||||||
if (filter.state > 0) {
|
|
||||||
apiEndpointUrl.addQueryParameter("country", filter.selected.id.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
is StatusFilter -> {
|
|
||||||
if (filter.state > 0) {
|
|
||||||
apiEndpointUrl.addQueryParameter("status", filter.selected.id.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
is SortByFilter -> {
|
|
||||||
val sortProperty = filter.sortProperties[filter.state!!.index]
|
|
||||||
val sortDirection = if (filter.state!!.ascending) "asc" else "desc"
|
|
||||||
apiEndpointUrl.setQueryParameter("sortProperty", sortProperty.slug)
|
|
||||||
apiEndpointUrl.setQueryParameter("sortDirection", sortDirection)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return GET(apiEndpointUrl.toString(), apiHeaders)
|
return GET(apiEndpointUrl.toString(), apiHeaders)
|
||||||
}
|
}
|
||||||
|
@ -167,19 +131,10 @@ class SaikaiScan : HttpSource() {
|
||||||
return GET(apiEndpointUrl, apiHeaders)
|
return GET(apiEndpointUrl, apiHeaders)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mangaDetailsParse(response: Response): SManga = SManga.create().apply {
|
override fun mangaDetailsParse(response: Response): SManga {
|
||||||
val result = response.parseAs<SaikaiScanPaginatedStoriesDto>()
|
val result = response.parseAs<SaikaiScanPaginatedStoriesDto>()
|
||||||
val story = result.data!![0]
|
|
||||||
|
|
||||||
title = story.title
|
return result.data!![0].toSManga()
|
||||||
author = story.authors.joinToString { it.name }
|
|
||||||
artist = story.artists.joinToString { it.name }
|
|
||||||
thumbnail_url = "$IMAGE_SERVER_URL/${story.image}"
|
|
||||||
genre = story.genres.joinToString { it.name }
|
|
||||||
status = story.status!!.name.toStatus()
|
|
||||||
description = Jsoup.parse(story.synopsis)
|
|
||||||
.select("p")
|
|
||||||
.joinToString("\n\n") { it.text() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun chapterListRequest(manga: SManga): Request {
|
override fun chapterListRequest(manga: SManga): Request {
|
||||||
|
@ -205,20 +160,10 @@ class SaikaiScan : HttpSource() {
|
||||||
|
|
||||||
return story.releases
|
return story.releases
|
||||||
.filter { it.isActive == 1 }
|
.filter { it.isActive == 1 }
|
||||||
.map { chapterFromObject(it, story.slug) }
|
.map { it.toSChapter(story.slug) }
|
||||||
.sortedByDescending(SChapter::chapter_number)
|
.sortedByDescending(SChapter::chapter_number)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun chapterFromObject(obj: SaikaiScanReleaseDto, storySlug: String): SChapter =
|
|
||||||
SChapter.create().apply {
|
|
||||||
name = "Capítulo ${obj.chapter}" +
|
|
||||||
(if (obj.title.isNullOrEmpty().not()) " - ${obj.title}" else "")
|
|
||||||
chapter_number = obj.chapter.toFloatOrNull() ?: -1f
|
|
||||||
date_upload = obj.publishedAt.toDate()
|
|
||||||
scanlator = this@SaikaiScan.name
|
|
||||||
url = "/ler/comics/$storySlug/${obj.id}/${obj.slug}"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun pageListRequest(chapter: SChapter): Request {
|
override fun pageListRequest(chapter: SChapter): Request {
|
||||||
val releaseId = chapter.url
|
val releaseId = chapter.url
|
||||||
.substringBeforeLast("/")
|
.substringBeforeLast("/")
|
||||||
|
@ -347,29 +292,16 @@ class SaikaiScan : HttpSource() {
|
||||||
json.decodeFromString(it.body?.string().orEmpty())
|
json.decodeFromString(it.body?.string().orEmpty())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun String.toDate(): Long {
|
|
||||||
return runCatching { DATE_FORMATTER.parse(this)?.time }
|
|
||||||
.getOrNull() ?: 0L
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun String.toStatus(): Int = when (this) {
|
|
||||||
"Concluído" -> SManga.COMPLETED
|
|
||||||
"Em Andamento" -> SManga.ONGOING
|
|
||||||
else -> SManga.UNKNOWN
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
const val SOURCE_NAME = "Saikai Scan"
|
||||||
|
|
||||||
private const val ACCEPT_IMAGE = "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8"
|
private const val ACCEPT_IMAGE = "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8"
|
||||||
private const val ACCEPT_JSON = "application/json, text/plain, */*"
|
private const val ACCEPT_JSON = "application/json, text/plain, */*"
|
||||||
|
|
||||||
private const val COMIC_FORMAT_ID = "2"
|
private const val COMIC_FORMAT_ID = "2"
|
||||||
private const val PER_PAGE = "12"
|
private const val PER_PAGE = "12"
|
||||||
|
|
||||||
private val DATE_FORMATTER by lazy {
|
|
||||||
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'", Locale("pt", "BR"))
|
|
||||||
}
|
|
||||||
|
|
||||||
private const val API_URL = "https://api.saikai.com.br"
|
private const val API_URL = "https://api.saikai.com.br"
|
||||||
private const val IMAGE_SERVER_URL = "https://s3-alpha.saikai.com.br"
|
const val IMAGE_SERVER_URL = "https://s3-alpha.saikai.com.br"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
package eu.kanade.tachiyomi.extension.pt.saikaiscan
|
package eu.kanade.tachiyomi.extension.pt.saikaiscan
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import org.jsoup.Jsoup
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class SaikaiScanResultDto<T>(
|
data class SaikaiScanResultDto<T>(
|
||||||
|
@ -29,7 +34,25 @@ data class SaikaiScanStoryDto(
|
||||||
val status: SaikaiScanStatusDto? = null,
|
val status: SaikaiScanStatusDto? = null,
|
||||||
val synopsis: String,
|
val synopsis: String,
|
||||||
val title: String
|
val title: String
|
||||||
)
|
) {
|
||||||
|
|
||||||
|
fun toSManga(): SManga = SManga.create().apply {
|
||||||
|
title = this@SaikaiScanStoryDto.title
|
||||||
|
author = authors.joinToString { it.name }
|
||||||
|
artist = artists.joinToString { it.name }
|
||||||
|
genre = genres.joinToString { it.name }
|
||||||
|
status = when (this@SaikaiScanStoryDto.status?.name) {
|
||||||
|
"Concluído" -> SManga.COMPLETED
|
||||||
|
"Em Andamento" -> SManga.ONGOING
|
||||||
|
else -> SManga.UNKNOWN
|
||||||
|
}
|
||||||
|
description = Jsoup.parseBodyFragment(synopsis)
|
||||||
|
.select("p")
|
||||||
|
.joinToString("\n\n") { it.text() }
|
||||||
|
thumbnail_url = "${SaikaiScan.IMAGE_SERVER_URL}/$image"
|
||||||
|
url = "/comics/$slug"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class SaikaiScanPersonDto(
|
data class SaikaiScanPersonDto(
|
||||||
|
@ -55,9 +78,24 @@ data class SaikaiScanReleaseDto(
|
||||||
@SerialName("release_images") val releaseImages: List<SaikaiScanReleaseImageDto> = emptyList(),
|
@SerialName("release_images") val releaseImages: List<SaikaiScanReleaseImageDto> = emptyList(),
|
||||||
val slug: String,
|
val slug: String,
|
||||||
val title: String? = ""
|
val title: String? = ""
|
||||||
)
|
) {
|
||||||
|
|
||||||
|
fun toSChapter(storySlug: String): SChapter = SChapter.create().apply {
|
||||||
|
name = "Capítulo $chapter" +
|
||||||
|
(if (this@SaikaiScanReleaseDto.title.isNullOrEmpty().not()) " - ${this@SaikaiScanReleaseDto.title}" else "")
|
||||||
|
chapter_number = chapter.toFloatOrNull() ?: -1f
|
||||||
|
date_upload = runCatching { DATE_FORMATTER.parse(publishedAt)?.time }
|
||||||
|
.getOrNull() ?: 0L
|
||||||
|
scanlator = SaikaiScan.SOURCE_NAME
|
||||||
|
url = "/ler/comics/$storySlug/$id/$slug"
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val DATE_FORMATTER by lazy {
|
||||||
|
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'", Locale("pt", "BR"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class SaikaiScanReleaseImageDto(
|
data class SaikaiScanReleaseImageDto(val image: String)
|
||||||
val image: String
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,10 +1,26 @@
|
||||||
package eu.kanade.tachiyomi.extension.pt.saikaiscan
|
package eu.kanade.tachiyomi.extension.pt.saikaiscan
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
import eu.kanade.tachiyomi.source.model.Filter
|
||||||
|
import okhttp3.HttpUrl
|
||||||
|
|
||||||
|
interface UrlQueryFilter {
|
||||||
|
fun addQueryParameter(url: HttpUrl.Builder)
|
||||||
|
}
|
||||||
|
|
||||||
class Genre(title: String, val id: Int) : Filter.CheckBox(title)
|
class Genre(title: String, val id: Int) : Filter.CheckBox(title)
|
||||||
|
|
||||||
class GenreFilter(genres: List<Genre>) : Filter.Group<Genre>("Gêneros", genres)
|
class GenreFilter(genres: List<Genre>) :
|
||||||
|
Filter.Group<Genre>("Gêneros", genres),
|
||||||
|
UrlQueryFilter {
|
||||||
|
|
||||||
|
override fun addQueryParameter(url: HttpUrl.Builder) {
|
||||||
|
val genresParameter = state
|
||||||
|
.filter { it.state }
|
||||||
|
.joinToString(",") { it.id.toString() }
|
||||||
|
|
||||||
|
url.addQueryParameter("genres", genresParameter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data class Country(val name: String, val id: Int) {
|
data class Country(val name: String, val id: Int) {
|
||||||
override fun toString(): String = name
|
override fun toString(): String = name
|
||||||
|
@ -15,26 +31,48 @@ open class EnhancedSelect<T>(name: String, values: Array<T>) : Filter.Select<T>(
|
||||||
get() = values[state]
|
get() = values[state]
|
||||||
}
|
}
|
||||||
|
|
||||||
class CountryFilter(countries: List<Country>) : EnhancedSelect<Country>(
|
class CountryFilter(countries: List<Country>) :
|
||||||
"Nacionalidade",
|
EnhancedSelect<Country>("Nacionalidade", countries.toTypedArray()),
|
||||||
countries.toTypedArray()
|
UrlQueryFilter {
|
||||||
)
|
|
||||||
|
override fun addQueryParameter(url: HttpUrl.Builder) {
|
||||||
|
if (state > 0) {
|
||||||
|
url.addQueryParameter("country", selected.id.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data class Status(val name: String, val id: Int) {
|
data class Status(val name: String, val id: Int) {
|
||||||
override fun toString(): String = name
|
override fun toString(): String = name
|
||||||
}
|
}
|
||||||
|
|
||||||
class StatusFilter(statuses: List<Status>) : EnhancedSelect<Status>(
|
class StatusFilter(statuses: List<Status>) :
|
||||||
"Status",
|
EnhancedSelect<Status>("Status", statuses.toTypedArray()),
|
||||||
statuses.toTypedArray()
|
UrlQueryFilter {
|
||||||
)
|
|
||||||
|
override fun addQueryParameter(url: HttpUrl.Builder) {
|
||||||
|
if (state > 0) {
|
||||||
|
url.addQueryParameter("status", selected.id.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data class SortProperty(val name: String, val slug: String) {
|
data class SortProperty(val name: String, val slug: String) {
|
||||||
override fun toString(): String = name
|
override fun toString(): String = name
|
||||||
}
|
}
|
||||||
|
|
||||||
class SortByFilter(val sortProperties: List<SortProperty>) : Filter.Sort(
|
class SortByFilter(val sortProperties: List<SortProperty>) :
|
||||||
"Ordenar por",
|
Filter.Sort(
|
||||||
sortProperties.map { it.name }.toTypedArray(),
|
name = "Ordenar por",
|
||||||
Selection(2, ascending = false)
|
values = sortProperties.map { it.name }.toTypedArray(),
|
||||||
)
|
state = Selection(2, ascending = false)
|
||||||
|
),
|
||||||
|
UrlQueryFilter {
|
||||||
|
|
||||||
|
override fun addQueryParameter(url: HttpUrl.Builder) {
|
||||||
|
val sortProperty = sortProperties[state!!.index]
|
||||||
|
val sortDirection = if (state!!.ascending) "asc" else "desc"
|
||||||
|
url.setQueryParameter("sortProperty", sortProperty.slug)
|
||||||
|
url.setQueryParameter("sortDirection", sortDirection)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue