Use Shikimori's update endpoint (#3810)
No idea why it was originally going via the addition endpoint but Shikimori's v1 and v2 APIs have a dedicated endpoint to update a list entry via PATCH or PUT (interchangeable, both allow partial payloads). Splitting off the update path revealed that findLibManga would return a non-null track, which in turn causes the update call to fail with a 404 due to `library_id` being null. After further investigation, I realised that findLibManga should always return null if the title is not in the user's library, not just in refreshes.
This commit is contained in:
@@ -55,7 +55,7 @@ class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return api.updateLibManga(track, getUsername())
|
return api.updateLibManga(track)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun delete(track: DomainTrack) {
|
override suspend fun delete(track: DomainTrack) {
|
||||||
@@ -93,11 +93,10 @@ class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun refresh(track: Track): Track {
|
override suspend fun refresh(track: Track): Track {
|
||||||
api.findLibManga(track, isRefresh = true)?.let { remoteTrack ->
|
val remoteTrack = api.findLibManga(track) ?: throw Exception("Could not find manga")
|
||||||
track.library_id = remoteTrack.library_id
|
track.library_id = remoteTrack.library_id
|
||||||
track.copyPersonalFrom(remoteTrack)
|
track.copyPersonalFrom(remoteTrack)
|
||||||
track.total_chapters = remoteTrack.total_chapters
|
track.total_chapters = remoteTrack.total_chapters
|
||||||
} ?: throw Exception("Could not find manga")
|
|
||||||
return track
|
return track
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import android.net.Uri
|
|||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.data.track.shikimori.dto.SMAddMangaResponse
|
import eu.kanade.tachiyomi.data.track.shikimori.dto.SMLibraryIdResponse
|
||||||
import eu.kanade.tachiyomi.data.track.shikimori.dto.SMOAuth
|
import eu.kanade.tachiyomi.data.track.shikimori.dto.SMOAuth
|
||||||
import eu.kanade.tachiyomi.data.track.shikimori.dto.SMSearchResult
|
import eu.kanade.tachiyomi.data.track.shikimori.dto.SMSearchResult
|
||||||
import eu.kanade.tachiyomi.data.track.shikimori.dto.SMUser
|
import eu.kanade.tachiyomi.data.track.shikimori.dto.SMUser
|
||||||
@@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.data.track.shikimori.dto.SMUserListResult
|
|||||||
import eu.kanade.tachiyomi.data.track.shikimori.dto.SMUserResult
|
import eu.kanade.tachiyomi.data.track.shikimori.dto.SMUserResult
|
||||||
import eu.kanade.tachiyomi.network.DELETE
|
import eu.kanade.tachiyomi.network.DELETE
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
|
import eu.kanade.tachiyomi.network.PUT
|
||||||
import eu.kanade.tachiyomi.network.awaitSuccess
|
import eu.kanade.tachiyomi.network.awaitSuccess
|
||||||
import eu.kanade.tachiyomi.network.jsonMime
|
import eu.kanade.tachiyomi.network.jsonMime
|
||||||
import eu.kanade.tachiyomi.network.parseAs
|
import eu.kanade.tachiyomi.network.parseAs
|
||||||
@@ -55,7 +56,7 @@ class ShikimoriApi(
|
|||||||
body = payload.toString().toRequestBody(jsonMime),
|
body = payload.toString().toRequestBody(jsonMime),
|
||||||
),
|
),
|
||||||
).awaitSuccess()
|
).awaitSuccess()
|
||||||
.parseAs<SMAddMangaResponse>()
|
.parseAs<SMLibraryIdResponse>()
|
||||||
.let {
|
.let {
|
||||||
// save id of the entry for possible future delete request
|
// save id of the entry for possible future delete request
|
||||||
track.library_id = it.id
|
track.library_id = it.id
|
||||||
@@ -65,7 +66,32 @@ class ShikimoriApi(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateLibManga(track: Track, userId: String): Track = addLibManga(track, userId)
|
suspend fun updateLibManga(track: Track): Track {
|
||||||
|
return withIOContext {
|
||||||
|
val payload = buildJsonObject {
|
||||||
|
putJsonObject("user_rate") {
|
||||||
|
put("chapters", track.last_chapter_read.toInt())
|
||||||
|
put("score", track.score.toInt())
|
||||||
|
put("status", track.toShikimoriStatus())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
with(json) {
|
||||||
|
authClient.newCall(
|
||||||
|
PUT(
|
||||||
|
"$API_URL/v2/user_rates/${track.library_id}",
|
||||||
|
body = payload.toString().toRequestBody(jsonMime),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.awaitSuccess()
|
||||||
|
.parseAs<SMLibraryIdResponse>()
|
||||||
|
.let {
|
||||||
|
track.library_id = it.id
|
||||||
|
}
|
||||||
|
track
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun deleteLibManga(track: DomainTrack) {
|
suspend fun deleteLibManga(track: DomainTrack) {
|
||||||
withIOContext {
|
withIOContext {
|
||||||
@@ -175,7 +201,7 @@ class ShikimoriApi(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun findLibManga(track: Track, isRefresh: Boolean = false): Track? {
|
suspend fun findLibManga(track: Track): Track? {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
val query = $$"""
|
val query = $$"""
|
||||||
|query($id: String) {
|
|query($id: String) {
|
||||||
@@ -216,9 +242,11 @@ class ShikimoriApi(
|
|||||||
// userRate data which will be null if the title is not in the user's list.
|
// userRate data which will be null if the title is not in the user's list.
|
||||||
// If it was removed on Shikimori and is still linked in the app, notify user via returning null here
|
// If it was removed on Shikimori and is still linked in the app, notify user via returning null here
|
||||||
// which throws an exception at the Shikimori.refresh call
|
// which throws an exception at the Shikimori.refresh call
|
||||||
if (isRefresh && listResult?.userRate == null) return@with null
|
if (listResult?.userRate == null) {
|
||||||
|
null
|
||||||
listResult?.toTrack(trackId)
|
} else {
|
||||||
|
listResult.toTrack(trackId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -3,6 +3,6 @@ package eu.kanade.tachiyomi.data.track.shikimori.dto
|
|||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class SMAddMangaResponse(
|
data class SMLibraryIdResponse(
|
||||||
val id: Long,
|
val id: Long,
|
||||||
)
|
)
|
||||||
Reference in New Issue
Block a user