Эх сурвалжийг харах

Fix Kavita interceptor crashing app + minor cleanup

arkon 2 жил өмнө
parent
commit
a54d9912d0

+ 14 - 14
app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/Kavita.kt

@@ -1,6 +1,5 @@
 package eu.kanade.tachiyomi.data.track.kavita
 
-import android.app.Application
 import android.content.Context
 import android.content.SharedPreferences
 import android.graphics.Color
@@ -13,18 +12,20 @@ import eu.kanade.tachiyomi.data.track.NoLoginTrackService
 import eu.kanade.tachiyomi.data.track.TrackService
 import eu.kanade.tachiyomi.data.track.model.TrackSearch
 import eu.kanade.tachiyomi.source.Source
-import uy.kohesive.injekt.Injekt
-import uy.kohesive.injekt.api.get
 import java.security.MessageDigest
+import eu.kanade.domain.manga.model.Manga as DomainManga
+import eu.kanade.domain.track.model.Track as DomainTrack
 
 class Kavita(private val context: Context, id: Long) : TrackService(id), EnhancedTrackService, NoLoginTrackService {
-    var authentications: OAuth? = null
+
     companion object {
         const val UNREAD = 1
         const val READING = 2
         const val COMPLETED = 3
     }
 
+    var authentications: OAuth? = null
+
     private val interceptor by lazy { KavitaInterceptor(this) }
     val api by lazy { KavitaApi(client, interceptor) }
 
@@ -39,18 +40,18 @@ class Kavita(private val context: Context, id: Long) : TrackService(id), Enhance
 
     override fun getStatus(status: Int): String = with(context) {
         when (status) {
-            Kavita.UNREAD -> getString(R.string.unread)
-            Kavita.READING -> getString(R.string.reading)
-            Kavita.COMPLETED -> getString(R.string.completed)
+            UNREAD -> getString(R.string.unread)
+            READING -> getString(R.string.reading)
+            COMPLETED -> getString(R.string.completed)
             else -> ""
         }
     }
 
-    override fun getReadingStatus(): Int = Kavita.READING
+    override fun getReadingStatus(): Int = READING
 
     override fun getRereadingStatus(): Int = -1
 
-    override fun getCompletionStatus(): Int = Kavita.COMPLETED
+    override fun getCompletionStatus(): Int = COMPLETED
 
     override fun getScoreList(): List<String> = emptyList()
 
@@ -103,10 +104,10 @@ class Kavita(private val context: Context, id: Long) : TrackService(id), Enhance
             null
         }
 
-    override fun isTrackFrom(track: eu.kanade.domain.track.model.Track, manga: eu.kanade.domain.manga.model.Manga, source: Source?): Boolean =
+    override fun isTrackFrom(track: DomainTrack, manga: DomainManga, source: Source?): Boolean =
         track.remoteUrl == manga.url && source?.let { accept(it) } == true
 
