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:
Vetle Ledaal 2022-02-04 13:12:57 +00:00 committed by GitHub
parent 2a180832e7
commit 77c3906e2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 137 additions and 32 deletions

View File

@ -6,7 +6,7 @@ ext {
extName = 'GMANGA'
pkgNameSuffix = 'ar.gmanga'
extClass = '.Gmanga'
extVersionCode = 8
extVersionCode = 9
}
dependencies {

View File

@ -2,7 +2,10 @@ package eu.kanade.tachiyomi.extension.ar.gmanga
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_SHOW_ALL
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.network.GET
import eu.kanade.tachiyomi.network.POST
@ -16,14 +19,12 @@ import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.float
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.json.long
import okhttp3.Headers
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
@ -65,41 +66,35 @@ class Gmanga : ConfigurableSource, HttpSource() {
return GET("$baseUrl/api/mangas/$mangaId/releases", headers)
}
@ExperimentalStdlibApi
override fun chapterListParse(response: Response): List<SChapter> {
val data = decryptResponse(response)
val chapters: List<JsonArray> = buildList {
val allChapters: ArrayList<JsonArray> = ArrayList()
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] }
allChapters.addAll(chapter.map { it.jsonArray })
val team = data["rows"]!!.jsonArray[1].jsonObject["rows"]!!.jsonArray.filter { it.jsonArray[0] == release.jsonArray[5] }
allChapters.addAll(team.map { it.jsonArray })
allChapters.add(release.jsonArray)
}
val table = json.decodeFromJsonElement<TableDto>(data)
val chapterList = table.asChapterList()
when (preferences.getString(PREF_CHAPTER_LISTING)) {
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)
}
val releases = when (preferences.getString(PREF_CHAPTER_LISTING)) {
PREF_CHAPTER_LISTING_SHOW_POPULAR ->
chapterList.releases
.groupBy { release -> release.chapterizationId }
.mapNotNull { (_, releases) -> releases.maxByOrNull { it.views } }
PREF_CHAPTER_LISTING_SHOW_ALL -> chapterList.releases
else -> emptyList()
}
return chapters.map {
return releases.map { release ->
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"
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")

View File

@ -39,10 +39,12 @@ class GmangaFilters() {
return buildJsonObject {
oneShotFilter.state.first().let {
when {
it.isIncluded() -> put("oneshot", true)
it.isExcluded() -> put("oneshot", false)
else -> put("oneshot", JsonNull)
putJsonObject("oneshot") {
when {
it.isIncluded() -> put("value", true)
it.isExcluded() -> put("value", false)
else -> put("value", JsonNull)
}
}
}

View File

@ -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,
)

View File

@ -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>,
)

View File

@ -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>,
)

View File

@ -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,
)
},
)

View File

@ -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,
)