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' extName = 'GMANGA'
pkgNameSuffix = 'ar.gmanga' pkgNameSuffix = 'ar.gmanga'
extClass = '.Gmanga' extClass = '.Gmanga'
extVersionCode = 8 extVersionCode = 9
} }
dependencies { dependencies {

View File

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

View File

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

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