Kagane: Fix MissingFieldException Error (#10981)
* fix dto and small fixes * bump * fix authors * remove unused code and fix review comment * fix lint * fix lintx2 :(
This commit is contained in:
parent
ccbde23c1f
commit
4ac7d3559c
@ -1,7 +1,7 @@
|
|||||||
ext {
|
ext {
|
||||||
extName = 'Kagane'
|
extName = 'Kagane'
|
||||||
extClass = '.Kagane'
|
extClass = '.Kagane'
|
||||||
extVersionCode = 3
|
extVersionCode = 4
|
||||||
isNsfw = true
|
isNsfw = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -31,84 +31,68 @@ class SearchDto(
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class DetailsDto(
|
class DetailsDto(
|
||||||
val data: Data,
|
val source: String,
|
||||||
|
val authors: List<String>,
|
||||||
|
val status: String,
|
||||||
|
val summary: String?,
|
||||||
|
val genres: List<String>,
|
||||||
|
@SerialName("alternate_titles")
|
||||||
|
val alternateTitles: List<AlternateTitles>,
|
||||||
) {
|
) {
|
||||||
@Serializable
|
@Serializable
|
||||||
class Data(
|
class AlternateTitles(
|
||||||
val metadata: Metadata,
|
val title: String,
|
||||||
val source: String,
|
)
|
||||||
) {
|
|
||||||
@Serializable
|
fun toSManga(): SManga = SManga.create().apply {
|
||||||
class Metadata(
|
val desc = StringBuilder()
|
||||||
val genres: List<String>,
|
if (!summary.isNullOrBlank()) desc.append(summary + "\n\n")
|
||||||
val status: String,
|
desc.append("Source: ").append(source + "\n\n")
|
||||||
val summary: String,
|
|
||||||
val alternateTitles: List<Title>,
|
if (alternateTitles.isNotEmpty()) {
|
||||||
) {
|
desc.append("Associated Name(s):\n\n")
|
||||||
@Serializable
|
alternateTitles.forEach { desc.append("• ${it.title}\n") }
|
||||||
class Title(
|
|
||||||
val title: String,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toSManga(): SManga = SManga.create().apply {
|
author = authors.joinToString()
|
||||||
val summary = StringBuilder()
|
description = desc.toString()
|
||||||
summary.append(metadata.summary)
|
genre = genres.joinToString()
|
||||||
.append("\n\n")
|
status = this@DetailsDto.status.toStatus()
|
||||||
.append("Source: ")
|
}
|
||||||
.append(source)
|
|
||||||
|
|
||||||
if (metadata.alternateTitles.isNotEmpty()) {
|
private fun String.toStatus(): Int {
|
||||||
summary.append("\n\nAssociated Name(s):")
|
return when (this) {
|
||||||
metadata.alternateTitles.forEach { summary.append("\n").append("• ${it.title}") }
|
"ONGOING" -> SManga.ONGOING
|
||||||
}
|
"ENDED" -> SManga.COMPLETED
|
||||||
|
else -> SManga.UNKNOWN
|
||||||
description = summary.toString()
|
|
||||||
genre = metadata.genres.joinToString()
|
|
||||||
status = metadata.status.toStatus()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun String.toStatus(): Int {
|
|
||||||
return when (this) {
|
|
||||||
"ONGOING" -> SManga.ONGOING
|
|
||||||
else -> SManga.COMPLETED
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class ChapterDto(
|
class ChapterDto(
|
||||||
val data: Data,
|
val content: List<Book>,
|
||||||
) {
|
) {
|
||||||
@Serializable
|
@Serializable
|
||||||
class Data(
|
class Book(
|
||||||
val content: List<Book>,
|
val id: String,
|
||||||
|
@SerialName("series_id")
|
||||||
|
val seriesId: String,
|
||||||
|
val title: String,
|
||||||
|
@SerialName("release_date")
|
||||||
|
val releaseDate: String?,
|
||||||
|
@SerialName("pages_count")
|
||||||
|
val pagesCount: Int,
|
||||||
) {
|
) {
|
||||||
@Serializable
|
fun toSChapter(): SChapter = SChapter.create().apply {
|
||||||
class Book(
|
url = "$seriesId;$id;$pagesCount"
|
||||||
val metadata: Metadata,
|
name = title
|
||||||
val id: String,
|
date_upload = dateFormat.tryParse(releaseDate)
|
||||||
val seriesId: String,
|
|
||||||
val created: String,
|
|
||||||
) {
|
|
||||||
@Serializable
|
|
||||||
class Metadata(
|
|
||||||
val title: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
fun toSChapter(): SChapter = SChapter.create().apply {
|
|
||||||
url = "$seriesId;$id"
|
|
||||||
name = metadata.title
|
|
||||||
date_upload = dateFormat.tryParse(created)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val dateFormat by lazy {
|
private val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH)
|
||||||
SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,19 +101,3 @@ class ChallengeDto(
|
|||||||
@SerialName("access_token")
|
@SerialName("access_token")
|
||||||
val accessToken: String,
|
val accessToken: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
|
||||||
class PagesCountDto(
|
|
||||||
val data: Data,
|
|
||||||
) {
|
|
||||||
@Serializable
|
|
||||||
class Data(
|
|
||||||
val media: PagesCount,
|
|
||||||
) {
|
|
||||||
@Serializable
|
|
||||||
class PagesCount(
|
|
||||||
@SerialName("pagesCount")
|
|
||||||
val pagesCount: Int,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -144,7 +144,7 @@ class Kagane : HttpSource(), ConfigurableSource {
|
|||||||
// =============================== Latest ===============================
|
// =============================== Latest ===============================
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int) =
|
override fun latestUpdatesRequest(page: Int) =
|
||||||
searchMangaRequest(page, "", FilterList(SortFilter(1)))
|
searchMangaRequest(page, "", FilterList(SortFilter(2)))
|
||||||
|
|
||||||
override fun latestUpdatesParse(response: Response) = searchMangaParse(response)
|
override fun latestUpdatesParse(response: Response) = searchMangaParse(response)
|
||||||
|
|
||||||
@ -188,7 +188,7 @@ class Kagane : HttpSource(), ConfigurableSource {
|
|||||||
|
|
||||||
override fun mangaDetailsParse(response: Response): SManga {
|
override fun mangaDetailsParse(response: Response): SManga {
|
||||||
val dto = response.parseAs<DetailsDto>()
|
val dto = response.parseAs<DetailsDto>()
|
||||||
return dto.data.toSManga()
|
return dto.toSManga()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mangaDetailsRequest(manga: SManga): Request {
|
override fun mangaDetailsRequest(manga: SManga): Request {
|
||||||
@ -203,7 +203,7 @@ class Kagane : HttpSource(), ConfigurableSource {
|
|||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
val dto = response.parseAs<ChapterDto>()
|
val dto = response.parseAs<ChapterDto>()
|
||||||
return dto.data.content.map { it.toSChapter() }.reversed()
|
return dto.content.map { it.toSChapter() }.reversed()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun chapterListRequest(manga: SManga): Request {
|
override fun chapterListRequest(manga: SManga): Request {
|
||||||
@ -224,15 +224,16 @@ class Kagane : HttpSource(), ConfigurableSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
|
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
|
||||||
var (seriesId, chapterId) = chapter.url.split(";")
|
if (chapter.url.count { it == ';' } == 2) throw Exception("Chapter url error, please refresh chapter list.")
|
||||||
|
var (seriesId, chapterId, pageCount) = chapter.url.split(";")
|
||||||
|
|
||||||
val challengeResp = getChallengeResponse(seriesId, chapterId)
|
val challengeResp = getChallengeResponse(seriesId, chapterId)
|
||||||
accessToken = challengeResp.accessToken
|
accessToken = challengeResp.accessToken
|
||||||
val pageCount = getPageCountResponse(seriesId, chapterId)
|
|
||||||
if (preferences.dataSaver) {
|
if (preferences.dataSaver) {
|
||||||
chapterId = chapterId + "_ds"
|
chapterId = chapterId + "_ds"
|
||||||
}
|
}
|
||||||
val pages = (0 until pageCount).map { page ->
|
|
||||||
|
val pages = (0 until pageCount.toInt()).map { page ->
|
||||||
val pageUrl = "$apiUrl/api/v1/books".toHttpUrl().newBuilder().apply {
|
val pageUrl = "$apiUrl/api/v1/books".toHttpUrl().newBuilder().apply {
|
||||||
addPathSegment(seriesId)
|
addPathSegment(seriesId)
|
||||||
addPathSegment("file")
|
addPathSegment("file")
|
||||||
@ -363,15 +364,6 @@ class Kagane : HttpSource(), ConfigurableSource {
|
|||||||
.parseAs<ChallengeDto>()
|
.parseAs<ChallengeDto>()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPageCountResponse(seriesId: String, chapterId: String): Int {
|
|
||||||
val challengeUrl = "$apiUrl/api/v1/books/$seriesId/metadata/$chapterId"
|
|
||||||
|
|
||||||
val dto = client.newCall(GET(challengeUrl, apiHeaders)).execute()
|
|
||||||
.parseAs<PagesCountDto>()
|
|
||||||
|
|
||||||
return dto.data.media.pagesCount
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun concat(vararg arrays: ByteArray): ByteArray =
|
private fun concat(vararg arrays: ByteArray): ByteArray =
|
||||||
arrays.reduce { acc, bytes -> acc + bytes }
|
arrays.reduce { acc, bytes -> acc + bytes }
|
||||||
|
|
||||||
@ -418,7 +410,7 @@ class Kagane : HttpSource(), ConfigurableSource {
|
|||||||
private val SharedPreferences.showNsfw
|
private val SharedPreferences.showNsfw
|
||||||
get() = this.getBoolean(SHOW_NSFW_KEY, true)
|
get() = this.getBoolean(SHOW_NSFW_KEY, true)
|
||||||
private val SharedPreferences.dataSaver
|
private val SharedPreferences.dataSaver
|
||||||
get() = this.getBoolean(DATA_SAVER, true)
|
get() = this.getBoolean(DATA_SAVER, false)
|
||||||
|
|
||||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||||
SwitchPreferenceCompat(screen.context).apply {
|
SwitchPreferenceCompat(screen.context).apply {
|
||||||
@ -429,7 +421,7 @@ class Kagane : HttpSource(), ConfigurableSource {
|
|||||||
SwitchPreferenceCompat(screen.context).apply {
|
SwitchPreferenceCompat(screen.context).apply {
|
||||||
key = DATA_SAVER
|
key = DATA_SAVER
|
||||||
title = "Data saver"
|
title = "Data saver"
|
||||||
setDefaultValue(true)
|
setDefaultValue(false)
|
||||||
}.let(screen::addPreference)
|
}.let(screen::addPreference)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,7 +429,7 @@ class Kagane : HttpSource(), ConfigurableSource {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val SHOW_NSFW_KEY = "pref_show_nsfw"
|
private const val SHOW_NSFW_KEY = "pref_show_nsfw"
|
||||||
private const val DATA_SAVER = "data_saver"
|
private const val DATA_SAVER = "data_saver_default"
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================= Filters ==============================
|
// ============================= Filters ==============================
|
||||||
@ -449,7 +441,7 @@ class Kagane : HttpSource(), ConfigurableSource {
|
|||||||
class SortFilter(state: Int = 0) : UriPartFilter(
|
class SortFilter(state: Int = 0) : UriPartFilter(
|
||||||
"Sort By",
|
"Sort By",
|
||||||
arrayOf(
|
arrayOf(
|
||||||
Pair("Relevance", ""),
|
Pair("Relevance", "avg_views,desc"),
|
||||||
Pair("Latest", "updated_at"),
|
Pair("Latest", "updated_at"),
|
||||||
Pair("Latest Descending", "updated_at,desc"),
|
Pair("Latest Descending", "updated_at,desc"),
|
||||||
Pair("By Name", "series_name"),
|
Pair("By Name", "series_name"),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user