HeanCms: Add option to use ID instead slug (#17647)
* Use ID instead slug * Minor changes * Opps * ID * I cant explain this * Fix for search in old API * Unnecessary IF * Yugen domain * Change message * Ah xD
This commit is contained in:
		
							parent
							
								
									b1aa65cedc
								
							
						
					
					
						commit
						d1d9e03560
					
				| @ -21,7 +21,7 @@ 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 fetchAllTitles = true |     override val slugStrategy = SlugStrategy.FETCH_ALL | ||||||
|     override val useNewQueryEndpoint = true |     override val useNewQueryEndpoint = true | ||||||
| 
 | 
 | ||||||
|     override val coverPath: String = "" |     override val coverPath: String = "" | ||||||
|  | |||||||
| @ -11,7 +11,7 @@ import java.util.concurrent.TimeUnit | |||||||
| class YugenMangas : | class YugenMangas : | ||||||
|     HeanCms( |     HeanCms( | ||||||
|         "YugenMangas", |         "YugenMangas", | ||||||
|         "https://yugenmangas.lat", |         "https://yugenmangas.net", | ||||||
|         "es", |         "es", | ||||||
|         "https://api.yugenmangas.net", |         "https://api.yugenmangas.net", | ||||||
|     ) { |     ) { | ||||||
| @ -19,7 +19,7 @@ class YugenMangas : | |||||||
|     // Site changed from Madara to HeanCms. |     // Site changed from Madara to HeanCms. | ||||||
|     override val versionId = 2 |     override val versionId = 2 | ||||||
| 
 | 
 | ||||||
|     override val fetchAllTitles = true |     override val slugStrategy = SlugStrategy.ID | ||||||
|     override val useNewQueryEndpoint = true |     override val useNewQueryEndpoint = true | ||||||
| 
 | 
 | ||||||
|     override val client = super.client.newBuilder() |     override val client = super.client.newBuilder() | ||||||
|  | |||||||
| @ -1,5 +1,7 @@ | |||||||
| 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,6 +23,8 @@ 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 | ||||||
| 
 | 
 | ||||||
| @ -31,11 +35,15 @@ 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 | ||||||
| 
 | 
 | ||||||
|     protected open val fetchAllTitles = false |     protected open val slugStrategy = SlugStrategy.NONE | ||||||
| 
 | 
 | ||||||
|     protected open val useNewQueryEndpoint = false |     protected open val useNewQueryEndpoint = false | ||||||
| 
 | 
 | ||||||
| @ -103,7 +111,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, fetchAllTitles) } |             val mangaList = result.data.map { | ||||||
|  |                 if (slugStrategy != SlugStrategy.NONE) { | ||||||
|  |                     preferences.slugMap = preferences.slugMap.toMutableMap() | ||||||
|  |                         .also { map -> map[it.slug.toPermSlugIfNeeded()] = it.slug } | ||||||
|  |                 } | ||||||
|  |                 it.toSManga(apiUrl, coverPath, slugStrategy) | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             fetchAllTitles() |             fetchAllTitles() | ||||||
| 
 | 
 | ||||||
| @ -111,7 +125,13 @@ abstract class HeanCms( | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         val mangaList = json.parseAs<List<HeanCmsSeriesDto>>() |         val mangaList = json.parseAs<List<HeanCmsSeriesDto>>() | ||||||
|             .map { it.toSManga(apiUrl, coverPath, fetchAllTitles) } |             .map { | ||||||
|  |                 if (slugStrategy != SlugStrategy.NONE) { | ||||||
|  |                     preferences.slugMap = preferences.slugMap.toMutableMap() | ||||||
|  |                         .also { map -> map[it.slug.toPermSlugIfNeeded()] = it.slug } | ||||||
|  |                 } | ||||||
|  |                 it.toSManga(apiUrl, coverPath, slugStrategy) | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|         fetchAllTitles() |         fetchAllTitles() | ||||||
| 
 | 
 | ||||||
| @ -163,11 +183,33 @@ abstract class HeanCms( | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         val slug = query.substringAfter(SEARCH_PREFIX) |         val slug = query.substringAfter(SEARCH_PREFIX) | ||||||
|         val manga = SManga.create().apply { url = "/series/$slug" } |         val manga = SManga.create().apply { | ||||||
|  |             url = if (slugStrategy != SlugStrategy.NONE) { | ||||||
|  |                 val mangaId = getIdBySlug(slug) | ||||||
|  |                 "/series/${slug.toPermSlugIfNeeded()}#$mangaId" | ||||||
|  |             } else { | ||||||
|  |                 "/series/$slug" | ||||||
|  |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         return fetchMangaDetails(manga).map { MangasPage(listOf(it), false) } |         return fetchMangaDetails(manga).map { MangasPage(listOf(it), false) } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private fun getIdBySlug(slug: String): Int { | ||||||
|  |         val result = runCatching { | ||||||
|  |             val response = client.newCall(GET("$apiUrl/series/$slug", headers)).execute() | ||||||
|  |             val json = response.body.string() | ||||||
|  | 
 | ||||||
|  |             val seriesDetail = json.parseAs<HeanCmsSeriesDto>() | ||||||
|  | 
 | ||||||
|  |             preferences.slugMap = preferences.slugMap.toMutableMap() | ||||||
|  |                 .also { it[seriesDetail.slug.toPermSlugIfNeeded()] = seriesDetail.slug } | ||||||
|  | 
 | ||||||
|  |             seriesDetail.id | ||||||
|  |         } | ||||||
|  |         return result.getOrNull() ?: throw Exception(intl.idNotFoundError + slug) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { |     override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { | ||||||
|         if (useNewQueryEndpoint) { |         if (useNewQueryEndpoint) { | ||||||
|             return newEndpointSearchMangaRequest(page, query, filters) |             return newEndpointSearchMangaRequest(page, query, filters) | ||||||
| @ -242,8 +284,8 @@ abstract class HeanCms( | |||||||
|             val mangaList = result |             val mangaList = result | ||||||
|                 .filter { it.type == "Comic" } |                 .filter { it.type == "Comic" } | ||||||
|                 .map { |                 .map { | ||||||
|                     it.slug = it.slug.replace(TIMESTAMP_REGEX, "") |                     it.slug = it.slug.toPermSlugIfNeeded() | ||||||
|                     it.toSManga(apiUrl, coverPath, seriesSlugMap.orEmpty(), fetchAllTitles) |                     it.toSManga(apiUrl, coverPath, seriesSlugMap.orEmpty(), slugStrategy) | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|             return MangasPage(mangaList, false) |             return MangasPage(mangaList, false) | ||||||
| @ -251,7 +293,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, fetchAllTitles) } |             val mangaList = result.data.map { | ||||||
|  |                 if (slugStrategy != SlugStrategy.NONE) { | ||||||
|  |                     preferences.slugMap = preferences.slugMap.toMutableMap() | ||||||
|  |                         .also { map -> map[it.slug.toPermSlugIfNeeded()] = it.slug } | ||||||
|  |                 } | ||||||
|  |                 it.toSManga(apiUrl, coverPath, slugStrategy) | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             fetchAllTitles() |             fetchAllTitles() | ||||||
| 
 | 
 | ||||||
| @ -259,7 +307,13 @@ abstract class HeanCms( | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         val mangaList = json.parseAs<List<HeanCmsSeriesDto>>() |         val mangaList = json.parseAs<List<HeanCmsSeriesDto>>() | ||||||
|             .map { it.toSManga(apiUrl, coverPath, fetchAllTitles) } |             .map { | ||||||
|  |                 if (slugStrategy != SlugStrategy.NONE) { | ||||||
|  |                     preferences.slugMap = preferences.slugMap.toMutableMap() | ||||||
|  |                         .also { map -> map[it.slug.toPermSlugIfNeeded()] = it.slug } | ||||||
|  |                 } | ||||||
|  |                 it.toSManga(apiUrl, coverPath, slugStrategy) | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|         fetchAllTitles() |         fetchAllTitles() | ||||||
| 
 | 
 | ||||||
| @ -269,22 +323,34 @@ abstract class HeanCms( | |||||||
|     override fun getMangaUrl(manga: SManga): String { |     override fun getMangaUrl(manga: SManga): String { | ||||||
|         val seriesSlug = manga.url |         val seriesSlug = manga.url | ||||||
|             .substringAfterLast("/") |             .substringAfterLast("/") | ||||||
|  |             .substringBefore("#") | ||||||
|             .toPermSlugIfNeeded() |             .toPermSlugIfNeeded() | ||||||
| 
 | 
 | ||||||
|         val currentSlug = seriesSlugMap?.get(seriesSlug)?.slug ?: seriesSlug |         val currentSlug = if (slugStrategy != SlugStrategy.NONE) { | ||||||
|  |             preferences.slugMap[seriesSlug] ?: seriesSlug | ||||||
|  |         } else { | ||||||
|  |             seriesSlug | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         return "$baseUrl/series/$currentSlug" |         return "$baseUrl/series/$currentSlug" | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override fun mangaDetailsRequest(manga: SManga): Request { |     override fun mangaDetailsRequest(manga: SManga): Request { | ||||||
|         if (fetchAllTitles && manga.url.contains(TIMESTAMP_REGEX)) { |         if (slugStrategy != SlugStrategy.NONE && (manga.url.contains(TIMESTAMP_REGEX))) { | ||||||
|  |             throw Exception(intl.urlChangedError(name)) | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (slugStrategy == SlugStrategy.ID && !manga.url.contains("#")) { | ||||||
|             throw Exception(intl.urlChangedError(name)) |             throw Exception(intl.urlChangedError(name)) | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         val seriesSlug = manga.url |         val seriesSlug = manga.url | ||||||
|             .substringAfterLast("/") |             .substringAfterLast("/") | ||||||
|  |             .substringBefore("#") | ||||||
|             .toPermSlugIfNeeded() |             .toPermSlugIfNeeded() | ||||||
| 
 | 
 | ||||||
|  |         val seriesId = manga.url.substringAfterLast("#") | ||||||
|  | 
 | ||||||
|         fetchAllTitles() |         fetchAllTitles() | ||||||
| 
 | 
 | ||||||
|         val seriesDetails = seriesSlugMap?.get(seriesSlug) |         val seriesDetails = seriesSlugMap?.get(seriesSlug) | ||||||
| @ -295,7 +361,11 @@ abstract class HeanCms( | |||||||
|             .add("Accept", ACCEPT_JSON) |             .add("Accept", ACCEPT_JSON) | ||||||
|             .build() |             .build() | ||||||
| 
 | 
 | ||||||
|         return GET("$apiUrl/series/$currentSlug#$currentStatus", apiHeaders) |         return if (slugStrategy == SlugStrategy.ID) { | ||||||
|  |             GET("$apiUrl/series/id/$seriesId", apiHeaders) | ||||||
|  |         } else { | ||||||
|  |             GET("$apiUrl/series/$currentSlug#$currentStatus", apiHeaders) | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override fun mangaDetailsParse(response: Response): SManga { |     override fun mangaDetailsParse(response: Response): SManga { | ||||||
| @ -303,8 +373,14 @@ abstract class HeanCms( | |||||||
| 
 | 
 | ||||||
|         val result = runCatching { response.parseAs<HeanCmsSeriesDto>() } |         val result = runCatching { response.parseAs<HeanCmsSeriesDto>() } | ||||||
| 
 | 
 | ||||||
|         val seriesDetails = result.getOrNull()?.toSManga(apiUrl, coverPath, fetchAllTitles) |         val seriesResult = result.getOrNull() ?: throw Exception(intl.urlChangedError(name)) | ||||||
|             ?: throw Exception(intl.urlChangedError(name)) | 
 | ||||||
|  |         if (slugStrategy != SlugStrategy.NONE) { | ||||||
|  |             preferences.slugMap = preferences.slugMap.toMutableMap() | ||||||
|  |                 .also { it[seriesResult.slug.toPermSlugIfNeeded()] = seriesResult.slug } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         val seriesDetails = seriesResult.toSManga(apiUrl, coverPath, slugStrategy) | ||||||
| 
 | 
 | ||||||
|         return seriesDetails.apply { |         return seriesDetails.apply { | ||||||
|             status = status.takeUnless { it == SManga.UNKNOWN } |             status = status.takeUnless { it == SManga.UNKNOWN } | ||||||
| @ -323,21 +399,39 @@ abstract class HeanCms( | |||||||
|             return result.seasons.orEmpty() |             return result.seasons.orEmpty() | ||||||
|                 .flatMap { it.chapters.orEmpty() } |                 .flatMap { it.chapters.orEmpty() } | ||||||
|                 .filterNot { it.price == 1 } |                 .filterNot { it.price == 1 } | ||||||
|                 .map { it.toSChapter(result.slug, dateFormat) } |                 .map { it.toSChapter(result.slug, dateFormat, slugStrategy) } | ||||||
|                 .filter { it.date_upload <= currentTimestamp } |                 .filter { it.date_upload <= currentTimestamp } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return result.chapters.orEmpty() |         return result.chapters.orEmpty() | ||||||
|             .filterNot { it.price == 1 } |             .filterNot { it.price == 1 } | ||||||
|             .map { it.toSChapter(result.slug, dateFormat) } |             .map { it.toSChapter(result.slug, dateFormat, slugStrategy) } | ||||||
|             .filter { it.date_upload <= currentTimestamp } |             .filter { it.date_upload <= currentTimestamp } | ||||||
|             .reversed() |             .reversed() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override fun getChapterUrl(chapter: SChapter): String = baseUrl + chapter.url |     override fun getChapterUrl(chapter: SChapter): String { | ||||||
|  |         if (slugStrategy == SlugStrategy.NONE) return baseUrl + chapter.url | ||||||
|  | 
 | ||||||
|  |         val seriesSlug = chapter.url | ||||||
|  |             .substringAfter("/series/") | ||||||
|  |             .substringBefore("/") | ||||||
|  |             .toPermSlugIfNeeded() | ||||||
|  | 
 | ||||||
|  |         val currentSlug = preferences.slugMap[seriesSlug] ?: seriesSlug | ||||||
|  |         val chapterUrl = chapter.url.replaceFirst(seriesSlug, currentSlug) | ||||||
|  | 
 | ||||||
|  |         return baseUrl + chapterUrl | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     override fun pageListRequest(chapter: SChapter): Request { |     override fun pageListRequest(chapter: SChapter): Request { | ||||||
|         if (useNewQueryEndpoint) { |         if (useNewQueryEndpoint) { | ||||||
|  |             if (slugStrategy != SlugStrategy.NONE) { | ||||||
|  |                 val seriesPermSlug = chapter.url.substringAfter("/series/").substringBefore("/") | ||||||
|  |                 val seriesSlug = preferences.slugMap[seriesPermSlug] ?: seriesPermSlug | ||||||
|  |                 val chapterUrl = chapter.url.replaceFirst(seriesPermSlug, seriesSlug) | ||||||
|  |                 return GET(baseUrl + chapterUrl, headers) | ||||||
|  |             } | ||||||
|             return GET(baseUrl + chapter.url, headers) |             return GET(baseUrl + chapter.url, headers) | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -389,7 +483,7 @@ abstract class HeanCms( | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     protected open fun fetchAllTitles() { |     protected open fun fetchAllTitles() { | ||||||
|         if (!seriesSlugMap.isNullOrEmpty() || !fetchAllTitles) { |         if (!seriesSlugMap.isNullOrEmpty() || slugStrategy != SlugStrategy.FETCH_ALL) { | ||||||
|             return |             return | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -418,6 +512,8 @@ abstract class HeanCms( | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         seriesSlugMap = result.getOrNull() |         seriesSlugMap = result.getOrNull() | ||||||
|  |         preferences.slugMap = preferences.slugMap.toMutableMap() | ||||||
|  |             .also { it.putAll(seriesSlugMap.orEmpty().mapValues { (_, v) -> v.slug }) } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     protected open fun allTitlesRequest(page: Int): Request { |     protected open fun allTitlesRequest(page: Int): Request { | ||||||
| @ -468,8 +564,21 @@ abstract class HeanCms( | |||||||
|      */ |      */ | ||||||
|     data class HeanCmsTitle(val slug: String, val thumbnailFileName: String, val status: Int) |     data class HeanCmsTitle(val slug: String, val thumbnailFileName: String, val status: Int) | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Used to specify the strategy to use when fetching the slug for a manga. | ||||||
|  |      * This is needed because some sources change the slug periodically. | ||||||
|  |      * [NONE]: Use series_slug without changes. | ||||||
|  |      * [ID]: Use series_id to fetch the slug from the API. | ||||||
|  |      * IMPORTANT: [ID] is only available in the new query endpoint. | ||||||
|  |      * [FETCH_ALL]: Convert the slug to a permanent slug by removing the timestamp. | ||||||
|  |      * At extension start, all the slugs are fetched and stored in a map. | ||||||
|  |      */ | ||||||
|  |     enum class SlugStrategy { | ||||||
|  |         NONE, ID, FETCH_ALL | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private fun String.toPermSlugIfNeeded(): String { |     private fun String.toPermSlugIfNeeded(): String { | ||||||
|         return if (fetchAllTitles) { |         return if (slugStrategy != SlugStrategy.NONE) { | ||||||
|             this.replace(TIMESTAMP_REGEX, "") |             this.replace(TIMESTAMP_REGEX, "") | ||||||
|         } else { |         } else { | ||||||
|             this |             this | ||||||
| @ -514,6 +623,18 @@ abstract class HeanCms( | |||||||
|     protected inline fun <reified R> List<*>.firstInstanceOrNull(): R? = |     protected inline fun <reified R> List<*>.firstInstanceOrNull(): R? = | ||||||
|         filterIsInstance<R>().firstOrNull() |         filterIsInstance<R>().firstOrNull() | ||||||
| 
 | 
 | ||||||
|  |     protected var SharedPreferences.slugMap: MutableMap<String, String> | ||||||
|  |         get() { | ||||||
|  |             val jsonMap = getString(PREF_URL_MAP_SLUG, "{}")!! | ||||||
|  |             val slugMap = runCatching { json.decodeFromString<Map<String, String>>(jsonMap) } | ||||||
|  |             return slugMap.getOrNull()?.toMutableMap() ?: mutableMapOf() | ||||||
|  |         } | ||||||
|  |         set(newSlugMap) { | ||||||
|  |             edit() | ||||||
|  |                 .putString(PREF_URL_MAP_SLUG, json.encodeToString(newSlugMap)) | ||||||
|  |                 .commit() | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|     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, */*" | ||||||
| @ -525,5 +646,7 @@ abstract class HeanCms( | |||||||
|         private const val PER_PAGE_MANGA_TITLES = 10000 |         private const val PER_PAGE_MANGA_TITLES = 10000 | ||||||
| 
 | 
 | ||||||
|         const val SEARCH_PREFIX = "slug:" |         const val SEARCH_PREFIX = "slug:" | ||||||
|  | 
 | ||||||
|  |         private const val PREF_URL_MAP_SLUG = "pref_url_map" | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| package eu.kanade.tachiyomi.multisrc.heancms | package eu.kanade.tachiyomi.multisrc.heancms | ||||||
| 
 | 
 | ||||||
|  | import eu.kanade.tachiyomi.multisrc.heancms.HeanCms.SlugStrategy | ||||||
| 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 | ||||||
| @ -36,9 +37,9 @@ data class HeanCmsSearchDto( | |||||||
|         apiUrl: String, |         apiUrl: String, | ||||||
|         coverPath: String, |         coverPath: String, | ||||||
|         slugMap: Map<String, HeanCms.HeanCmsTitle>, |         slugMap: Map<String, HeanCms.HeanCmsTitle>, | ||||||
|         fetchAllTiles: Boolean, |         slugStrategy: SlugStrategy, | ||||||
|     ): SManga = SManga.create().apply { |     ): SManga = SManga.create().apply { | ||||||
|         val slugOnly = slug.toPermSlugIfNeeded(fetchAllTiles) |         val slugOnly = slug.toPermSlugIfNeeded(slugStrategy) | ||||||
|         val thumbnailFileName = slugMap[slugOnly]?.thumbnailFileName |         val thumbnailFileName = slugMap[slugOnly]?.thumbnailFileName | ||||||
|         title = this@HeanCmsSearchDto.title |         title = this@HeanCmsSearchDto.title | ||||||
|         thumbnail_url = thumbnail?.toAbsoluteThumbnailUrl(apiUrl, coverPath) |         thumbnail_url = thumbnail?.toAbsoluteThumbnailUrl(apiUrl, coverPath) | ||||||
| @ -66,10 +67,10 @@ data class HeanCmsSeriesDto( | |||||||
|     fun toSManga( |     fun toSManga( | ||||||
|         apiUrl: String, |         apiUrl: String, | ||||||
|         coverPath: String, |         coverPath: String, | ||||||
|         fetchAllTiles: Boolean, |         slugStrategy: SlugStrategy, | ||||||
|     ): 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 slugOnly = slug.toPermSlugIfNeeded(fetchAllTiles) |         val slugOnly = slug.toPermSlugIfNeeded(slugStrategy) | ||||||
| 
 | 
 | ||||||
|         title = this@HeanCmsSeriesDto.title |         title = this@HeanCmsSeriesDto.title | ||||||
|         author = this@HeanCmsSeriesDto.author?.trim() |         author = this@HeanCmsSeriesDto.author?.trim() | ||||||
| @ -83,7 +84,11 @@ data class HeanCmsSeriesDto( | |||||||
|         thumbnail_url = thumbnail.ifEmpty { null } |         thumbnail_url = thumbnail.ifEmpty { null } | ||||||
|             ?.toAbsoluteThumbnailUrl(apiUrl, coverPath) |             ?.toAbsoluteThumbnailUrl(apiUrl, coverPath) | ||||||
|         status = this@HeanCmsSeriesDto.status?.toStatus() ?: SManga.UNKNOWN |         status = this@HeanCmsSeriesDto.status?.toStatus() ?: SManga.UNKNOWN | ||||||
|         url = "/series/$slugOnly" |         url = if (slugStrategy != SlugStrategy.NONE) { | ||||||
|  |             "/series/$slugOnly#$id" | ||||||
|  |         } else { | ||||||
|  |             "/series/$slug" | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -105,11 +110,16 @@ data class HeanCmsChapterDto( | |||||||
|     @SerialName("created_at") val createdAt: String, |     @SerialName("created_at") val createdAt: String, | ||||||
|     val price: Int? = null, |     val price: Int? = null, | ||||||
| ) { | ) { | ||||||
|     fun toSChapter(seriesSlug: String, dateFormat: SimpleDateFormat): SChapter = SChapter.create().apply { |     fun toSChapter( | ||||||
|  |         seriesSlug: String, | ||||||
|  |         dateFormat: SimpleDateFormat, | ||||||
|  |         slugStrategy: SlugStrategy, | ||||||
|  |     ): SChapter = SChapter.create().apply { | ||||||
|  |         val seriesSlugOnly = seriesSlug.toPermSlugIfNeeded(slugStrategy) | ||||||
|         name = this@HeanCmsChapterDto.name.trim() |         name = this@HeanCmsChapterDto.name.trim() | ||||||
|         date_upload = runCatching { dateFormat.parse(createdAt)?.time } |         date_upload = runCatching { dateFormat.parse(createdAt)?.time } | ||||||
|             .getOrNull() ?: 0L |             .getOrNull() ?: 0L | ||||||
|         url = "/series/$seriesSlug/$slug#$id" |         url = "/series/$seriesSlugOnly/$slug#$id" | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -140,8 +150,8 @@ private fun String.toAbsoluteThumbnailUrl(apiUrl: String, coverPath: String): St | |||||||
|     return if (startsWith("https://")) this else "$apiUrl/$coverPath$this" |     return if (startsWith("https://")) this else "$apiUrl/$coverPath$this" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| private fun String.toPermSlugIfNeeded(fetchAllTitles: Boolean): String { | private fun String.toPermSlugIfNeeded(slugStrategy: SlugStrategy): String { | ||||||
|     return if (fetchAllTitles) { |     return if (slugStrategy != SlugStrategy.NONE) { | ||||||
|         this.replace(HeanCms.TIMESTAMP_REGEX, "") |         this.replace(HeanCms.TIMESTAMP_REGEX, "") | ||||||
|     } else { |     } else { | ||||||
|         this |         this | ||||||
|  | |||||||
| @ -9,13 +9,13 @@ class HeanCmsGenerator : ThemeSourceGenerator { | |||||||
| 
 | 
 | ||||||
|     override val themeClass = "HeanCms" |     override val themeClass = "HeanCms" | ||||||
| 
 | 
 | ||||||
|     override val baseVersionCode: Int = 17 |     override val baseVersionCode: Int = 18 | ||||||
| 
 | 
 | ||||||
|     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), | ||||||
|         SingleLang("Omega Scans", "https://omegascans.org", "en", isNsfw = true, overrideVersionCode = 17), |         SingleLang("Omega Scans", "https://omegascans.org", "en", isNsfw = true, overrideVersionCode = 17), | ||||||
|         SingleLang("Reaper Scans", "https://reaperscans.net", "pt-BR", overrideVersionCode = 36), |         SingleLang("Reaper Scans", "https://reaperscans.net", "pt-BR", overrideVersionCode = 36), | ||||||
|         SingleLang("YugenMangas", "https://yugenmangas.lat", "es", isNsfw = true, overrideVersionCode = 7), |         SingleLang("YugenMangas", "https://yugenmangas.net", "es", isNsfw = true, overrideVersionCode = 7), | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     companion object { |     companion object { | ||||||
|  | |||||||
| @ -88,6 +88,12 @@ class HeanCmsIntl(lang: String) { | |||||||
|                 "to $sourceName to update the URL." |                 "to $sourceName to update the URL." | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     val idNotFoundError: String = when (availableLang) { | ||||||
|  |         BRAZILIAN_PORTUGUESE -> "Falha ao obter o ID do slug: " | ||||||
|  |         SPANISH -> "No se pudo encontrar el ID para: " | ||||||
|  |         else -> "Failed to get the ID for slug: " | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     companion object { |     companion object { | ||||||
|         const val BRAZILIAN_PORTUGUESE = "pt-BR" |         const val BRAZILIAN_PORTUGUESE = "pt-BR" | ||||||
|         const val ENGLISH = "en" |         const val ENGLISH = "en" | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 bapeey
						bapeey