From cbf72f4c60cb85f29f8446ba1adb1cfd29d38a59 Mon Sep 17 00:00:00 2001 From: Constantin Piber <59023762+cpiber@users.noreply.github.com> Date: Fri, 31 Oct 2025 18:52:44 +0100 Subject: [PATCH] Migrate Kitsu to use library_id and remote_id properly (#2609) --- CHANGELOG.md | 3 +++ .../java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt | 1 + .../eu/kanade/tachiyomi/data/track/kitsu/KitsuApi.kt | 10 +++++----- .../tachiyomi/data/track/kitsu/dto/KitsuListSearch.kt | 3 ++- data/src/main/sqldelight/tachiyomi/migrations/8.sqm | 7 +++++++ 5 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 data/src/main/sqldelight/tachiyomi/migrations/8.sqm diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bba98f6a..52a0d7c32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,9 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co - Fix category migration flag being ignored due to incorrect check against chapter flag ([@Secozzi](https://github.com/Secozzi)) ([#2484](https://github.com/mihonapp/mihon/pull/2484)) - Fix disabling incognito mode from notification ([@NGB-Was-Taken](https://github.com/NGB-Was-Taken)) ([#2512](https://github.com/mihonapp/mihon/pull/2512)) +### Other +- Fix Kitsu tracker to conform to tracker data structure properly ([@cpiber](https://github.com/cpiber)) ([#2609](https://github.com/mihonapp/mihon/pull/2609)) + ## [v0.19.1] - 2025-08-07 ### Changed - LocalSource now reads ComicInfo.xml file for chapter (if available) to display chapter title, number and scanlator ([@raxod502](https://github.com/radian-software)) ([#2332](https://github.com/mihonapp/mihon/pull/2332)) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt index 971f62c1b..0ec899aeb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt @@ -104,6 +104,7 @@ class Kitsu(id: Long) : BaseTracker(id, "Kitsu"), DeletableTracker { return if (remoteTrack != null) { track.copyPersonalFrom(remoteTrack, copyRemotePrivate = false) track.remote_id = remoteTrack.remote_id + track.library_id = remoteTrack.library_id if (track.status != COMPLETED) { track.status = if (hasReadChapters) READING else track.status diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/KitsuApi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/KitsuApi.kt index c494b805f..446808704 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/KitsuApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/KitsuApi.kt @@ -76,7 +76,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor) .awaitSuccess() .parseAs() .let { - track.remote_id = it.data.id + track.library_id = it.data.id track } } @@ -88,7 +88,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor) val data = buildJsonObject { putJsonObject("data") { put("type", "libraryEntries") - put("id", track.remote_id) + put("id", track.library_id) putJsonObject("attributes") { put("status", track.toApiStatus()) put("progress", track.last_chapter_read.toInt()) @@ -102,7 +102,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor) authClient.newCall( Request.Builder() - .url("${BASE_URL}library-entries/${track.remote_id}") + .url("${BASE_URL}library-entries/${track.library_id}") .headers( headersOf("Content-Type", VND_API_JSON), ) @@ -119,7 +119,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor) withIOContext { authClient.newCall( DELETE( - "${BASE_URL}library-entries/${track.remoteId}", + "${BASE_URL}library-entries/${track.libraryId}", headers = headersOf("Content-Type", VND_API_JSON), ), ) @@ -192,7 +192,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor) suspend fun getLibManga(track: Track): Track { return withIOContext { val url = "${BASE_URL}library-entries".toUri().buildUpon() - .encodedQuery("filter[id]=${track.remote_id}") + .encodedQuery("filter[id]=${track.library_id}") .appendQueryParameter("include", "manga") .build() with(json) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/dto/KitsuListSearch.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/dto/KitsuListSearch.kt index 4fc8437da..ad715f12d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/dto/KitsuListSearch.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/dto/KitsuListSearch.kt @@ -21,7 +21,8 @@ data class KitsuListSearchResult( val manga = included[0].attributes return TrackSearch.create(TrackerManager.KITSU).apply { - remote_id = userData.id + remote_id = included[0].id + library_id = userData.id title = manga.canonicalTitle total_chapters = manga.chapterCount ?: 0 cover_url = manga.posterImage?.original ?: "" diff --git a/data/src/main/sqldelight/tachiyomi/migrations/8.sqm b/data/src/main/sqldelight/tachiyomi/migrations/8.sqm new file mode 100644 index 000000000..e07e36184 --- /dev/null +++ b/data/src/main/sqldelight/tachiyomi/migrations/8.sqm @@ -0,0 +1,7 @@ +-- Save the current remote_id as library_id, since old Kitsu tracker did not use this correctly +UPDATE manga_sync SET library_id = remote_id WHERE sync_id = 3; + +-- Kitsu and Suwayomi aren't using the remote_id field properly, but for both the ID is present in the URL +-- This parses a url and gets the ID from the trailing path part, e.g. https://kitsu.app/manga/ +-- Based on https://stackoverflow.com/a/38330814 +UPDATE manga_sync SET remote_id = replace(remote_url, rtrim(remote_url, replace(remote_url, '/', '')), '') WHERE sync_id IN (3, 9);