diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistApi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistApi.kt index 0b6dca2b9..1ee49927e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistApi.kt @@ -5,6 +5,7 @@ import androidx.core.net.toUri import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.track.anilist.dto.ALAddMangaResult import eu.kanade.tachiyomi.data.track.anilist.dto.ALCurrentUserResult +import eu.kanade.tachiyomi.data.track.anilist.dto.ALError import eu.kanade.tachiyomi.data.track.anilist.dto.ALIdSearchResult import eu.kanade.tachiyomi.data.track.anilist.dto.ALMangaMetadata import eu.kanade.tachiyomi.data.track.anilist.dto.ALOAuth @@ -26,6 +27,7 @@ import kotlinx.serialization.json.put import kotlinx.serialization.json.putJsonObject import okhttp3.OkHttpClient import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.Response import tachiyomi.core.common.util.lang.withIOContext import uy.kohesive.injekt.injectLazy import java.time.Instant @@ -43,6 +45,25 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { .rateLimit(permits = 85, period = 1.minutes) .build() + // KMK --> + private fun Response.parseALError() { + val bodyString = peekBody(1024 * 1024).string() + val errorObj = try { + json.decodeFromString(bodyString) + } catch (_: Exception) { + null + } + + errorObj?.errors?.firstOrNull()?.let { + val msg = it.message + if (msg.contains("Invalid token") || it.status == 401) { + throw Exception("AniList token expired, please login again") + } + throw Exception(msg) + } + } + // KMK <-- + suspend fun addLibManga(track: Track): Track { return withIOContext { val query = $$""" @@ -71,6 +92,9 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { ), ) .awaitSuccess() + // KMK --> + .also { it.parseALError() } + // KMK <-- .parseAs() .let { track.library_id = it.data.entry.id @@ -112,6 +136,9 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { } authClient.newCall(POST(API_URL, body = payload.toString().toRequestBody(jsonMime))) .awaitSuccess() + // KMK --> + .use { it.parseALError() } + // KMK <-- track } } @@ -134,6 +161,9 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { } authClient.newCall(POST(API_URL, body = payload.toString().toRequestBody(jsonMime))) .awaitSuccess() + // KMK --> + .use { it.parseALError() } + // KMK <-- } } @@ -192,6 +222,9 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { ), ) .awaitSuccess() + // KMK --> + .also { it.parseALError() } + // KMK <-- .parseAs() .data.page.media .map { it.toALManga().toTrack() } @@ -271,6 +304,9 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { ), ) .awaitSuccess() + // KMK --> + .also { it.parseALError() } + // KMK <-- .parseAs() .data.page.mediaList .map { it.toALUserManga() } @@ -312,6 +348,9 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { ), ) .awaitSuccess() + // KMK --> + .also { it.parseALError() } + // KMK <-- .parseAs() .let { val viewer = it.data.viewer @@ -323,9 +362,9 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { suspend fun getMangaMetadata(track: DomainTrack): TrackMangaMetadata { return withIOContext { - val query = """ - |query (${'$'}mangaId: Int!) { - |Media (id: ${'$'}mangaId) { + val query = $$""" + |query ($mangaId: Int!) { + |Media (id: $mangaId) { |id |title { |userPreferred @@ -365,9 +404,12 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { ), ) .awaitSuccess() + // KMK --> + .also { it.parseALError() } + // KMK <-- .parseAs() - .let { - val media = it.data.media + .let { metadata -> + val media = metadata.data.media TrackMangaMetadata( remoteId = media.id, title = media.title.userPreferred, @@ -392,9 +434,9 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { // SY --> suspend fun searchById(id: String): TrackSearch { return withIOContext { - val query = """ - |query (${'$'}mangaId: Int!) { - |Media (id: ${'$'}mangaId) { + val query = $$""" + |query ($mangaId: Int!) { + |Media (id: $mangaId) { |id |title { |userPreferred @@ -430,6 +472,9 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { ), ) .awaitSuccess() + // KMK --> + .also { it.parseALError() } + // KMK <-- .parseAs() .data.media .toALManga() diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/dto/ALError.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/dto/ALError.kt new file mode 100644 index 000000000..7376cb881 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/dto/ALError.kt @@ -0,0 +1,14 @@ +package eu.kanade.tachiyomi.data.track.anilist.dto + +import kotlinx.serialization.Serializable + +@Serializable +data class ALError( + val errors: List? = null, +) + +@Serializable +data class ALErrorItem( + val message: String, + val status: Int? = null, +)