|
@@ -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}"
|