瀏覽代碼

Added Start/Finished Date Support to AniList

Based on https://github.com/Jays2Kings/tachiyomiJ2K/commit/1e3de8a67f239a3126178b95f2b028fbba1e7633

Co-Authored-By: Jays2Kings
Jays2Kings 4 年之前
父節點
當前提交
2ba60e9114

+ 2 - 0
app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt

@@ -35,6 +35,8 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) {
 
     private val api by lazy { AnilistApi(client, interceptor) }
 
+    override val supportsReadingDates: Boolean = true
+
     private val scorePreference = preferences.anilistScoreType()
 
     init {

+ 64 - 25
app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistApi.kt

@@ -2,6 +2,9 @@ package eu.kanade.tachiyomi.data.track.anilist
 
 import android.net.Uri
 import androidx.core.net.toUri
+import com.afollestad.date.dayOfMonth
+import com.afollestad.date.month
+import com.afollestad.date.year
 import eu.kanade.tachiyomi.data.database.models.Track
 import eu.kanade.tachiyomi.data.track.model.TrackSearch
 import eu.kanade.tachiyomi.network.POST
@@ -9,6 +12,7 @@ import eu.kanade.tachiyomi.network.await
 import eu.kanade.tachiyomi.network.jsonMime
 import eu.kanade.tachiyomi.network.parseAs
 import eu.kanade.tachiyomi.util.lang.withIOContext
+import kotlinx.serialization.json.JsonNull
 import kotlinx.serialization.json.JsonObject
 import kotlinx.serialization.json.buildJsonObject
 import kotlinx.serialization.json.contentOrNull
@@ -30,8 +34,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
 
     suspend fun addLibManga(track: Track): Track {
         return withIOContext {
-            val query =
-                """
+            val query = """
             |mutation AddManga(${'$'}mangaId: Int, ${'$'}progress: Int, ${'$'}status: MediaListStatus) {
                 |SaveMediaListEntry (mediaId: ${'$'}mangaId, progress: ${'$'}progress, status: ${'$'}status) { 
                 |   id 
@@ -65,10 +68,15 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
 
     suspend fun updateLibManga(track: Track): Track {
         return withIOContext {
-            val query =
-                """
-            |mutation UpdateManga(${'$'}listId: Int, ${'$'}progress: Int, ${'$'}status: MediaListStatus, ${'$'}score: Int) {
-                |SaveMediaListEntry (id: ${'$'}listId, progress: ${'$'}progress, status: ${'$'}status, scoreRaw: ${'$'}score) {
+            val query = """
+            |mutation UpdateManga(
+                |${'$'}listId: Int, ${'$'}progress: Int, ${'$'}status: MediaListStatus,
+                |${'$'}score: Int, ${'$'}startedAt: FuzzyDateInput, ${'$'}completedAt: FuzzyDateInput
+            |) {
+                |SaveMediaListEntry(
+                    |id: ${'$'}listId, progress: ${'$'}progress, status: ${'$'}status,
+                    |scoreRaw: ${'$'}score, startedAt: ${'$'}startedAt, completedAt: ${'$'}completedAt
+                |) {
                     |id
                     |status
                     |progress
@@ -82,6 +90,8 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
                     put("progress", track.last_chapter_read)
                     put("status", track.toAnilistStatus())
                     put("score", track.score.toInt())
+                    put("startedAt", createDate(track.started_reading_date))
+                    put("completedAt", createDate(track.finished_reading_date))
                 }
             }
             authClient.newCall(POST(apiUrl, body = payload.toString().toRequestBody(jsonMime)))
@@ -92,8 +102,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
 
     suspend fun search(search: String): List<TrackSearch> {
         return withIOContext {
-            val query =
-                """
+            val query = """
             |query Search(${'$'}query: String) {
                 |Page (perPage: 50) {
                     |media(search: ${'$'}query, type: MANGA, format_not_in: [NOVEL]) {
@@ -143,8 +152,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
 
     suspend fun findLibManga(track: Track, userid: Int): Track? {
         return withIOContext {
-            val query =
-                """
+            val query = """
             |query (${'$'}id: Int!, ${'$'}manga_id: Int!) {
                 |Page {
                     |mediaList(userId: ${'$'}id, type: MANGA, mediaId: ${'$'}manga_id) {
@@ -152,6 +160,16 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
                         |status
                         |scoreRaw: score(format: POINT_100)
                         |progress
+                        |startedAt {
+                            |year
+                            |month
+                            |day
+                        |}
+                        |completedAt {
+                            |year
+                            |month
+                            |day
+                        |}
                         |media {
                             |id
                             |title {
@@ -209,8 +227,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
 
     suspend fun getCurrentUser(): Pair<Int, String> {
         return withIOContext {
-            val query =
-                """
+            val query = """
             |query User {
                 |Viewer {
                     |id
@@ -243,18 +260,6 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
     }
 
     private fun jsonToALManga(struct: JsonObject): ALManga {
-        val date = try {
-            val date = Calendar.getInstance()
-            date.set(
-                struct["startDate"]!!.jsonObject["year"]!!.jsonPrimitive.int,
-                struct["startDate"]!!.jsonObject["month"]!!.jsonPrimitive.int - 1,
-                struct["startDate"]!!.jsonObject["day"]!!.jsonPrimitive.int
-            )
-            date.timeInMillis
-        } catch (_: Exception) {
-            0L
-        }
-
         return ALManga(
             struct["id"]!!.jsonPrimitive.int,
             struct["title"]!!.jsonObject["romaji"]!!.jsonPrimitive.content,
@@ -262,7 +267,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
             struct["description"]!!.jsonPrimitive.contentOrNull,
             struct["type"]!!.jsonPrimitive.content,
             struct["status"]!!.jsonPrimitive.contentOrNull ?: "",
-            date,
+            parseDate(struct, "startDate"),
             struct["chapters"]!!.jsonPrimitive.intOrNull ?: 0
         )
     }
@@ -273,10 +278,44 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
             struct["status"]!!.jsonPrimitive.content,
             struct["scoreRaw"]!!.jsonPrimitive.int,
             struct["progress"]!!.jsonPrimitive.int,
+            parseDate(struct, "startedAt"),
+            parseDate(struct, "completedAt"),
             jsonToALManga(struct["media"]!!.jsonObject)
         )
     }
 
+    private fun parseDate(struct: JsonObject, dateKey: String): Long {
+        return try {
+            val date = Calendar.getInstance()
+            date.set(
+                struct[dateKey]!!.jsonObject["year"]!!.jsonPrimitive.int,
+                struct[dateKey]!!.jsonObject["month"]!!.jsonPrimitive.int - 1,
+                struct[dateKey]!!.jsonObject["day"]!!.jsonPrimitive.int
+            )
+            date.timeInMillis
+        } catch (_: Exception) {
+            0L
+        }
+    }
+
+    private fun createDate(dateValue: Long): JsonObject {
+        if (dateValue == 0L) {
+            return buildJsonObject {
+                put("year", JsonNull)
+                put("month", JsonNull)
+                put("day", JsonNull)
+            }
+        }
+
+        val calendar = Calendar.getInstance()
+        calendar.timeInMillis = dateValue
+        return buildJsonObject {
+            put("year", calendar.year)
+            put("month", calendar.month + 1)
+            put("day", calendar.dayOfMonth)
+        }
+    }
+
     companion object {
         private const val clientId = "385"
         private const val apiUrl = "https://graphql.anilist.co/"

+ 4 - 0
app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistModels.kt

@@ -44,6 +44,8 @@ data class ALUserManga(
     val list_status: String,
     val score_raw: Int,
     val chapters_read: Int,
+    val start_date_fuzzy: Long,
+    val completed_date_fuzzy: Long,
     val manga: ALManga
 ) {
 
@@ -51,6 +53,8 @@ data class ALUserManga(
         media_id = manga.media_id
         status = toTrackStatus()
         score = score_raw.toFloat()
+        started_reading_date = start_date_fuzzy
+        finished_reading_date = completed_date_fuzzy
         last_chapter_read = chapters_read
         library_id = [email protected]_id
         total_chapters = manga.total_chapters