From 892f95a7a60e9778aeab82ca88a060c1ce11cf71 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Wed, 31 Jan 2024 13:56:30 +0200 Subject: [PATCH] Fix scrobbling chapter index --- .../kotatsu/history/data/HistoryRepository.kt | 5 +--- .../anilist/data/AniListRepository.kt | 5 ++-- .../anilist/domain/AniListScrobbler.kt | 4 ++- .../common/data/ScrobblerRepository.kt | 3 +- .../scrobbling/common/domain/Scrobbler.kt | 29 +++++++++++++++---- .../selector/ScrobblingSelectorViewModel.kt | 16 +++------- .../scrobbling/kitsu/data/KitsuRepository.kt | 5 ++-- .../scrobbling/kitsu/domain/KitsuScrobbler.kt | 4 ++- .../scrobbling/mal/data/MALRepository.kt | 5 ++-- .../scrobbling/mal/domain/MALScrobbler.kt | 4 ++- .../shikimori/data/ShikimoriRepository.kt | 5 ++-- .../shikimori/domain/ShikimoriScrobbler.kt | 4 ++- 12 files changed, 49 insertions(+), 40 deletions(-) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryRepository.kt index 7a9e5cf5e..5d2e06292 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryRepository.kt @@ -109,10 +109,7 @@ class HistoryRepository @Inject constructor( ), ) trackingRepository.syncWithHistory(manga, chapterId) - val chapter = manga.chapters?.findById(chapterId) - if (chapter != null) { - scrobblers.forEach { it.tryScrobble(manga.id, chapter) } - } + scrobblers.forEach { it.tryScrobble(manga, chapterId) } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/data/AniListRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/data/AniListRepository.kt index 42552bef4..5fa6ce203 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/data/AniListRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/data/AniListRepository.kt @@ -11,7 +11,6 @@ import org.json.JSONObject import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.parsers.exception.GraphQLException -import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.util.await import org.koitharu.kotatsu.parsers.util.json.getStringOrNull import org.koitharu.kotatsu.parsers.util.json.mapJSON @@ -154,11 +153,11 @@ class AniListRepository @Inject constructor( saveRate(response.getJSONObject("data").getJSONObject("SaveMediaListEntry"), mangaId) } - override suspend fun updateRate(rateId: Int, mangaId: Long, chapter: MangaChapter) { + override suspend fun updateRate(rateId: Int, mangaId: Long, chapter: Int) { val response = doRequest( REQUEST_MUTATION, """ - SaveMediaListEntry(id: $rateId, progress: ${chapter.number}) { + SaveMediaListEntry(id: $rateId, progress: $chapter) { id mediaId status diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/domain/AniListScrobbler.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/domain/AniListScrobbler.kt index ef4612950..9404d727d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/domain/AniListScrobbler.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/domain/AniListScrobbler.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.scrobbling.anilist.domain import org.koitharu.kotatsu.core.db.MangaDatabase +import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.scrobbling.anilist.data.AniListRepository import org.koitharu.kotatsu.scrobbling.common.domain.Scrobbler import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService @@ -12,7 +13,8 @@ import javax.inject.Singleton class AniListScrobbler @Inject constructor( private val repository: AniListRepository, db: MangaDatabase, -) : Scrobbler(db, ScrobblerService.ANILIST, repository) { + mangaRepositoryFactory: MangaRepository.Factory, +) : Scrobbler(db, ScrobblerService.ANILIST, repository, mangaRepositoryFactory) { init { statuses[ScrobblingStatus.PLANNED] = "PLANNING" diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/data/ScrobblerRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/data/ScrobblerRepository.kt index 35ed7bd46..0e5a686b2 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/data/ScrobblerRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/data/ScrobblerRepository.kt @@ -1,6 +1,5 @@ package org.koitharu.kotatsu.scrobbling.common.data -import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerMangaInfo import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser @@ -27,7 +26,7 @@ interface ScrobblerRepository { suspend fun createRate(mangaId: Long, scrobblerMangaId: Long) - suspend fun updateRate(rateId: Int, mangaId: Long, chapter: MangaChapter) + suspend fun updateRate(rateId: Int, mangaId: Long, chapter: Int) suspend fun updateRate(rateId: Int, mangaId: Long, rating: Float, status: String?, comment: String?) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt index f218ebee1..9db96ade8 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt @@ -11,10 +11,12 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import org.koitharu.kotatsu.core.db.MangaDatabase +import org.koitharu.kotatsu.core.model.findById +import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.util.ext.findKeyByValue import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug import org.koitharu.kotatsu.core.util.ext.sanitize -import org.koitharu.kotatsu.parsers.model.MangaChapter +import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.scrobbling.common.data.ScrobblerRepository import org.koitharu.kotatsu.scrobbling.common.data.ScrobblingEntity @@ -30,6 +32,7 @@ abstract class Scrobbler( protected val db: MangaDatabase, val scrobblerService: ScrobblerService, private val repository: ScrobblerRepository, + private val mangaRepositoryFactory: MangaRepository.Factory, ) { private val infoCache = LongSparseArray() @@ -68,9 +71,23 @@ abstract class Scrobbler( repository.createRate(mangaId, targetId) } - suspend fun scrobble(mangaId: Long, chapter: MangaChapter) { - val entity = db.getScrobblingDao().find(scrobblerService.id, mangaId) ?: return - repository.updateRate(entity.id, entity.mangaId, chapter) + suspend fun scrobble(manga: Manga, chapterId: Long) { + var chapters = manga.chapters + if (chapters.isNullOrEmpty()) { + chapters = mangaRepositoryFactory.create(manga.source).getDetails(manga).chapters + } + requireNotNull(chapters) + val chapter = checkNotNull(chapters.findById(chapterId)) { + "Chapter $chapterId not found in this manga" + } + val number = if (chapter.number > 0f) { + chapter.number.toInt() + } else { + chapters = chapters.filter { x -> x.branch == chapter.branch } + chapters.indexOf(chapter) + 1 + } + val entity = db.getScrobblingDao().find(scrobblerService.id, manga.id) ?: return + repository.updateRate(entity.id, entity.mangaId, number) } suspend fun getScrobblingInfoOrNull(mangaId: Long): ScrobblingInfo? { @@ -137,9 +154,9 @@ abstract class Scrobbler( } } -suspend fun Scrobbler.tryScrobble(mangaId: Long, chapter: MangaChapter): Boolean { +suspend fun Scrobbler.tryScrobble(manga: Manga, chapterId: Long): Boolean { return runCatchingCancellable { - scrobble(mangaId, chapter) + scrobble(manga, chapterId) }.onFailure { it.printStackTraceDebug() }.isSuccess diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt index 380614ffe..6702b1abc 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt @@ -14,10 +14,8 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.plus import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.model.findById import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.parser.MangaIntent -import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.ui.BaseViewModel import org.koitharu.kotatsu.core.util.ext.MutableEventFlow import org.koitharu.kotatsu.core.util.ext.call @@ -40,7 +38,6 @@ class ScrobblingSelectorViewModel @Inject constructor( savedStateHandle: SavedStateHandle, scrobblers: Set<@JvmSuppressWildcards Scrobbler>, private val historyRepository: HistoryRepository, - private val mangaRepositoryFactory: MangaRepository.Factory, ) : BaseViewModel() { val manga = savedStateHandle.require(MangaIntent.KEY_MANGA).manga @@ -164,15 +161,10 @@ class ScrobblingSelectorViewModel @Inject constructor( comment = prevInfo?.comment, ) if (history != null) { - val chapter = mangaRepositoryFactory.create(manga.source) - .getDetails(manga) - .chapters?.findById(history.chapterId) - if (chapter != null) { - currentScrobbler.scrobble( - mangaId = manga.id, - chapter = chapter, - ) - } + currentScrobbler.scrobble( + manga = manga, + chapterId = history.chapterId, + ) } onClose.call(Unit) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/kitsu/data/KitsuRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/kitsu/data/KitsuRepository.kt index c6b0b7386..12c637670 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/kitsu/data/KitsuRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/kitsu/data/KitsuRepository.kt @@ -12,7 +12,6 @@ import org.json.JSONObject import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.util.ext.parseJsonOrNull -import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.util.await import org.koitharu.kotatsu.parsers.util.json.getFloatOrDefault import org.koitharu.kotatsu.parsers.util.json.getIntOrDefault @@ -161,13 +160,13 @@ class KitsuRepository( saveRate(response, mangaId) } - override suspend fun updateRate(rateId: Int, mangaId: Long, chapter: MangaChapter) { + override suspend fun updateRate(rateId: Int, mangaId: Long, chapter: Int) { val payload = JSONObject() payload.putJO("data") { put("type", "libraryEntries") put("id", rateId) putJO("attributes") { - put("progress", chapter.number.toInt()) // TODO + put("progress", chapter) } } val request = Request.Builder() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/kitsu/domain/KitsuScrobbler.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/kitsu/domain/KitsuScrobbler.kt index f19cf899e..221f2e191 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/kitsu/domain/KitsuScrobbler.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/kitsu/domain/KitsuScrobbler.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.scrobbling.kitsu.domain import org.koitharu.kotatsu.core.db.MangaDatabase +import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.scrobbling.common.domain.Scrobbler import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingStatus @@ -10,7 +11,8 @@ import javax.inject.Inject class KitsuScrobbler @Inject constructor( private val repository: KitsuRepository, db: MangaDatabase, -) : Scrobbler(db, ScrobblerService.KITSU, repository) { + mangaRepositoryFactory: MangaRepository.Factory, +) : Scrobbler(db, ScrobblerService.KITSU, repository, mangaRepositoryFactory) { init { statuses[ScrobblingStatus.PLANNED] = "planned" diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/mal/data/MALRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/mal/data/MALRepository.kt index d3c028ee5..3a23804b1 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/mal/data/MALRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/mal/data/MALRepository.kt @@ -10,7 +10,6 @@ import okhttp3.Request import org.json.JSONObject import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.db.MangaDatabase -import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.util.await import org.koitharu.kotatsu.parsers.util.json.getStringOrNull import org.koitharu.kotatsu.parsers.util.json.mapJSONNotNull @@ -132,9 +131,9 @@ class MALRepository @Inject constructor( saveRate(response, mangaId, scrobblerMangaId) } - override suspend fun updateRate(rateId: Int, mangaId: Long, chapter: MangaChapter) { + override suspend fun updateRate(rateId: Int, mangaId: Long, chapter: Int) { val body = FormBody.Builder() - .add("num_chapters_read", chapter.number.toString()) + .add("num_chapters_read", chapter.toString()) val url = BASE_API_URL.toHttpUrl().newBuilder() .addPathSegment("manga") .addPathSegment(rateId.toString()) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/mal/domain/MALScrobbler.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/mal/domain/MALScrobbler.kt index 3f83625e9..a256dbe88 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/mal/domain/MALScrobbler.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/mal/domain/MALScrobbler.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.scrobbling.mal.domain import org.koitharu.kotatsu.core.db.MangaDatabase +import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.scrobbling.common.domain.Scrobbler import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingStatus @@ -14,7 +15,8 @@ private const val RATING_MAX = 10f class MALScrobbler @Inject constructor( private val repository: MALRepository, db: MangaDatabase, -) : Scrobbler(db, ScrobblerService.MAL, repository) { + mangaRepositoryFactory: MangaRepository.Factory, +) : Scrobbler(db, ScrobblerService.MAL, repository, mangaRepositoryFactory) { init { statuses[ScrobblingStatus.PLANNED] = "plan_to_read" diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt index 266932fdf..0ca1054ea 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt @@ -10,7 +10,6 @@ import org.json.JSONObject import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.util.ext.toRequestBody -import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.util.await import org.koitharu.kotatsu.parsers.util.json.getStringOrNull import org.koitharu.kotatsu.parsers.util.json.mapJSON @@ -130,12 +129,12 @@ class ShikimoriRepository @Inject constructor( saveRate(response, mangaId) } - override suspend fun updateRate(rateId: Int, mangaId: Long, chapter: MangaChapter) { + override suspend fun updateRate(rateId: Int, mangaId: Long, chapter: Int) { val payload = JSONObject() payload.put( "user_rate", JSONObject().apply { - put("chapters", chapter.number) + put("chapters", chapter) }, ) val url = BASE_URL.toHttpUrl().newBuilder() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/shikimori/domain/ShikimoriScrobbler.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/shikimori/domain/ShikimoriScrobbler.kt index b0d720359..281063b8a 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/shikimori/domain/ShikimoriScrobbler.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/shikimori/domain/ShikimoriScrobbler.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.scrobbling.shikimori.domain import org.koitharu.kotatsu.core.db.MangaDatabase +import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.scrobbling.common.domain.Scrobbler import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingStatus @@ -14,7 +15,8 @@ private const val RATING_MAX = 10f class ShikimoriScrobbler @Inject constructor( private val repository: ShikimoriRepository, db: MangaDatabase, -) : Scrobbler(db, ScrobblerService.SHIKIMORI, repository) { + mangaRepositoryFactory: MangaRepository.Factory, +) : Scrobbler(db, ScrobblerService.SHIKIMORI, repository, mangaRepositoryFactory) { init { statuses[ScrobblingStatus.PLANNED] = "planned"