Gmanga: fix search request and chapter parsing (#10686)
* Gmanga: fix search request and chapter parsing * Ignore HTTP 103 in fetchMangaDetails * [skip ci] attempt fix 'Sequence contains no items' * [skip ci] revert HTTP 103 changes * Improve chapter sort
This commit is contained in:
parent
2a180832e7
commit
77c3906e2c
|
@ -6,7 +6,7 @@ ext {
|
||||||
extName = 'GMANGA'
|
extName = 'GMANGA'
|
||||||
pkgNameSuffix = 'ar.gmanga'
|
pkgNameSuffix = 'ar.gmanga'
|
||||||
extClass = '.Gmanga'
|
extClass = '.Gmanga'
|
||||||
extVersionCode = 8
|
extVersionCode = 9
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
|
@ -2,7 +2,10 @@ package eu.kanade.tachiyomi.extension.ar.gmanga
|
||||||
|
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
import eu.kanade.tachiyomi.extension.ar.gmanga.GmangaPreferences.Companion.PREF_CHAPTER_LISTING
|
import eu.kanade.tachiyomi.extension.ar.gmanga.GmangaPreferences.Companion.PREF_CHAPTER_LISTING
|
||||||
|
import eu.kanade.tachiyomi.extension.ar.gmanga.GmangaPreferences.Companion.PREF_CHAPTER_LISTING_SHOW_ALL
|
||||||
import eu.kanade.tachiyomi.extension.ar.gmanga.GmangaPreferences.Companion.PREF_CHAPTER_LISTING_SHOW_POPULAR
|
import eu.kanade.tachiyomi.extension.ar.gmanga.GmangaPreferences.Companion.PREF_CHAPTER_LISTING_SHOW_POPULAR
|
||||||
|
import eu.kanade.tachiyomi.extension.ar.gmanga.dto.TableDto
|
||||||
|
import eu.kanade.tachiyomi.extension.ar.gmanga.dto.asChapterList
|
||||||
import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
|
import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
|
@ -16,14 +19,12 @@ import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.json.JsonArray
|
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
import kotlinx.serialization.json.contentOrNull
|
import kotlinx.serialization.json.contentOrNull
|
||||||
import kotlinx.serialization.json.float
|
import kotlinx.serialization.json.decodeFromJsonElement
|
||||||
import kotlinx.serialization.json.jsonArray
|
import kotlinx.serialization.json.jsonArray
|
||||||
import kotlinx.serialization.json.jsonObject
|
import kotlinx.serialization.json.jsonObject
|
||||||
import kotlinx.serialization.json.jsonPrimitive
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
import kotlinx.serialization.json.long
|
|
||||||
import okhttp3.Headers
|
import okhttp3.Headers
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
@ -65,41 +66,35 @@ class Gmanga : ConfigurableSource, HttpSource() {
|
||||||
return GET("$baseUrl/api/mangas/$mangaId/releases", headers)
|
return GET("$baseUrl/api/mangas/$mangaId/releases", headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ExperimentalStdlibApi
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
val data = decryptResponse(response)
|
val data = decryptResponse(response)
|
||||||
|
|
||||||
val chapters: List<JsonArray> = buildList {
|
val table = json.decodeFromJsonElement<TableDto>(data)
|
||||||
val allChapters: ArrayList<JsonArray> = ArrayList()
|
val chapterList = table.asChapterList()
|
||||||
data["rows"]!!.jsonArray[0].jsonObject["rows"]!!.jsonArray.forEach { release ->
|
|
||||||
val chapter = data["rows"]!!.jsonArray[2].jsonObject["rows"]!!.jsonArray.filter { it.jsonArray[0] == release.jsonArray[4] }
|
val releases = when (preferences.getString(PREF_CHAPTER_LISTING)) {
|
||||||
allChapters.addAll(chapter.map { it.jsonArray })
|
PREF_CHAPTER_LISTING_SHOW_POPULAR ->
|
||||||
val team = data["rows"]!!.jsonArray[1].jsonObject["rows"]!!.jsonArray.filter { it.jsonArray[0] == release.jsonArray[5] }
|
chapterList.releases
|
||||||
allChapters.addAll(team.map { it.jsonArray })
|
.groupBy { release -> release.chapterizationId }
|
||||||
allChapters.add(release.jsonArray)
|
.mapNotNull { (_, releases) -> releases.maxByOrNull { it.views } }
|
||||||
|
PREF_CHAPTER_LISTING_SHOW_ALL -> chapterList.releases
|
||||||
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
when (preferences.getString(PREF_CHAPTER_LISTING)) {
|
return releases.map { release ->
|
||||||
PREF_CHAPTER_LISTING_SHOW_POPULAR -> addAll(
|
|
||||||
allChapters.groupBy { it.jsonArray[4].jsonPrimitive.float }
|
|
||||||
.map { (_: Float, versions: List<JsonArray>) -> versions.maxByOrNull { it[5].jsonPrimitive.float }!! }
|
|
||||||
)
|
|
||||||
else -> addAll(allChapters)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return chapters.map {
|
|
||||||
SChapter.create().apply {
|
SChapter.create().apply {
|
||||||
chapter_number = it[8].jsonPrimitive.float
|
val chapter = chapterList.chapters.first { it.id == release.chapterizationId }
|
||||||
|
val team = chapterList.teams.firstOrNull { it.id == release.teamId }
|
||||||
|
|
||||||
val chapterName = it[10].jsonPrimitive.content.let { if (it.trim() != "") " - $it" else "" }
|
url = "/r/${release.id}"
|
||||||
|
chapter_number = chapter.chapter
|
||||||
|
date_upload = release.timestamp * 1000
|
||||||
|
scanlator = team?.name
|
||||||
|
|
||||||
url = "/r/${it[0]}"
|
val chapterName = chapter.title.let { if (it.trim() != "") " - $it" else "" }
|
||||||
name = "${chapter_number.let { if (it % 1 > 0) it else it.toInt() }}$chapterName"
|
name = "${chapter_number.let { if (it % 1 > 0) it else it.toInt() }}$chapterName"
|
||||||
date_upload = it[2].jsonPrimitive.long * 1000
|
|
||||||
scanlator = it[13].jsonPrimitive.content
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}.sortedWith(compareBy({ -it.chapter_number }, { -it.date_upload }))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Not used")
|
||||||
|
|
|
@ -39,10 +39,12 @@ class GmangaFilters() {
|
||||||
|
|
||||||
return buildJsonObject {
|
return buildJsonObject {
|
||||||
oneShotFilter.state.first().let {
|
oneShotFilter.state.first().let {
|
||||||
|
putJsonObject("oneshot") {
|
||||||
when {
|
when {
|
||||||
it.isIncluded() -> put("oneshot", true)
|
it.isIncluded() -> put("value", true)
|
||||||
it.isExcluded() -> put("oneshot", false)
|
it.isExcluded() -> put("value", false)
|
||||||
else -> put("oneshot", JsonNull)
|
else -> put("value", JsonNull)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package eu.kanade.tachiyomi.extension.ar.gmanga.dto
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ChapterDto(
|
||||||
|
val id: Int,
|
||||||
|
val chapter: Float,
|
||||||
|
val volume: Int,
|
||||||
|
val title: String,
|
||||||
|
@SerialName("time_stamp") val timestamp: Long,
|
||||||
|
)
|
|
@ -0,0 +1,10 @@
|
||||||
|
package eu.kanade.tachiyomi.extension.ar.gmanga.dto
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ChapterListDto(
|
||||||
|
val releases: List<ReleaseDto>,
|
||||||
|
val teams: List<TeamDto>,
|
||||||
|
val chapters: List<ChapterDto>,
|
||||||
|
)
|
|
@ -0,0 +1,15 @@
|
||||||
|
package eu.kanade.tachiyomi.extension.ar.gmanga.dto
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ReleaseDto(
|
||||||
|
val id: Int,
|
||||||
|
@SerialName("created_at") val createdAt: String,
|
||||||
|
@SerialName("timestamp") val timestamp: Long,
|
||||||
|
val views: Int,
|
||||||
|
@SerialName("chapterization_id") val chapterizationId: Int,
|
||||||
|
@SerialName("team_id") val teamId: Int,
|
||||||
|
val teams: List<Int>,
|
||||||
|
)
|
|
@ -0,0 +1,61 @@
|
||||||
|
package eu.kanade.tachiyomi.extension.ar.gmanga.dto
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
import kotlinx.serialization.json.decodeFromJsonElement
|
||||||
|
import kotlinx.serialization.json.float
|
||||||
|
import kotlinx.serialization.json.int
|
||||||
|
import kotlinx.serialization.json.jsonArray
|
||||||
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
|
import kotlinx.serialization.json.long
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TableDto(
|
||||||
|
val cols: List<String>,
|
||||||
|
val rows: List<JsonElement>,
|
||||||
|
val isCompact: Boolean,
|
||||||
|
val maxLevel: Int,
|
||||||
|
val isArray: Boolean? = null,
|
||||||
|
val isObject: Boolean? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
|
private fun TableDto.get(key: String): TableDto? {
|
||||||
|
isObject ?: return null
|
||||||
|
|
||||||
|
val index = cols.indexOf(key)
|
||||||
|
return json.decodeFromJsonElement(rows[index])
|
||||||
|
}
|
||||||
|
|
||||||
|
fun TableDto.asChapterList() = ChapterListDto(
|
||||||
|
// YOLO
|
||||||
|
get("releases")!!.rows.map {
|
||||||
|
ReleaseDto(
|
||||||
|
it.jsonArray[0].jsonPrimitive.int,
|
||||||
|
it.jsonArray[1].jsonPrimitive.content,
|
||||||
|
it.jsonArray[2].jsonPrimitive.long,
|
||||||
|
it.jsonArray[3].jsonPrimitive.int,
|
||||||
|
it.jsonArray[4].jsonPrimitive.int,
|
||||||
|
it.jsonArray[5].jsonPrimitive.int,
|
||||||
|
it.jsonArray[6].jsonArray.map { it.jsonPrimitive.int },
|
||||||
|
)
|
||||||
|
},
|
||||||
|
get("teams")!!.rows.map {
|
||||||
|
TeamDto(
|
||||||
|
it.jsonArray[0].jsonPrimitive.int,
|
||||||
|
it.jsonArray[1].jsonPrimitive.content,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
get("chapterizations")!!.rows.map {
|
||||||
|
ChapterDto(
|
||||||
|
it.jsonArray[0].jsonPrimitive.int,
|
||||||
|
it.jsonArray[1].jsonPrimitive.float,
|
||||||
|
it.jsonArray[2].jsonPrimitive.int,
|
||||||
|
it.jsonArray[3].jsonPrimitive.content,
|
||||||
|
it.jsonArray[4].jsonPrimitive.long,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
|
@ -0,0 +1,9 @@
|
||||||
|
package eu.kanade.tachiyomi.extension.ar.gmanga.dto
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TeamDto(
|
||||||
|
val id: Int,
|
||||||
|
val name: String,
|
||||||
|
)
|
Loading…
Reference in New Issue