mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Changed Kitsu to use Algoria search directly (#1514)
* Changed Kitsu to use Algoria search directly, was recommended by the Kitsu Dev team * remove extra line * fixed end date bug added filtering out novel back in * save the retrofit instances locally for search.
This commit is contained in:
		@@ -24,6 +24,22 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
 | 
			
		||||
            .build()
 | 
			
		||||
            .create(KitsuApi.Rest::class.java)
 | 
			
		||||
 | 
			
		||||
    private val searchRest = Retrofit.Builder()
 | 
			
		||||
            .baseUrl(algoliaKeyUrl)
 | 
			
		||||
            .client(client)
 | 
			
		||||
            .addConverterFactory(GsonConverterFactory.create())
 | 
			
		||||
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
 | 
			
		||||
            .build()
 | 
			
		||||
            .create(KitsuApi.SearchKeyRest::class.java)
 | 
			
		||||
 | 
			
		||||
    private val algoliaRest = Retrofit.Builder()
 | 
			
		||||
            .baseUrl(algoliaUrl)
 | 
			
		||||
            .client(client)
 | 
			
		||||
            .addConverterFactory(GsonConverterFactory.create())
 | 
			
		||||
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
 | 
			
		||||
            .build()
 | 
			
		||||
            .create(KitsuApi.AgoliaSearchRest::class.java)
 | 
			
		||||
 | 
			
		||||
    fun addLibManga(track: Track, userId: String): Observable<Track> {
 | 
			
		||||
        return Observable.defer {
 | 
			
		||||
            // @formatter:off
 | 
			
		||||
@@ -48,7 +64,6 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
 | 
			
		||||
                            )
 | 
			
		||||
                    )
 | 
			
		||||
            )
 | 
			
		||||
            // @formatter:on
 | 
			
		||||
 | 
			
		||||
            rest.addLibManga(jsonObject("data" to data))
 | 
			
		||||
                    .map { json ->
 | 
			
		||||
@@ -77,12 +92,25 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    fun search(query: String): Observable<List<TrackSearch>> {
 | 
			
		||||
        return rest.search(query)
 | 
			
		||||
        return searchRest
 | 
			
		||||
                .getKey().map { json ->
 | 
			
		||||
                    json["media"].asJsonObject["key"].string
 | 
			
		||||
                }.flatMap { key ->
 | 
			
		||||
                    algoliaSearch(key, query)
 | 
			
		||||
                }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private fun algoliaSearch(key: String, query: String): Observable<List<TrackSearch>> {
 | 
			
		||||
        val jsonObject = jsonObject("params" to "query=$query$algoliaFilter")
 | 
			
		||||
        return algoliaRest
 | 
			
		||||
                .getSearchQuery(algoliaAppId, key, jsonObject)
 | 
			
		||||
                .map { json ->
 | 
			
		||||
                    val data = json["data"].array
 | 
			
		||||
                    data.map { KitsuManga(it.obj) }
 | 
			
		||||
                            .filter { it.type != "novel" }
 | 
			
		||||
                    val data = json["hits"].array
 | 
			
		||||
                    data.map { KitsuSearchManga(it.obj) }
 | 
			
		||||
                            .filter { it.subType != "novel" }
 | 
			
		||||
                            .map { it.toTrack() }
 | 
			
		||||
                }
 | 
			
		||||
    }
 | 
			
		||||
@@ -143,10 +171,6 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
 | 
			
		||||
                @Body data: JsonObject
 | 
			
		||||
        ): Observable<JsonObject>
 | 
			
		||||
 | 
			
		||||
        @GET("manga")
 | 
			
		||||
        fun search(
 | 
			
		||||
                @Query("filter[text]", encoded = true) query: String
 | 
			
		||||
        ): Observable<JsonObject>
 | 
			
		||||
 | 
			
		||||
        @GET("library-entries")
 | 
			
		||||
        fun findLibManga(
 | 
			
		||||
@@ -168,6 +192,16 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private interface SearchKeyRest {
 | 
			
		||||
        @GET("media/")
 | 
			
		||||
        fun getKey(): Observable<JsonObject>
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private interface AgoliaSearchRest {
 | 
			
		||||
        @POST("query/")
 | 
			
		||||
        fun getSearchQuery(@Header("X-Algolia-Application-Id") appid: String, @Header("X-Algolia-API-Key") key: String, @Body json: JsonObject): Observable<JsonObject>
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private interface LoginRest {
 | 
			
		||||
 | 
			
		||||
        @FormUrlEncoded
 | 
			
		||||
@@ -188,6 +222,11 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
 | 
			
		||||
        private const val baseUrl = "https://kitsu.io/api/edge/"
 | 
			
		||||
        private const val loginUrl = "https://kitsu.io/api/"
 | 
			
		||||
        private const val baseMangaUrl = "https://kitsu.io/manga/"
 | 
			
		||||
        private const val algoliaKeyUrl = "https://kitsu.io/api/edge/algolia-keys/"
 | 
			
		||||
        private const val algoliaUrl = "https://AWQO5J657S-dsn.algolia.net/1/indexes/production_media/"
 | 
			
		||||
        private const val algoliaAppId = "AWQO5J657S"
 | 
			
		||||
        private const val algoliaFilter = "&facetFilters=%5B%22kind%3Amanga%22%5D&attributesToRetrieve=%5B%22synopsis%22%2C%22canonicalTitle%22%2C%22chapterCount%22%2C%22posterImage%22%2C%22startDate%22%2C%22subtype%22%2C%22endDate%22%2C%20%22id%22%5D"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        fun mangaUrl(remoteId: Int): String {
 | 
			
		||||
            return baseMangaUrl + remoteId
 | 
			
		||||
 
 | 
			
		||||
@@ -7,38 +7,59 @@ import eu.kanade.tachiyomi.data.database.models.Track
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.TrackManager
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
 | 
			
		||||
 | 
			
		||||
open class KitsuManga(obj: JsonObject) {
 | 
			
		||||
class KitsuSearchManga(obj: JsonObject) {
 | 
			
		||||
    val id by obj.byInt
 | 
			
		||||
    val canonicalTitle by obj["attributes"].byString
 | 
			
		||||
    val chapterCount = obj["attributes"].obj.get("chapterCount").nullInt
 | 
			
		||||
    val type = obj["attributes"].obj.get("mangaType").nullString.orEmpty()
 | 
			
		||||
    val original by obj["attributes"].obj["posterImage"].byString
 | 
			
		||||
    val synopsis by obj["attributes"].byString
 | 
			
		||||
    val startDate = obj["attributes"].obj.get("startDate").nullString.orEmpty()
 | 
			
		||||
    open val status = obj["attributes"].obj.get("status").nullString.orEmpty()
 | 
			
		||||
    private val canonicalTitle by obj.byString
 | 
			
		||||
    private val chapterCount = obj.get("chapterCount").nullInt
 | 
			
		||||
    val subType = obj.get("subType").nullString
 | 
			
		||||
    val original by obj["posterImage"].byString
 | 
			
		||||
    private val synopsis by obj.byString
 | 
			
		||||
    private val startDate = obj.get("startDate").nullString
 | 
			
		||||
    private val endDate = obj.get("endDate").nullString
 | 
			
		||||
 | 
			
		||||
    @CallSuper
 | 
			
		||||
    open fun toTrack() = TrackSearch.create(TrackManager.KITSU).apply {
 | 
			
		||||
        media_id = this@KitsuManga.id
 | 
			
		||||
        media_id = this@KitsuSearchManga.id
 | 
			
		||||
        title = canonicalTitle
 | 
			
		||||
        total_chapters = chapterCount ?: 0
 | 
			
		||||
        cover_url = original
 | 
			
		||||
        summary = synopsis
 | 
			
		||||
        tracking_url = KitsuApi.mangaUrl(media_id)
 | 
			
		||||
        publishing_status = this@KitsuManga.status
 | 
			
		||||
        publishing_type = type
 | 
			
		||||
 | 
			
		||||
        if (endDate == null) {
 | 
			
		||||
            publishing_status = "Publishing"
 | 
			
		||||
        } else {
 | 
			
		||||
            publishing_status = "Finished"
 | 
			
		||||
        }
 | 
			
		||||
        publishing_type = subType ?: ""
 | 
			
		||||
        start_date = startDate.orEmpty()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class KitsuLibManga(obj: JsonObject, manga: JsonObject) : KitsuManga(manga) {
 | 
			
		||||
    val libraryId by obj.byInt("id")
 | 
			
		||||
    override val status by obj["attributes"].byString
 | 
			
		||||
    val ratingTwenty = obj["attributes"].obj.get("ratingTwenty").nullString
 | 
			
		||||
 | 
			
		||||
class KitsuLibManga(obj: JsonObject, manga: JsonObject) {
 | 
			
		||||
    val id by manga.byInt
 | 
			
		||||
    private val canonicalTitle by manga["attributes"].byString
 | 
			
		||||
    private val chapterCount = manga["attributes"].obj.get("chapterCount").nullInt
 | 
			
		||||
    val type = manga["attributes"].obj.get("mangaType").nullString.orEmpty()
 | 
			
		||||
    val original by manga["attributes"].obj["posterImage"].byString
 | 
			
		||||
    private val synopsis by manga["attributes"].byString
 | 
			
		||||
    private val startDate = manga["attributes"].obj.get("startDate").nullString.orEmpty()
 | 
			
		||||
    private val libraryId by obj.byInt("id")
 | 
			
		||||
    val status by obj["attributes"].byString
 | 
			
		||||
    private val ratingTwenty = obj["attributes"].obj.get("ratingTwenty").nullString
 | 
			
		||||
    val progress by obj["attributes"].byInt
 | 
			
		||||
 | 
			
		||||
    override fun toTrack() = super.toTrack().apply {
 | 
			
		||||
        media_id = libraryId // TODO migrate media ids to library ids
 | 
			
		||||
    open fun toTrack() = TrackSearch.create(TrackManager.KITSU).apply {
 | 
			
		||||
        media_id = libraryId
 | 
			
		||||
        title = canonicalTitle
 | 
			
		||||
        total_chapters = chapterCount ?: 0
 | 
			
		||||
        cover_url = original
 | 
			
		||||
        summary = synopsis
 | 
			
		||||
        tracking_url = KitsuApi.mangaUrl(media_id)
 | 
			
		||||
        publishing_status = this@KitsuLibManga.status
 | 
			
		||||
        publishing_type = type
 | 
			
		||||
        start_date = startDate
 | 
			
		||||
        status = toTrackStatus()
 | 
			
		||||
        score = ratingTwenty?.let { it.toInt() / 2f } ?: 0f
 | 
			
		||||
        last_chapter_read = progress
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user