-    override fun migrateTrack(track: eu.kanade.domain.track.model.Track, manga: eu.kanade.domain.manga.model.Manga, newSource: Source): eu.kanade.domain.track.model.Track? =
+    override fun migrateTrack(track: DomainTrack, manga: DomainManga, newSource: Source): DomainTrack? =
         if (accept(newSource)) {
             track.copy(remoteUrl = manga.url)
         } else {
@@ -118,13 +119,13 @@ class Kavita(private val context: Context, id: Long) : TrackService(id), Enhance
         for (sourceId in 1..3) {
             val authentication = oauth.authentications[sourceId - 1]
             val sourceSuffixID by lazy {
-                val key = "${"kavita_$sourceId"}/all/1" // Hardcoded versionID to 1
+                val key = "kavita_$sourceId/all/1" // Hardcoded versionID to 1
                 val bytes = MessageDigest.getInstance("MD5").digest(key.toByteArray())
                 (0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }
                     .reduce(Long::or) and Long.MAX_VALUE
             }
             val preferences: SharedPreferences by lazy {
-                Injekt.get<Application>().getSharedPreferences("source_$sourceSuffixID", 0x0000)
+                context.getSharedPreferences("source_$sourceSuffixID", 0x0000)
             }
             val prefApiUrl = preferences.getString("APIURL", "")!!
             if (prefApiUrl.isEmpty()) {
@@ -133,7 +134,6 @@ class Kavita(private val context: Context, id: Long) : TrackService(id), Enhance
             }
             val prefApiKey = preferences.getString("APIKEY", "")!!
             val token = api.getNewToken(apiUrl = prefApiUrl, apiKey = prefApiKey)
-
             if (token.isNullOrEmpty()) {
                 // Source is not accessible. Skip
                 continue

+ 62 - 59
app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/KavitaApi.kt

@@ -13,51 +13,57 @@ import okhttp3.Dns
 import okhttp3.MediaType.Companion.toMediaTypeOrNull
 import okhttp3.OkHttpClient
 import okhttp3.RequestBody.Companion.toRequestBody
+import java.io.IOException
 import java.net.SocketTimeoutException
 
 class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor) {
-    private val authClient = client.newBuilder().dns(Dns.SYSTEM).addInterceptor(interceptor).build()
+
+    private val authClient = client.newBuilder()
+        .dns(Dns.SYSTEM)
+        .addInterceptor(interceptor)
+        .build()
+
     fun getApiFromUrl(url: String): String {
         return url.split("/api/").first() + "/api"
     }
 
+    /*
+     * Uses url to compare against each source APIURL's to get the correct custom source preference.
+     * Now having source preference we can do getString("APIKEY")
+     * Authenticates to get the token
+     * Saves the token in the var jwtToken
+     */
     fun getNewToken(apiUrl: String, apiKey: String): String? {
-        /*
-         * Uses url to compare against each source APIURL's to get the correct custom source preference.
-         * Now having source preference we can do getString("APIKEY")
-         * Authenticates to get the token
-         * Saves the token in the var jwtToken
-         */
-
         val request = POST(
             "$apiUrl/Plugin/authenticate?apiKey=$apiKey&pluginName=Tachiyomi-Kavita",
             body = "{}".toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull()),
         )
         try {
             client.newCall(request).execute().use {
-                if (it.code == 200) {
-                    return it.parseAs<AuthenticationDto>().token
-                }
-                if (it.code == 401) {
-                    logcat(LogPriority.WARN) { "Unauthorized / api key not valid:Cleaned api URL:${apiUrl}Api key is empty:${apiKey.isEmpty()}" }
-                    throw Exception("Unauthorized / api key not valid")
-                }
-                if (it.code == 500) {
-                    logcat(LogPriority.WARN) { "Error fetching jwt token. Cleaned api URL:$apiUrl Api key is empty:${apiKey.isEmpty()}" }
-                    throw Exception("Error fetching jwt token")
+                when (it.code) {
+                    200 -> return it.parseAs<AuthenticationDto>().token
+                    401 -> {
+                        logcat(LogPriority.WARN) { "Unauthorized / api key not valid: Cleaned api URL: $apiUrl, Api key is empty: ${apiKey.isEmpty()}" }
+                        throw IOException("Unauthorized / api key not valid")
+                    }
+                    500 -> {
+                        logcat(LogPriority.WARN) { "Error fetching JWT token. Cleaned api URL: $apiUrl, Api key is empty: ${apiKey.isEmpty()}" }
+                        throw IOException("Error fetching JWT token")
+                    }
+                    else -> {}
                 }
             }
-            // Not sure which one to cathc
+            // Not sure which one to catch
         } catch (e: SocketTimeoutException) {
             logcat(LogPriority.WARN) {
-                "Could not fetch jwt token. Probably due to connectivity issue or the url '$apiUrl' is not available. Skipping"
+                "Could not fetch JWT token. Probably due to connectivity issue or the url '$apiUrl' is not available, skipping"
             }
             return null
         } catch (e: Exception) {
             logcat(LogPriority.ERROR) {
-                "Unhandled Exception fetching jwt token for url: '$apiUrl'"
+                "Unhandled exception fetching JWT token for url: '$apiUrl'"
             }
-            throw e
+            throw IOException(e)
         }
 
         return null
@@ -67,16 +73,17 @@ class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor
         return "${getApiFromUrl(url)}/Series/volumes?seriesId=${getIdFromUrl(url)}"
     }
 
+    /* Strips serie id from URL */
     private fun getIdFromUrl(url: String): Int {
-        /*Strips serie id from Url*/
         return url.substringAfterLast("/").toInt()
     }
 
+    /*
+     * Returns total chapters in the series.
+     * Ignores volumes.
+     * Volumes consisting of 1 file treated as chapter
+     */
     private fun getTotalChapters(url: String): Int {
-        /*Returns total chapters in the series.
-         * Ignores volumes.
-         * Volumes consisting of 1 file treated as chapter
-         */
         val requestUrl = getApiVolumesUrl(url)
         try {
             val listVolumeDto = authClient.newCall(GET(requestUrl))
@@ -103,50 +110,46 @@ class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor
         val serieId = getIdFromUrl(url)
         val requestUrl = "${getApiFromUrl(url)}/Tachiyomi/latest-chapter?seriesId=$serieId"
         try {
-            authClient.newCall(GET(requestUrl))
-                .execute().use {
-                    if (it.code == 200) {
-                        return it.parseAs<ChapterDto>().number!!.replace(",", ".").toFloat()
-                    }
-                    if (it.code == 204) {
-                        return 0F
-                    }
+            authClient.newCall(GET(requestUrl)).execute().use {
+                if (it.code == 200) {
+                    return it.parseAs<ChapterDto>().number!!.replace(",", ".").toFloat()
+                }
+                if (it.code == 204) {
+                    return 0F
                 }
+            }
         } catch (e: Exception) {
-            logcat(LogPriority.WARN, e) { "Exception getting latest chapter read. Could not get itemRequest:$requestUrl" }
+            logcat(LogPriority.WARN, e) { "Exception getting latest chapter read. Could not get itemRequest: $requestUrl" }
             throw e
         }
         return 0F
     }
 
-    suspend fun getTrackSearch(url: String): TrackSearch =
-        withIOContext {
-            try {
-                val serieDto: SeriesDto =
-                    authClient.newCall(GET(url))
-                        .await()
-                        .parseAs<SeriesDto>()
-
-                val track = serieDto.toTrack()
+    suspend fun getTrackSearch(url: String): TrackSearch = withIOContext {
+        try {
+            val serieDto: SeriesDto = authClient.newCall(GET(url))
+                .await()
+                .parseAs()
 
-                track.apply {
-                    cover_url = serieDto.thumbnail_url.toString()
-                    tracking_url = url
-                    total_chapters = getTotalChapters(url)
+            val track = serieDto.toTrack()
+            track.apply {
+                cover_url = serieDto.thumbnail_url.toString()
+                tracking_url = url
+                total_chapters = getTotalChapters(url)
 
-                    title = serieDto.name
-                    status = when (serieDto.pagesRead) {
-                        serieDto.pages -> Kavita.COMPLETED
-                        0 -> Kavita.UNREAD
-                        else -> Kavita.READING
-                    }
-                    last_chapter_read = getLatestChapterRead(url)
+                title = serieDto.name
+                status = when (serieDto.pagesRead) {
+                    serieDto.pages -> Kavita.COMPLETED
+                    0 -> Kavita.UNREAD
+                    else -> Kavita.READING
                 }
-            } catch (e: Exception) {
-                logcat(LogPriority.WARN, e) { "Could not get item: $url" }
-                throw e
+                last_chapter_read = getLatestChapterRead(url)
             }
+        } catch (e: Exception) {
+            logcat(LogPriority.WARN, e) { "Could not get item: $url" }
+            throw e
         }
+    }
 
     suspend fun updateProgress(track: Track): Track {
         val requestUrl = "${getApiFromUrl(track.tracking_url)}/Tachiyomi/mark-chapter-until-as-read?seriesId=${getIdFromUrl(track.tracking_url)}&chapterNumber=${track.last_chapter_read}"

+ 17 - 1
app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/KavitaModels.kt

@@ -21,7 +21,6 @@ data class SeriesDto(
     val created: String? = "",
     val libraryId: Int,
     val libraryName: String? = "",
-
 ) {
     fun toTrack(): TrackSearch = TrackSearch.create(TrackManager.KAVITA).also {
         it.title = name
@@ -63,6 +62,23 @@ data class AuthenticationDto(
     val apiKey: String,
 )
 
+class OAuth(
+    val authentications: List<SourceAuth> = listOf(
+        SourceAuth(1),
+        SourceAuth(2),
+        SourceAuth(3),
+    ),
+) {
+    fun getToken(apiUrl: String): String? {
+        for (authentication in authentications) {
+            if (authentication.apiUrl == apiUrl) {
+                return authentication.jwtToken
+            }
+        }
+        return null
+    }
+}
+
 data class SourceAuth(
     var sourceId: Int,
     var apiUrl: String = "",

+ 0 - 19
app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/OAuth.kt

@@ -1,19 +0,0 @@
-package eu.kanade.tachiyomi.data.track.kavita
-
-class OAuth(
-    val authentications: List<SourceAuth> = listOf<SourceAuth>(
-        SourceAuth(1),
-        SourceAuth(2),
-        SourceAuth(3),
-    ),
-) {
-
-    fun getToken(apiUrl: String): String? {
-        for (authentication in authentications) {
-            if (authentication.apiUrl == apiUrl) {
-                return authentication.jwtToken
-            }
-        }
-        return null
-    }
-}