parent
bf6740e7e0
commit
2f1cae5bbf
|
@ -21,8 +21,6 @@ class ReaperScans : HeanCms(
|
||||||
// Site changed from Madara to HeanCms.
|
// Site changed from Madara to HeanCms.
|
||||||
override val versionId = 2
|
override val versionId = 2
|
||||||
|
|
||||||
override val fetchAllTitlesStrategy = FetchAllStrategy.SEARCH_ALL
|
|
||||||
|
|
||||||
override val coverPath: String = ""
|
override val coverPath: String = ""
|
||||||
|
|
||||||
override val dateFormat: SimpleDateFormat = super.dateFormat.apply {
|
override val dateFormat: SimpleDateFormat = super.dateFormat.apply {
|
||||||
|
|
|
@ -1,16 +1,9 @@
|
||||||
package eu.kanade.tachiyomi.extension.es.yugenmangas
|
package eu.kanade.tachiyomi.extension.es.yugenmangas
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import android.content.SharedPreferences
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.preference.ListPreference
|
|
||||||
import androidx.preference.PreferenceScreen
|
|
||||||
import eu.kanade.tachiyomi.multisrc.heancms.Genre
|
import eu.kanade.tachiyomi.multisrc.heancms.Genre
|
||||||
import eu.kanade.tachiyomi.multisrc.heancms.HeanCms
|
import eu.kanade.tachiyomi.multisrc.heancms.HeanCms
|
||||||
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
|
||||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
import uy.kohesive.injekt.Injekt
|
|
||||||
import uy.kohesive.injekt.api.get
|
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.TimeZone
|
import java.util.TimeZone
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
@ -21,26 +14,15 @@ class YugenMangas :
|
||||||
"https://yugenmangas.net",
|
"https://yugenmangas.net",
|
||||||
"es",
|
"es",
|
||||||
"https://api.yugenmangas.net",
|
"https://api.yugenmangas.net",
|
||||||
),
|
) {
|
||||||
ConfigurableSource {
|
|
||||||
|
|
||||||
private val preferences: SharedPreferences by lazy {
|
|
||||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Site changed from Madara to HeanCms.
|
// Site changed from Madara to HeanCms.
|
||||||
override val versionId = 2
|
override val versionId = 2
|
||||||
|
|
||||||
override val fetchAllTitlesStrategy = when (getfetchAllStrategyPref()) {
|
|
||||||
"all" -> FetchAllStrategy.SEARCH_ALL
|
|
||||||
"each" -> FetchAllStrategy.SEARCH_EACH
|
|
||||||
else -> FetchAllStrategy.NONE
|
|
||||||
}
|
|
||||||
|
|
||||||
override val client = super.client.newBuilder()
|
override val client = super.client.newBuilder()
|
||||||
.connectTimeout(60, TimeUnit.SECONDS)
|
.connectTimeout(60, TimeUnit.SECONDS)
|
||||||
.readTimeout(90, TimeUnit.SECONDS)
|
.readTimeout(90, TimeUnit.SECONDS)
|
||||||
.rateLimit(2, 3)
|
.rateLimitHost(apiUrl.toHttpUrl(), 2, 3)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
override val coverPath: String = ""
|
override val coverPath: String = ""
|
||||||
|
@ -99,42 +81,4 @@ class YugenMangas :
|
||||||
Genre("Yaoi", 43),
|
Genre("Yaoi", 43),
|
||||||
Genre("Yuri", 44),
|
Genre("Yuri", 44),
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun getfetchAllStrategyPref(): String? {
|
|
||||||
return preferences.getString(PREF_FETCH_ALL_STRATEGY_KEY, PREF_FETCH_ALL_STRATEGY_DEFAULT)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
|
||||||
val fetchAllStrategyPreference = ListPreference(screen.context).apply {
|
|
||||||
key = PREF_FETCH_ALL_STRATEGY_KEY
|
|
||||||
title = PREF_FETCH_ALL_STRATEGY_TITLE
|
|
||||||
summary = PREF_FETCH_ALL_STRATEGY_SUMMARY
|
|
||||||
entries = PREF_FETCH_ALL_STRATEGY_ENTRIES
|
|
||||||
entryValues = PREF_FETCH_ALL_STRATEGY_VALUES
|
|
||||||
setDefaultValue(PREF_FETCH_ALL_STRATEGY_DEFAULT)
|
|
||||||
|
|
||||||
setOnPreferenceChangeListener { _, newValue ->
|
|
||||||
Toast.makeText(screen.context, RESTART_MESSAGE, Toast.LENGTH_LONG).show()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
screen.addPreference(fetchAllStrategyPreference)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val PREF_FETCH_ALL_STRATEGY_KEY = "prefFetchAllStrategy"
|
|
||||||
const val PREF_FETCH_ALL_STRATEGY_TITLE = "Método de búsqueda"
|
|
||||||
const val PREF_FETCH_ALL_STRATEGY_SUMMARY = "Global: Busca las URLs de todas las series al iniciar la aplicación, lento pero más estable.\n" +
|
|
||||||
"Individual: Busca la URL de la serie al actualizar, rápido pero puede fallar.\n" +
|
|
||||||
"Ninguno: Usa la URL con la que fue agregado, tendrá que migrar si la URL cambia.\n" +
|
|
||||||
"Valor actual: %s"
|
|
||||||
|
|
||||||
val PREF_FETCH_ALL_STRATEGY_ENTRIES = arrayOf("Ninguno", "Individual", "Global")
|
|
||||||
val PREF_FETCH_ALL_STRATEGY_VALUES = arrayOf("off", "each", "all")
|
|
||||||
|
|
||||||
const val PREF_FETCH_ALL_STRATEGY_DEFAULT = "off"
|
|
||||||
|
|
||||||
const val RESTART_MESSAGE = "Reinicie la aplicación para que los cambios surtan efecto."
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package eu.kanade.tachiyomi.multisrc.heancms
|
package eu.kanade.tachiyomi.multisrc.heancms
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import android.content.SharedPreferences
|
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
import eu.kanade.tachiyomi.source.model.Filter
|
||||||
|
@ -21,8 +19,6 @@ import okhttp3.Request
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import uy.kohesive.injekt.Injekt
|
|
||||||
import uy.kohesive.injekt.api.get
|
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
|
@ -33,10 +29,6 @@ abstract class HeanCms(
|
||||||
protected val apiUrl: String = baseUrl.replace("://", "://api."),
|
protected val apiUrl: String = baseUrl.replace("://", "://api."),
|
||||||
) : HttpSource() {
|
) : HttpSource() {
|
||||||
|
|
||||||
private val preferences: SharedPreferences by lazy {
|
|
||||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val supportsLatest = true
|
override val supportsLatest = true
|
||||||
|
|
||||||
override val client: OkHttpClient = network.cloudflareClient
|
override val client: OkHttpClient = network.cloudflareClient
|
||||||
|
@ -53,14 +45,10 @@ abstract class HeanCms(
|
||||||
|
|
||||||
protected val intl by lazy { HeanCmsIntl(lang) }
|
protected val intl by lazy { HeanCmsIntl(lang) }
|
||||||
|
|
||||||
protected open val fetchAllTitlesStrategy = FetchAllStrategy.NONE
|
|
||||||
|
|
||||||
protected open val coverPath: String = "cover/"
|
protected open val coverPath: String = "cover/"
|
||||||
|
|
||||||
protected open val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ", Locale.US)
|
protected open val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ", Locale.US)
|
||||||
|
|
||||||
private var seriesSlugMap: Map<String, HeanCmsTitle>? = null
|
|
||||||
|
|
||||||
override fun headersBuilder(): Headers.Builder = Headers.Builder()
|
override fun headersBuilder(): Headers.Builder = Headers.Builder()
|
||||||
.add("Origin", baseUrl)
|
.add("Origin", baseUrl)
|
||||||
.add("Referer", "$baseUrl/")
|
.add("Referer", "$baseUrl/")
|
||||||
|
@ -70,7 +58,7 @@ abstract class HeanCms(
|
||||||
page = page,
|
page = page,
|
||||||
order = "desc",
|
order = "desc",
|
||||||
orderBy = "total_views",
|
orderBy = "total_views",
|
||||||
status = "Ongoing",
|
status = "All",
|
||||||
type = "Comic",
|
type = "Comic",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -89,17 +77,13 @@ abstract class HeanCms(
|
||||||
|
|
||||||
if (json.startsWith("{")) {
|
if (json.startsWith("{")) {
|
||||||
val result = json.parseAs<HeanCmsQuerySearchDto>()
|
val result = json.parseAs<HeanCmsQuerySearchDto>()
|
||||||
val mangaList = result.data.map { it.toSManga(apiUrl, coverPath, fetchAllTitlesStrategy) }
|
val mangaList = result.data.map { it.toSManga(apiUrl, coverPath) }
|
||||||
|
|
||||||
fetchAllTitles()
|
|
||||||
|
|
||||||
return MangasPage(mangaList, result.meta?.hasNextPage ?: false)
|
return MangasPage(mangaList, result.meta?.hasNextPage ?: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
val mangaList = json.parseAs<List<HeanCmsSeriesDto>>()
|
val mangaList = json.parseAs<List<HeanCmsSeriesDto>>()
|
||||||
.map { it.toSManga(apiUrl, coverPath, fetchAllTitlesStrategy) }
|
.map { it.toSManga(apiUrl, coverPath) }
|
||||||
|
|
||||||
fetchAllTitles()
|
|
||||||
|
|
||||||
return MangasPage(mangaList, hasNextPage = false)
|
return MangasPage(mangaList, hasNextPage = false)
|
||||||
}
|
}
|
||||||
|
@ -109,7 +93,7 @@ abstract class HeanCms(
|
||||||
page = page,
|
page = page,
|
||||||
order = "desc",
|
order = "desc",
|
||||||
orderBy = "latest",
|
orderBy = "latest",
|
||||||
status = "Ongoing",
|
status = "All",
|
||||||
type = "Comic",
|
type = "Comic",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -137,10 +121,6 @@ abstract class HeanCms(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||||
/**
|
|
||||||
* Their query search endpoint doesn't return the thumbnails, so we need to do
|
|
||||||
* later an special parsing to get the thumbnails as well from the slug map.
|
|
||||||
*/
|
|
||||||
if (query.isNotBlank()) {
|
if (query.isNotBlank()) {
|
||||||
val searchPayloadObj = HeanCmsSearchPayloadDto(query)
|
val searchPayloadObj = HeanCmsSearchPayloadDto(query)
|
||||||
val searchPayload = json.encodeToString(searchPayloadObj)
|
val searchPayload = json.encodeToString(searchPayloadObj)
|
||||||
|
@ -182,96 +162,49 @@ abstract class HeanCms(
|
||||||
val json = response.body.string()
|
val json = response.body.string()
|
||||||
|
|
||||||
if (response.request.url.pathSegments.last() == "search") {
|
if (response.request.url.pathSegments.last() == "search") {
|
||||||
fetchAllTitles()
|
|
||||||
|
|
||||||
val result = json.parseAs<List<HeanCmsSearchDto>>()
|
val result = json.parseAs<List<HeanCmsSearchDto>>()
|
||||||
val mangaList = result
|
val mangaList = result
|
||||||
.filter { it.type == "Comic" }
|
.filter { it.type == "Comic" }
|
||||||
.map { it.toSManga(apiUrl, coverPath, seriesSlugMap.orEmpty(), fetchAllTitlesStrategy) }
|
.map {
|
||||||
|
it.slug = it.slug.replace(TIMESTAMP_REGEX, "")
|
||||||
|
it.toSManga(apiUrl, coverPath)
|
||||||
|
}
|
||||||
|
|
||||||
return MangasPage(mangaList, false)
|
return MangasPage(mangaList, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json.startsWith("{")) {
|
if (json.startsWith("{")) {
|
||||||
val result = json.parseAs<HeanCmsQuerySearchDto>()
|
val result = json.parseAs<HeanCmsQuerySearchDto>()
|
||||||
val mangaList = result.data.map { it.toSManga(apiUrl, coverPath, fetchAllTitlesStrategy) }
|
val mangaList = result.data.map { it.toSManga(apiUrl, coverPath) }
|
||||||
|
|
||||||
fetchAllTitles()
|
|
||||||
|
|
||||||
return MangasPage(mangaList, result.meta?.hasNextPage ?: false)
|
return MangasPage(mangaList, result.meta?.hasNextPage ?: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
val mangaList = json.parseAs<List<HeanCmsSeriesDto>>()
|
val mangaList = json.parseAs<List<HeanCmsSeriesDto>>()
|
||||||
.map { it.toSManga(apiUrl, coverPath, fetchAllTitlesStrategy) }
|
.map { it.toSManga(apiUrl, coverPath) }
|
||||||
|
|
||||||
fetchAllTitles()
|
|
||||||
|
|
||||||
return MangasPage(mangaList, hasNextPage = false)
|
return MangasPage(mangaList, hasNextPage = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMangaUrl(manga: SManga): String {
|
override fun getMangaUrl(manga: SManga) = baseUrl + manga.url
|
||||||
val seriesSlug = manga.url
|
|
||||||
.substringAfterLast("/")
|
|
||||||
.replace(TIMESTAMP_REGEX, "")
|
|
||||||
|
|
||||||
val currentSlug = if (fetchAllTitlesStrategy == FetchAllStrategy.SEARCH_EACH) {
|
|
||||||
preferences.slugMap[seriesSlug] ?: manga.url.substringAfterLast("/")
|
|
||||||
} else {
|
|
||||||
seriesSlugMap?.get(seriesSlug)?.slug ?: manga.url.substringAfterLast("/")
|
|
||||||
}
|
|
||||||
|
|
||||||
return "$baseUrl/series/$currentSlug"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun mangaDetailsRequest(manga: SManga): Request {
|
override fun mangaDetailsRequest(manga: SManga): Request {
|
||||||
if (fetchAllTitlesStrategy == FetchAllStrategy.SEARCH_EACH) {
|
|
||||||
val searchQuery = manga.title
|
|
||||||
val searchPayloadObj = HeanCmsSearchPayloadDto(searchQuery)
|
|
||||||
val searchPayload = json.encodeToString(searchPayloadObj)
|
|
||||||
.toRequestBody(JSON_MEDIA_TYPE)
|
|
||||||
|
|
||||||
val apiHeaders = headersBuilder()
|
|
||||||
.add("Accept", ACCEPT_JSON)
|
|
||||||
.add("Content-Type", searchPayload.contentType().toString())
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val mangaSlug = manga.url
|
|
||||||
.substringAfterLast("/")
|
|
||||||
|
|
||||||
return POST("$apiUrl/series/search#$mangaSlug", apiHeaders, searchPayload)
|
|
||||||
}
|
|
||||||
|
|
||||||
val seriesSlug = manga.url
|
val seriesSlug = manga.url
|
||||||
.substringAfterLast("/")
|
.substringAfterLast("/")
|
||||||
.replace(TIMESTAMP_REGEX, "")
|
|
||||||
|
|
||||||
fetchAllTitles()
|
|
||||||
|
|
||||||
val seriesDetails = seriesSlugMap?.get(seriesSlug)
|
|
||||||
val currentSlug = seriesDetails?.slug ?: manga.url.substringAfterLast("/")
|
|
||||||
val currentStatus = seriesDetails?.status ?: manga.status
|
|
||||||
|
|
||||||
val apiHeaders = headersBuilder()
|
val apiHeaders = headersBuilder()
|
||||||
.add("Accept", ACCEPT_JSON)
|
.add("Accept", ACCEPT_JSON)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
return GET("$apiUrl/series/$currentSlug#$currentStatus", apiHeaders)
|
return GET("$apiUrl/series/$seriesSlug#${manga.status}", apiHeaders)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mangaDetailsParse(response: Response): SManga {
|
override fun mangaDetailsParse(response: Response): SManga {
|
||||||
val mangaStatus = response.request.url.fragment?.toIntOrNull() ?: SManga.UNKNOWN
|
val mangaStatus = response.request.url.fragment?.toIntOrNull() ?: SManga.UNKNOWN
|
||||||
|
|
||||||
val result = runCatching {
|
val result = runCatching { response.parseAs<HeanCmsSeriesDto>() }
|
||||||
if (fetchAllTitlesStrategy == FetchAllStrategy.SEARCH_EACH) {
|
|
||||||
val originalSlug = response.request.url.fragment!!
|
|
||||||
val searchResult = response.parseAs<List<HeanCmsSearchDto>>()
|
|
||||||
searchResultToSeries(originalSlug, searchResult)
|
|
||||||
} else {
|
|
||||||
response.parseAs<HeanCmsSeriesDto>()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val seriesDetails = result.getOrNull()?.toSManga(apiUrl, coverPath, fetchAllTitlesStrategy)
|
val seriesDetails = result.getOrNull()?.toSManga(apiUrl, coverPath)
|
||||||
?: throw Exception(intl.urlChangedError(name))
|
?: throw Exception(intl.urlChangedError(name))
|
||||||
|
|
||||||
return seriesDetails.apply {
|
return seriesDetails.apply {
|
||||||
|
@ -283,13 +216,7 @@ abstract class HeanCms(
|
||||||
override fun chapterListRequest(manga: SManga): Request = mangaDetailsRequest(manga)
|
override fun chapterListRequest(manga: SManga): Request = mangaDetailsRequest(manga)
|
||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
val result = if (fetchAllTitlesStrategy == FetchAllStrategy.SEARCH_EACH) {
|
val result = response.parseAs<HeanCmsSeriesDto>()
|
||||||
val originalSlug = response.request.url.fragment!!
|
|
||||||
val searchResult = response.parseAs<List<HeanCmsSearchDto>>()
|
|
||||||
searchResultToSeries(originalSlug, searchResult)
|
|
||||||
} else {
|
|
||||||
response.parseAs<HeanCmsSeriesDto>()
|
|
||||||
}
|
|
||||||
|
|
||||||
val currentTimestamp = System.currentTimeMillis()
|
val currentTimestamp = System.currentTimeMillis()
|
||||||
|
|
||||||
|
@ -300,31 +227,6 @@ abstract class HeanCms(
|
||||||
.reversed()
|
.reversed()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun searchResultToSeries(originalSlug: String, searchResult: List<HeanCmsSearchDto>): HeanCmsSeriesDto {
|
|
||||||
val mangaSlug = searchResult
|
|
||||||
.filter { it.type == "Comic" }
|
|
||||||
.map { it.slug }
|
|
||||||
.find { it.startsWith(originalSlug) || originalSlug.startsWith(it) }
|
|
||||||
?: originalSlug
|
|
||||||
|
|
||||||
val apiHeaders = headersBuilder()
|
|
||||||
.add("Accept", ACCEPT_JSON)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val detailsRequest = GET("$apiUrl/series/$mangaSlug", apiHeaders)
|
|
||||||
val result = client.newCall(detailsRequest).execute()
|
|
||||||
.parseAs<HeanCmsSeriesDto>()
|
|
||||||
|
|
||||||
val permSlug = result.slug
|
|
||||||
.substringAfterLast("/")
|
|
||||||
.replace(TIMESTAMP_REGEX, "")
|
|
||||||
|
|
||||||
preferences.slugMap = preferences.slugMap.toMutableMap()
|
|
||||||
.also { it[permSlug] = result.slug.substringAfterLast("/") }
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getChapterUrl(chapter: SChapter): String = baseUrl + chapter.url
|
override fun getChapterUrl(chapter: SChapter): String = baseUrl + chapter.url
|
||||||
|
|
||||||
override fun pageListRequest(chapter: SChapter): Request {
|
override fun pageListRequest(chapter: SChapter): Request {
|
||||||
|
@ -379,83 +281,6 @@ abstract class HeanCms(
|
||||||
|
|
||||||
protected open fun getGenreList(): List<Genre> = emptyList()
|
protected open fun getGenreList(): List<Genre> = emptyList()
|
||||||
|
|
||||||
protected open fun fetchAllTitles() {
|
|
||||||
if (!seriesSlugMap.isNullOrEmpty() || fetchAllTitlesStrategy != FetchAllStrategy.SEARCH_ALL) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val result = runCatching {
|
|
||||||
var hasNextPage = true
|
|
||||||
var page = 1
|
|
||||||
val tempMap = mutableMapOf<String, HeanCmsTitle>()
|
|
||||||
|
|
||||||
while (hasNextPage) {
|
|
||||||
val response = client.newCall(allTitlesRequest(page)).execute()
|
|
||||||
val json = response.body.string()
|
|
||||||
|
|
||||||
if (json.startsWith("{")) {
|
|
||||||
val result = json.parseAs<HeanCmsQuerySearchDto>()
|
|
||||||
tempMap.putAll(parseAllTitles(result.data))
|
|
||||||
hasNextPage = result.meta?.hasNextPage ?: false
|
|
||||||
page++
|
|
||||||
} else {
|
|
||||||
val result = json.parseAs<List<HeanCmsSeriesDto>>()
|
|
||||||
tempMap.putAll(parseAllTitles(result))
|
|
||||||
hasNextPage = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tempMap.toMap()
|
|
||||||
}
|
|
||||||
|
|
||||||
seriesSlugMap = result.getOrNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
protected open fun allTitlesRequest(page: Int): Request {
|
|
||||||
val payloadObj = HeanCmsQuerySearchPayloadDto(
|
|
||||||
page = page,
|
|
||||||
order = "desc",
|
|
||||||
orderBy = "total_views",
|
|
||||||
type = "Comic",
|
|
||||||
)
|
|
||||||
|
|
||||||
val payload = json.encodeToString(payloadObj).toRequestBody(JSON_MEDIA_TYPE)
|
|
||||||
|
|
||||||
val apiHeaders = headersBuilder()
|
|
||||||
.add("Accept", ACCEPT_JSON)
|
|
||||||
.add("Content-Type", payload.contentType().toString())
|
|
||||||
.build()
|
|
||||||
|
|
||||||
return POST("$apiUrl/series/querysearch", apiHeaders, payload)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected var SharedPreferences.slugMap: MutableMap<String, String>
|
|
||||||
get() {
|
|
||||||
val jsonMap = getString(PREF_URL_MAP, "{}")!!
|
|
||||||
val slugMap = runCatching { json.decodeFromString<Map<String, String>>(jsonMap) }
|
|
||||||
return slugMap.getOrNull()?.toMutableMap() ?: mutableMapOf()
|
|
||||||
}
|
|
||||||
set(newSlugMap) {
|
|
||||||
edit()
|
|
||||||
.putString(PREF_URL_MAP, json.encodeToString(newSlugMap))
|
|
||||||
.commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
protected open fun parseAllTitles(result: List<HeanCmsSeriesDto>): Map<String, HeanCmsTitle> {
|
|
||||||
return result
|
|
||||||
.filter { it.type == "Comic" }
|
|
||||||
.associateBy(
|
|
||||||
keySelector = { it.slug.replace(TIMESTAMP_REGEX, "") },
|
|
||||||
valueTransform = {
|
|
||||||
HeanCmsTitle(
|
|
||||||
slug = it.slug,
|
|
||||||
thumbnailFileName = it.thumbnail,
|
|
||||||
status = it.status?.toStatus() ?: SManga.UNKNOWN,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getFilterList(): FilterList {
|
override fun getFilterList(): FilterList {
|
||||||
val genres = getGenreList()
|
val genres = getGenreList()
|
||||||
|
|
||||||
|
@ -478,28 +303,14 @@ abstract class HeanCms(
|
||||||
private inline fun <reified R> List<*>.firstInstanceOrNull(): R? =
|
private inline fun <reified R> List<*>.firstInstanceOrNull(): R? =
|
||||||
filterIsInstance<R>().firstOrNull()
|
filterIsInstance<R>().firstOrNull()
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to store the current slugs for sources that change it periodically and for the
|
|
||||||
* search that doesn't return the thumbnail URLs.
|
|
||||||
*/
|
|
||||||
data class HeanCmsTitle(val slug: String, val thumbnailFileName: String, val status: Int)
|
|
||||||
|
|
||||||
enum class FetchAllStrategy {
|
|
||||||
NONE,
|
|
||||||
SEARCH_EACH,
|
|
||||||
SEARCH_ALL,
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
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 val JSON_MEDIA_TYPE = "application/json".toMediaType()
|
private val JSON_MEDIA_TYPE = "application/json".toMediaType()
|
||||||
|
|
||||||
val TIMESTAMP_REGEX = "-\\d+$".toRegex()
|
val TIMESTAMP_REGEX = """-\d{13}$""".toRegex()
|
||||||
|
|
||||||
const val SEARCH_PREFIX = "slug:"
|
const val SEARCH_PREFIX = "slug:"
|
||||||
|
|
||||||
private const val PREF_URL_MAP = "pref_url_map"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package eu.kanade.tachiyomi.multisrc.heancms
|
package eu.kanade.tachiyomi.multisrc.heancms
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.multisrc.heancms.HeanCms.FetchAllStrategy
|
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
|
@ -27,7 +26,7 @@ data class HeanCmsQuerySearchMetaDto(
|
||||||
@Serializable
|
@Serializable
|
||||||
data class HeanCmsSearchDto(
|
data class HeanCmsSearchDto(
|
||||||
val description: String? = null,
|
val description: String? = null,
|
||||||
@SerialName("series_slug") val slug: String,
|
@SerialName("series_slug") var slug: String,
|
||||||
@SerialName("series_type") val type: String,
|
@SerialName("series_type") val type: String,
|
||||||
val title: String,
|
val title: String,
|
||||||
val thumbnail: String? = null,
|
val thumbnail: String? = null,
|
||||||
|
@ -36,15 +35,9 @@ data class HeanCmsSearchDto(
|
||||||
fun toSManga(
|
fun toSManga(
|
||||||
apiUrl: String,
|
apiUrl: String,
|
||||||
coverPath: String,
|
coverPath: String,
|
||||||
slugMap: Map<String, HeanCms.HeanCmsTitle>,
|
|
||||||
fetchStrategy: FetchAllStrategy = FetchAllStrategy.NONE,
|
|
||||||
): SManga = SManga.create().apply {
|
): SManga = SManga.create().apply {
|
||||||
val slug = if (fetchStrategy == FetchAllStrategy.NONE) slug else slug.replace(HeanCms.TIMESTAMP_REGEX, "")
|
|
||||||
val thumbnailFileName = slugMap[slug]?.thumbnailFileName
|
|
||||||
|
|
||||||
title = this@HeanCmsSearchDto.title
|
title = this@HeanCmsSearchDto.title
|
||||||
thumbnail_url = thumbnail?.toAbsoluteThumbnailUrl(apiUrl, coverPath)
|
thumbnail_url = thumbnail?.toAbsoluteThumbnailUrl(apiUrl, coverPath)
|
||||||
?: thumbnailFileName?.toAbsoluteThumbnailUrl(apiUrl, coverPath)
|
|
||||||
url = "/series/$slug"
|
url = "/series/$slug"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,10 +60,8 @@ data class HeanCmsSeriesDto(
|
||||||
fun toSManga(
|
fun toSManga(
|
||||||
apiUrl: String,
|
apiUrl: String,
|
||||||
coverPath: String,
|
coverPath: String,
|
||||||
fetchStrategy: FetchAllStrategy = FetchAllStrategy.NONE,
|
|
||||||
): SManga = SManga.create().apply {
|
): SManga = SManga.create().apply {
|
||||||
val descriptionBody = this@HeanCmsSeriesDto.description?.let(Jsoup::parseBodyFragment)
|
val descriptionBody = this@HeanCmsSeriesDto.description?.let(Jsoup::parseBodyFragment)
|
||||||
val slug = if (fetchStrategy == FetchAllStrategy.NONE) slug else slug.replace(HeanCms.TIMESTAMP_REGEX, "")
|
|
||||||
|
|
||||||
title = this@HeanCmsSeriesDto.title
|
title = this@HeanCmsSeriesDto.title
|
||||||
author = this@HeanCmsSeriesDto.author?.trim()
|
author = this@HeanCmsSeriesDto.author?.trim()
|
||||||
|
|
|
@ -9,7 +9,7 @@ class HeanCmsGenerator : ThemeSourceGenerator {
|
||||||
|
|
||||||
override val themeClass = "HeanCms"
|
override val themeClass = "HeanCms"
|
||||||
|
|
||||||
override val baseVersionCode: Int = 15
|
override val baseVersionCode: Int = 16
|
||||||
|
|
||||||
override val sources = listOf(
|
override val sources = listOf(
|
||||||
SingleLang("Glorious Scan", "https://gloriousscan.com", "pt-BR", overrideVersionCode = 17),
|
SingleLang("Glorious Scan", "https://gloriousscan.com", "pt-BR", overrideVersionCode = 17),
|
||||||
|
|
Loading…
Reference in New Issue