ReaderFront: translate genres (#9756)
This commit is contained in:
parent
7b96c41fed
commit
6c8a44f56a
|
@ -4,13 +4,10 @@ import eu.kanade.tachiyomi.multisrc.readerfront.ReaderFront
|
||||||
import eu.kanade.tachiyomi.source.SourceFactory
|
import eu.kanade.tachiyomi.source.SourceFactory
|
||||||
|
|
||||||
class RavensScansFactory : SourceFactory {
|
class RavensScansFactory : SourceFactory {
|
||||||
override fun createSources() = listOf(
|
override fun createSources() = listOf(RavensScans("es"), RavensScans("en"))
|
||||||
RavensScans("es", 1),
|
|
||||||
RavensScans("en", 2)
|
|
||||||
)
|
|
||||||
|
|
||||||
class RavensScans(override val lang: String, override val langId: Int) :
|
class RavensScans(lang: String) :
|
||||||
ReaderFront("Ravens Scans", "https://ravens-scans.com/", lang, langId) {
|
ReaderFront("Ravens Scans", "https://ravens-scans.com/", lang) {
|
||||||
override fun getImageCDN(path: String, width: Int) =
|
override fun getImageCDN(path: String, width: Int) =
|
||||||
"https://i${(0..2).random()}.wp.com/img-cdn1.ravens-scans.com" +
|
"https://i${(0..2).random()}.wp.com/img-cdn1.ravens-scans.com" +
|
||||||
"$path?strip=all&quality=100&w=$width"
|
"$path?strip=all&quality=100&w=$width"
|
||||||
|
|
|
@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.extension.en.scyllascans
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.multisrc.readerfront.ReaderFront
|
import eu.kanade.tachiyomi.multisrc.readerfront.ReaderFront
|
||||||
|
|
||||||
class ScyllaScans : ReaderFront("Scylla Scans", "https://scyllascans.org/", "en", 2) {
|
class ScyllaScans : ReaderFront("Scylla Scans", "https://scyllascans.org/", "en") {
|
||||||
override fun getImageCDN(path: String, width: Int) =
|
override fun getImageCDN(path: String, width: Int) =
|
||||||
"https://i${(0..2).random()}.wp.com/api.scyllascans.org" +
|
"https://i${(0..2).random()}.wp.com/api.scyllascans.org" +
|
||||||
"$path?strip=all&quality=100&w=$width"
|
"$path?strip=all&quality=100&w=$width"
|
||||||
|
|
|
@ -18,30 +18,31 @@ import okhttp3.Response
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
abstract class ReaderFront(
|
abstract class ReaderFront(
|
||||||
override val name: String,
|
final override val name: String,
|
||||||
override val baseUrl: String,
|
final override val baseUrl: String,
|
||||||
override val lang: String,
|
final override val lang: String
|
||||||
open val langId: Int
|
|
||||||
) : HttpSource() {
|
) : HttpSource() {
|
||||||
override val supportsLatest = true
|
override val supportsLatest = true
|
||||||
|
|
||||||
private val json by injectLazy<Json>()
|
private val json by injectLazy<Json>()
|
||||||
|
|
||||||
open val apiUrl by lazy { baseUrl.replaceFirst("://", "://api.") }
|
private val i18n = ReaderFrontI18N(lang)
|
||||||
|
|
||||||
|
open val apiUrl = baseUrl.replaceFirst("://", "://api.")
|
||||||
|
|
||||||
abstract fun getImageCDN(path: String, width: Int = 350): String
|
abstract fun getImageCDN(path: String, width: Int = 350): String
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int) =
|
override fun latestUpdatesRequest(page: Int) =
|
||||||
GET("$apiUrl?query=${works(langId, "updatedAt", "DESC", page, 12)}", headers)
|
GET("$apiUrl?query=${works(i18n.id, "updatedAt", "DESC", page, 12)}", headers)
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int) =
|
override fun popularMangaRequest(page: Int) =
|
||||||
GET("$apiUrl?query=${works(langId, "stub", "ASC", page, 120)}", headers)
|
GET("$apiUrl?query=${works(i18n.id, "stub", "ASC", page, 120)}", headers)
|
||||||
|
|
||||||
override fun mangaDetailsRequest(manga: SManga) =
|
override fun mangaDetailsRequest(manga: SManga) =
|
||||||
GET("$baseUrl/work/$lang/${manga.url}", headers)
|
GET("$baseUrl/work/$lang/${manga.url}", headers)
|
||||||
|
|
||||||
override fun chapterListRequest(manga: SManga) =
|
override fun chapterListRequest(manga: SManga) =
|
||||||
GET("$apiUrl?query=${chaptersByWork(langId, manga.url)}", headers)
|
GET("$apiUrl?query=${chaptersByWork(i18n.id, manga.url)}", headers)
|
||||||
|
|
||||||
override fun pageListRequest(chapter: SChapter) =
|
override fun pageListRequest(chapter: SChapter) =
|
||||||
GET("$apiUrl?query=${chapterById(chapter.url.toInt())}", headers)
|
GET("$apiUrl?query=${chapterById(chapter.url.toInt())}", headers)
|
||||||
|
@ -72,7 +73,7 @@ abstract class ReaderFront(
|
||||||
append(it.demographic_name!!)
|
append(it.demographic_name!!)
|
||||||
if (it.genres!!.isNotEmpty()) {
|
if (it.genres!!.isNotEmpty()) {
|
||||||
append(", ")
|
append(", ")
|
||||||
it.genres.joinTo(this) { it.genre }
|
it.genres.joinTo(this, transform = i18n::get)
|
||||||
}
|
}
|
||||||
append(", ")
|
append(", ")
|
||||||
append(it.type!!)
|
append(it.type!!)
|
||||||
|
@ -88,7 +89,7 @@ abstract class ReaderFront(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun chapterListParse(response: Response) =
|
override fun chapterListParse(response: Response) =
|
||||||
response.parse<List<Chapter>>("chaptersByWork").map {
|
response.parse<List<Release>>("chaptersByWork").map {
|
||||||
SChapter.create().apply {
|
SChapter.create().apply {
|
||||||
url = it.id.toString()
|
url = it.id.toString()
|
||||||
name = it.toString()
|
name = it.toString()
|
||||||
|
@ -98,14 +99,14 @@ abstract class ReaderFront(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pageListParse(response: Response) =
|
override fun pageListParse(response: Response) =
|
||||||
response.parse<PageList>("chapterById").let {
|
response.parse<Chapter>("chapterById").let {
|
||||||
it.mapIndexed { idx, page ->
|
it.mapIndexed { idx, page ->
|
||||||
Page(idx, "", getImageCDN(it.path(page), page.width))
|
Page(idx, "", getImageCDN(it.path(page), page.width))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun fetchMangaDetails(manga: SManga) =
|
override fun fetchMangaDetails(manga: SManga) =
|
||||||
GET("$apiUrl?query=${work(langId, manga.url)}", headers).let {
|
GET("$apiUrl?query=${work(i18n.id, manga.url)}", headers).let {
|
||||||
client.newCall(it).asObservableSuccess().map(::mangaDetailsParse)
|
client.newCall(it).asObservableSuccess().map(::mangaDetailsParse)
|
||||||
}!!
|
}!!
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,8 @@ data class Work(
|
||||||
val status_name: String? = null,
|
val status_name: String? = null,
|
||||||
val description: String? = null,
|
val description: String? = null,
|
||||||
val demographic_name: String? = null,
|
val demographic_name: String? = null,
|
||||||
val genres: List<Name>? = null,
|
val genres: List<NameWrapper>? = null,
|
||||||
private val people_works: List<People>? = null
|
private val people_works: List<PeopleWorks>? = null
|
||||||
) {
|
) {
|
||||||
@Transient
|
@Transient
|
||||||
val authors = people_works?.filter { it.role == 1 }
|
val authors = people_works?.filter { it.role == 1 }
|
||||||
|
@ -30,7 +30,7 @@ data class Work(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Chapter(
|
data class Release(
|
||||||
val id: Int,
|
val id: Int,
|
||||||
private val chapter: Int,
|
private val chapter: Int,
|
||||||
private val subchapter: Int,
|
private val subchapter: Int,
|
||||||
|
@ -45,21 +45,27 @@ data class Chapter(
|
||||||
val timestamp = dateFormat.parse(releaseDate)?.time ?: 0L
|
val timestamp = dateFormat.parse(releaseDate)?.time ?: 0L
|
||||||
|
|
||||||
override fun toString() = buildString {
|
override fun toString() = buildString {
|
||||||
if (volume > 0) append("Volume $volume ")
|
if (number > 0) {
|
||||||
if (number > 0) append("Chapter ${decimalFormat.format(number)}: ")
|
if (volume > 0) append("Volume $volume ")
|
||||||
|
append("Chapter ${decimalFormat.format(number)}")
|
||||||
|
if (name.isNotEmpty()) append(": ")
|
||||||
|
}
|
||||||
append(name)
|
append(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private const val ISO_DATE = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
|
||||||
|
|
||||||
private val decimalFormat = DecimalFormat("#.##")
|
private val decimalFormat = DecimalFormat("#.##")
|
||||||
private val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ROOT)
|
|
||||||
|
private val dateFormat = SimpleDateFormat(ISO_DATE, Locale.ROOT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class PageList(
|
data class Chapter(
|
||||||
private val uniqid: String,
|
private val uniqid: String,
|
||||||
private val work: Uniqid,
|
private val work: UniqidWrapper,
|
||||||
private val pages: List<Page>
|
private val pages: List<Page>
|
||||||
) : Iterable<Page> by pages {
|
) : Iterable<Page> by pages {
|
||||||
/** Get the path of a page in the list. */
|
/** Get the path of a page in the list. */
|
||||||
|
@ -74,19 +80,16 @@ data class Page(private val filename: String, val width: Int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Uniqid(private val uniqid: String) {
|
data class UniqidWrapper(private val uniqid: String) {
|
||||||
override fun toString() = uniqid
|
override fun toString() = uniqid
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class People(val role: Int, private val people: Name) {
|
data class PeopleWorks(val role: Int, private val people: NameWrapper) {
|
||||||
override fun toString() = people.toString()
|
override fun toString() = people.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Name(private val name: String) {
|
data class NameWrapper(private val name: String) {
|
||||||
val genre: String // TODO: replace with a localized genre map
|
|
||||||
get() = name.split('_').joinToString(" ") { it.capitalize(Locale.ROOT) }
|
|
||||||
|
|
||||||
override fun toString() = name
|
override fun toString() = name
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ class ReaderFrontGenerator : ThemeSourceGenerator {
|
||||||
|
|
||||||
override val themeClass = "ReaderFront"
|
override val themeClass = "ReaderFront"
|
||||||
|
|
||||||
override val baseVersionCode = 1
|
override val baseVersionCode = 2
|
||||||
|
|
||||||
override val sources = listOf(
|
override val sources = listOf(
|
||||||
MultiLang("Ravens Scans", "https://ravens-scans.com/", listOf("es", "en"), true),
|
MultiLang("Ravens Scans", "https://ravens-scans.com/", listOf("es", "en"), true),
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
package eu.kanade.tachiyomi.multisrc.readerfront
|
||||||
|
|
||||||
|
sealed class ReaderFrontI18N(val id: Int) {
|
||||||
|
protected abstract val genres: Map<String, String>
|
||||||
|
|
||||||
|
operator fun get(name: NameWrapper) = genres[name.toString()]!!
|
||||||
|
|
||||||
|
object SPANISH : ReaderFrontI18N(1) {
|
||||||
|
override val genres = mapOf(
|
||||||
|
"action" to "Acción",
|
||||||
|
"adult" to "Adulto",
|
||||||
|
"adventure" to "Aventura",
|
||||||
|
"comedy" to "Comedia",
|
||||||
|
"doujinshi" to "Doujinshi",
|
||||||
|
"drama" to "Drama",
|
||||||
|
"ecchi" to "Ecchi",
|
||||||
|
"fantasy" to "Fantasía",
|
||||||
|
"gender_bender" to "Cambio de Sexo",
|
||||||
|
"harem" to "Harem",
|
||||||
|
"hentai" to "Hentai",
|
||||||
|
"historical" to "Histórico",
|
||||||
|
"horror" to "Horror",
|
||||||
|
"martial_arts" to "Artes Marciales",
|
||||||
|
"mature" to "Maduro",
|
||||||
|
"mecha" to "Mecha",
|
||||||
|
"mystery" to "Misterio",
|
||||||
|
"psychological" to "Psicologico",
|
||||||
|
"romance" to "Romance",
|
||||||
|
"school_life" to "Vida Escolar",
|
||||||
|
"sci_fi" to "Ciencia Ficción",
|
||||||
|
"slice_of_life" to "Recuentos de la Vida",
|
||||||
|
"smut" to "Smut",
|
||||||
|
"sports" to "Deportes",
|
||||||
|
"supernatural" to "Sobrenatural",
|
||||||
|
"tragedy" to "Tragédia",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
object ENGLISH : ReaderFrontI18N(2) {
|
||||||
|
override val genres = mapOf(
|
||||||
|
"action" to "Action",
|
||||||
|
"adult" to "Adult",
|
||||||
|
"adventure" to "Adventure",
|
||||||
|
"comedy" to "Comedy",
|
||||||
|
"doujinshi" to "Doujinshi",
|
||||||
|
"drama" to "Drama",
|
||||||
|
"ecchi" to "Ecchi",
|
||||||
|
"fantasy" to "Fantasy",
|
||||||
|
"gender_bender" to "Gender Bender",
|
||||||
|
"harem" to "Harem",
|
||||||
|
"hentai" to "Hentai",
|
||||||
|
"historical" to "Historical",
|
||||||
|
"horror" to "Horror",
|
||||||
|
"martial_arts" to "Martial Arts",
|
||||||
|
"mature" to "Mature",
|
||||||
|
"mecha" to "Mecha",
|
||||||
|
"mystery" to "Mystery",
|
||||||
|
"psychological" to "Psychological",
|
||||||
|
"romance" to "Romance",
|
||||||
|
"school_life" to "School Life",
|
||||||
|
"sci_fi" to "Sci-fi",
|
||||||
|
"slice_of_life" to "Slice Of Life",
|
||||||
|
"smut" to "Smut",
|
||||||
|
"sports" to "Sports",
|
||||||
|
"supernatural" to "Supernatural",
|
||||||
|
"tragedy" to "Tragedy",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
operator fun invoke(lang: String) = when (lang) {
|
||||||
|
"es" -> SPANISH
|
||||||
|
"en" -> ENGLISH
|
||||||
|
else -> error("Unsupported language: $lang")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue