From ab58a9952e55485d81193f13ffc262725d8cae32 Mon Sep 17 00:00:00 2001 From: MajorTanya <39014446+MajorTanya@users.noreply.github.com> Date: Wed, 8 Jul 2026 19:41:23 +0200 Subject: [PATCH] Fix Hikka search failing due to unclosed response & show toast on remote-removed titles (#3548) * Fix Hikka search failing due to unclosed response This closes #3547. I have also included a precautionary refactor of the `getRead` method in HikkaApi.kt, which by the looks of it _could_ leak an unclosed response as well. The try/catch with awaitSuccess pattern has been used in this same way in the Bangumi and MangaBaka implementations as well. The benefit here is that `awaitSuccess()` closes the response on error before throwing an `HttpException`. * Show toast on remote-removed list entries --- CHANGELOG.md | 1 + .../kanade/tachiyomi/data/track/hikka/Hikka.kt | 15 +++++++-------- .../tachiyomi/data/track/hikka/HikkaApi.kt | 17 +++++++++++------ .../data/track/hikka/HikkaInterceptor.kt | 3 +++ 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d35a5e78..310022f9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co ### Added - [Hikka](https://hikka.io/) tracker support ([@Lorg0n](https://github.com/Lorg0n)) ([#1386](https://github.com/mihonapp/mihon/pull/1386)) - Fix Hikka not defaulting to "Plan to Read" for unread titles ([@MajorTanya](https://github.com/MajorTanya)) ([#3534](https://github.com/mihonapp/mihon/pull/3534)) + - Fix Hikka search throwing error due to unclosed response ([@MajorTanya](https://github.com/MajorTanya)) ([#3548](https://github.com/mihonapp/mihon/pull/3548)) - Add support for [MangaBaka](https://mangabaka.org) tracker ([@MajorTanya](https://github.com/MajorTanya)) ([#3047](https://github.com/mihonapp/mihon/pull/3047)) - Support resumable image downloads if supported by source ([@xMohnad](https://github.com/xMohnad)) ([#3167](https://github.com/mihonapp/mihon/pull/3167)) - Display authors and description in Shikimori search results ([@MajorTanya](https://github.com/MajorTanya)) ([#3499](https://github.com/mihonapp/mihon/pull/3499)) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/hikka/Hikka.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/hikka/Hikka.kt index 91dbd6d63..dcac04b2f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/hikka/Hikka.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/hikka/Hikka.kt @@ -125,14 +125,13 @@ class Hikka(id: Long) : BaseTracker(id, "Hikka"), DeletableTracker { track.copyPersonalFrom(remoteTrack) track.total_chapters = remoteTrack.total_chapters - val readContent = api.getRead(track) - if (readContent != null) { - track.score = readContent.score.toDouble() - track.last_chapter_read = readContent.chapters.toDouble() - track.status = toTrackStatus(readContent.status) - track.started_reading_date = (readContent.startDate ?: 0L) * 1000 - track.finished_reading_date = (readContent.endDate ?: 0L) * 1000 - } + val readContent = api.getRead(track) ?: throw Exception("Could not find manga") + + track.score = readContent.score.toDouble() + track.last_chapter_read = readContent.chapters.toDouble() + track.status = toTrackStatus(readContent.status) + track.started_reading_date = (readContent.startDate ?: 0L) * 1000 + track.finished_reading_date = (readContent.endDate ?: 0L) * 1000 return track } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/hikka/HikkaApi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/hikka/HikkaApi.kt index 3d313c419..d18fcfdb6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/hikka/HikkaApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/hikka/HikkaApi.kt @@ -11,6 +11,7 @@ import eu.kanade.tachiyomi.data.track.hikka.dto.HKUser import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.network.DELETE import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.network.HttpException import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.PUT import eu.kanade.tachiyomi.network.awaitSuccess @@ -103,12 +104,16 @@ class HikkaApi( val slug = track.tracking_url.split("/")[4] val url = "$BASE_API_URL/read/manga/$slug".toUri().buildUpon().build() with(json) { - val response = authClient.newCall(GET(url.toString())).execute() - if (response.code == 404) { - return@withIOContext null - } - response.use { - it.parseAs() + try { + authClient.newCall(GET(url.toString())) + .awaitSuccess() + .parseAs() + } catch (e: HttpException) { + if (e.code == 404) { + null + } else { + throw e + } } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/hikka/HikkaInterceptor.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/hikka/HikkaInterceptor.kt index f13d198c4..8de795bef 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/hikka/HikkaInterceptor.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/hikka/HikkaInterceptor.kt @@ -22,11 +22,14 @@ class HikkaInterceptor(private val hikka: Hikka) : Interceptor { refreshTokenResponse.close() hikka.logout() throw Exception("Hikka: The token is expired") + } else { + refreshTokenResponse.close() } val authTokenInfoResponse = chain.proceed(HikkaApi.authTokenInfo(currAuth.accessToken)) if (!authTokenInfoResponse.isSuccessful) { authTokenInfoResponse.close() + throw Exception("Hikka: Auth token info failed") } val authTokenInfo = json.decodeFromString(authTokenInfoResponse.body.string())