Add more shikimori api methods
This commit is contained in:
@@ -8,6 +8,6 @@ val detailsModule
|
||||
get() = module {
|
||||
|
||||
viewModel { intent ->
|
||||
DetailsViewModel(intent.get(), get(), get(), get(), get(), get(), get())
|
||||
DetailsViewModel(intent.get(), get(), get(), get(), get(), get(), get(), get())
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.koitharu.kotatsu.details.ui
|
||||
|
||||
import androidx.core.os.LocaleListCompat
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.asFlow
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
@@ -26,6 +27,8 @@ import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.toTitleCase
|
||||
import org.koitharu.kotatsu.shikimori.data.ShikimoriRepository
|
||||
import org.koitharu.kotatsu.shikimori.data.model.ShikimoriMangaInfo
|
||||
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
|
||||
import org.koitharu.kotatsu.utils.SingleLiveEvent
|
||||
import org.koitharu.kotatsu.utils.ext.iterator
|
||||
@@ -39,6 +42,7 @@ class DetailsViewModel(
|
||||
private val trackingRepository: TrackingRepository,
|
||||
private val mangaDataRepository: MangaDataRepository,
|
||||
private val settings: AppSettings,
|
||||
private val shikimoriRepository: ShikimoriRepository,
|
||||
) : BaseViewModel() {
|
||||
|
||||
private var loadingJob: Job
|
||||
@@ -85,6 +89,7 @@ class DetailsViewModel(
|
||||
.asLiveData(viewModelScope.coroutineContext)
|
||||
|
||||
val onMangaRemoved = SingleLiveEvent<Manga>()
|
||||
val shikimoriInfo = MutableLiveData<ShikimoriMangaInfo?>()
|
||||
|
||||
val branches = mangaData.map {
|
||||
it?.chapters?.mapToSet { x -> x.branch }?.sortedBy { x -> x }.orEmpty()
|
||||
@@ -204,6 +209,7 @@ class DetailsViewModel(
|
||||
localMangaRepository.findSavedManga(manga)
|
||||
}
|
||||
}.getOrNull()
|
||||
findShikimoriManga(manga)
|
||||
}
|
||||
|
||||
private fun mapChapters(
|
||||
@@ -312,4 +318,18 @@ class DetailsViewModel(
|
||||
it.chapter.name.contains(query, ignoreCase = true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun findShikimoriManga(manga: Manga) {
|
||||
if (!shikimoriRepository.isAuthorized) {
|
||||
return
|
||||
}
|
||||
launchJob(Dispatchers.Default) {
|
||||
val data = runCatching {
|
||||
shikimoriRepository.findMangaInfo(manga)
|
||||
}.getOrNull()
|
||||
if (data != null) {
|
||||
shikimoriInfo.postValue(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,11 @@ package org.koitharu.kotatsu.shikimori.data
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.koitharu.kotatsu.parsers.util.await
|
||||
import org.koitharu.kotatsu.parsers.util.parseJson
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSON
|
||||
import org.koitharu.kotatsu.shikimori.data.model.ShikimoriManga
|
||||
import org.koitharu.kotatsu.shikimori.data.model.ShikimoriMangaInfo
|
||||
import org.koitharu.kotatsu.shikimori.data.model.ShikimoriUser
|
||||
|
||||
private const val CLIENT_ID = "Mw6F0tPEOgyV7F9U9Twg50Q8SndMY7hzIOfXg0AX_XU"
|
||||
@@ -49,4 +52,41 @@ class ShikimoriRepository(
|
||||
val response = okHttp.newCall(request.build()).await().parseJson()
|
||||
return ShikimoriUser(response)
|
||||
}
|
||||
|
||||
suspend fun findMangaInfo(manga: Manga): ShikimoriMangaInfo? {
|
||||
val q = manga.title.urlEncoded()
|
||||
val request = Request.Builder()
|
||||
.get()
|
||||
.url("https://shikimori.one/api/mangas?limit=20&search=$q&censored=false")
|
||||
val response = okHttp.newCall(request.build()).await().parseJsonArray()
|
||||
val candidates = response.mapJSON { ShikimoriManga(it) }
|
||||
val bestCandidate = candidates.minByOrNull {
|
||||
it.name.levenshteinDistance(manga.title)
|
||||
} ?: return null
|
||||
return getMangaInfo(bestCandidate.id)
|
||||
}
|
||||
|
||||
suspend fun getRelatedManga(id: Long): List<ShikimoriManga> {
|
||||
val request = Request.Builder()
|
||||
.get()
|
||||
.url("https://shikimori.one/api/mangas/$id/related")
|
||||
val response = okHttp.newCall(request.build()).await().parseJsonArray()
|
||||
return response.mapJSON { jo -> ShikimoriManga(jo) }
|
||||
}
|
||||
|
||||
suspend fun getSimilarManga(id: Long): List<ShikimoriManga> {
|
||||
val request = Request.Builder()
|
||||
.get()
|
||||
.url("https://shikimori.one/api/mangas/$id/similar")
|
||||
val response = okHttp.newCall(request.build()).await().parseJsonArray()
|
||||
return response.mapJSON { jo -> ShikimoriManga(jo) }
|
||||
}
|
||||
|
||||
suspend fun getMangaInfo(id: Long): ShikimoriMangaInfo {
|
||||
val request = Request.Builder()
|
||||
.get()
|
||||
.url("https://shikimori.one/api/mangas/$id")
|
||||
val response = okHttp.newCall(request.build()).await().parseJson()
|
||||
return ShikimoriMangaInfo(response)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.koitharu.kotatsu.shikimori.data.model
|
||||
|
||||
import org.json.JSONObject
|
||||
|
||||
class ShikimoriManga(
|
||||
val id: Long,
|
||||
val name: String,
|
||||
val cover: String,
|
||||
val url: String,
|
||||
) {
|
||||
|
||||
constructor(json: JSONObject) : this(
|
||||
id = json.getLong("id"),
|
||||
name = json.getString("name"),
|
||||
cover = json.getJSONObject("image").getString("preview"),
|
||||
url = json.getString("url"),
|
||||
)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as ShikimoriManga
|
||||
|
||||
if (id != other.id) return false
|
||||
if (name != other.name) return false
|
||||
if (cover != other.cover) return false
|
||||
if (url != other.url) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = id.hashCode()
|
||||
result = 31 * result + name.hashCode()
|
||||
result = 31 * result + cover.hashCode()
|
||||
result = 31 * result + url.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "ShikimoriManga #$id \"$name\" $url"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.koitharu.kotatsu.shikimori.data.model
|
||||
|
||||
import org.json.JSONObject
|
||||
|
||||
class ShikimoriMangaInfo(
|
||||
val id: Long,
|
||||
val name: String,
|
||||
val cover: String,
|
||||
val url: String,
|
||||
val descriptionHtml: String,
|
||||
) {
|
||||
|
||||
constructor(json: JSONObject) : this(
|
||||
id = json.getLong("id"),
|
||||
name = json.getString("name"),
|
||||
cover = json.getJSONObject("image").getString("preview"),
|
||||
url = json.getString("url"),
|
||||
descriptionHtml = json.getString("description_html"),
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user