|
|
|
@ -1,6 +1,8 @@
|
|
|
|
|
package eu.kanade.tachiyomi.data.track.kitsu
|
|
|
|
|
|
|
|
|
|
import com.github.salomonbrys.kotson.*
|
|
|
|
|
import com.google.gson.JsonObject
|
|
|
|
|
import eu.kanade.tachiyomi.data.database.models.Track
|
|
|
|
|
import eu.kanade.tachiyomi.data.network.POST
|
|
|
|
|
import okhttp3.FormBody
|
|
|
|
|
import okhttp3.OkHttpClient
|
|
|
|
@ -10,29 +12,178 @@ import retrofit2.converter.gson.GsonConverterFactory
|
|
|
|
|
import retrofit2.http.*
|
|
|
|
|
import rx.Observable
|
|
|
|
|
|
|
|
|
|
interface KitsuApi {
|
|
|
|
|
class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor) {
|
|
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
|
private const val clientId = "dd031b32d2f56c990b1425efe6c42ad847e7fe3ab46bf1299f05ecd856bdb7dd"
|
|
|
|
|
private const val clientSecret = "54d7307928f63414defd96399fc31ba847961ceaecef3a5fd93144e960c0e151"
|
|
|
|
|
private const val baseUrl = "https://kitsu.io/api/edge/"
|
|
|
|
|
private const val loginUrl = "https://kitsu.io/api/"
|
|
|
|
|
|
|
|
|
|
fun createService(client: OkHttpClient) = Retrofit.Builder()
|
|
|
|
|
.baseUrl(baseUrl)
|
|
|
|
|
.client(client)
|
|
|
|
|
.addConverterFactory(GsonConverterFactory.create())
|
|
|
|
|
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
|
|
|
|
|
.build()
|
|
|
|
|
.create(KitsuApi::class.java)
|
|
|
|
|
private val rest = Retrofit.Builder()
|
|
|
|
|
.baseUrl(baseUrl)
|
|
|
|
|
.client(client.newBuilder().addInterceptor(interceptor).build())
|
|
|
|
|
.addConverterFactory(GsonConverterFactory.create())
|
|
|
|
|
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
|
|
|
|
|
.build()
|
|
|
|
|
.create(KitsuApi.Rest::class.java)
|
|
|
|
|
|
|
|
|
|
fun createLoginService(client: OkHttpClient) = Retrofit.Builder()
|
|
|
|
|
fun login(username: String, password: String): Observable<OAuth> {
|
|
|
|
|
return Retrofit.Builder()
|
|
|
|
|
.baseUrl(loginUrl)
|
|
|
|
|
.client(client)
|
|
|
|
|
.addConverterFactory(GsonConverterFactory.create())
|
|
|
|
|
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
|
|
|
|
|
.build()
|
|
|
|
|
.create(KitsuApi::class.java)
|
|
|
|
|
.create(KitsuApi.LoginRest::class.java)
|
|
|
|
|
.requestAccessToken(username, password)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun getCurrentUser(): Observable<String> {
|
|
|
|
|
return rest.getCurrentUser().map { it["data"].array[0]["id"].string }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun search(query: String): Observable<List<Track>> {
|
|
|
|
|
return rest.search(query)
|
|
|
|
|
.map { json ->
|
|
|
|
|
val data = json["data"].array
|
|
|
|
|
data.map { KitsuManga(it.obj).toTrack() }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun findLibManga(userId: String, remoteId: Int): Observable<Track?> {
|
|
|
|
|
return rest.findLibManga(userId, remoteId)
|
|
|
|
|
.map { json ->
|
|
|
|
|
val data = json["data"].array
|
|
|
|
|
if (data.size() > 0) {
|
|
|
|
|
KitsuLibManga(data[0].obj, json["included"].array[0].obj).toTrack()
|
|
|
|
|
} else {
|
|
|
|
|
null
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun addLibManga(track: Track, userId: String): Observable<Track> {
|
|
|
|
|
return Observable.defer {
|
|
|
|
|
// @formatter:off
|
|
|
|
|
val data = jsonObject(
|
|
|
|
|
"type" to "libraryEntries",
|
|
|
|
|
"attributes" to jsonObject(
|
|
|
|
|
"status" to track.toKitsuStatus(),
|
|
|
|
|
"progress" to track.last_chapter_read
|
|
|
|
|
),
|
|
|
|
|
"relationships" to jsonObject(
|
|
|
|
|
"user" to jsonObject(
|
|
|
|
|
"data" to jsonObject(
|
|
|
|
|
"id" to userId,
|
|
|
|
|
"type" to "users"
|
|
|
|
|
)
|
|
|
|
|
),
|
|
|
|
|
"media" to jsonObject(
|
|
|
|
|
"data" to jsonObject(
|
|
|
|
|
"id" to track.remote_id,
|
|
|
|
|
"type" to "manga"
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
// @formatter:on
|
|
|
|
|
|
|
|
|
|
rest.addLibManga(jsonObject("data" to data))
|
|
|
|
|
.map { json ->
|
|
|
|
|
track.remote_id = json["data"]["id"].int
|
|
|
|
|
track
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun updateLibManga(track: Track): Observable<Track> {
|
|
|
|
|
return Observable.defer {
|
|
|
|
|
// @formatter:off
|
|
|
|
|
val data = jsonObject(
|
|
|
|
|
"type" to "libraryEntries",
|
|
|
|
|
"id" to track.remote_id,
|
|
|
|
|
"attributes" to jsonObject(
|
|
|
|
|
"status" to track.toKitsuStatus(),
|
|
|
|
|
"progress" to track.last_chapter_read,
|
|
|
|
|
"rating" to track.toKitsuScore()
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
// @formatter:on
|
|
|
|
|
|
|
|
|
|
rest.updateLibManga(track.remote_id, jsonObject("data" to data))
|
|
|
|
|
.map { track }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun getLibManga(track: Track): Observable<Track> {
|
|
|
|
|
return rest.getLibManga(track.remote_id)
|
|
|
|
|
.map { json ->
|
|
|
|
|
val data = json["data"].array
|
|
|
|
|
if (data.size() > 0) {
|
|
|
|
|
val include = json["included"].array[0].obj
|
|
|
|
|
KitsuLibManga(data[0].obj, include).toTrack()
|
|
|
|
|
} else {
|
|
|
|
|
throw Exception("Could not find manga")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private interface Rest {
|
|
|
|
|
|
|
|
|
|
@GET("users")
|
|
|
|
|
fun getCurrentUser(
|
|
|
|
|
@Query("filter[self]", encoded = true) self: Boolean = true
|
|
|
|
|
): Observable<JsonObject>
|
|
|
|
|
|
|
|
|
|
@GET("manga")
|
|
|
|
|
fun search(
|
|
|
|
|
@Query("filter[text]", encoded = true) query: String
|
|
|
|
|
): Observable<JsonObject>
|
|
|
|
|
|
|
|
|
|
@GET("library-entries")
|
|
|
|
|
fun getLibManga(
|
|
|
|
|
@Query("filter[id]", encoded = true) remoteId: Int,
|
|
|
|
|
@Query("include") includes: String = "media"
|
|
|
|
|
): Observable<JsonObject>
|
|
|
|
|
|
|
|
|
|
@GET("library-entries")
|
|
|
|
|
fun findLibManga(
|
|
|
|
|
@Query("filter[user_id]", encoded = true) userId: String,
|
|
|
|
|
@Query("filter[media_id]", encoded = true) remoteId: Int,
|
|
|
|
|
@Query("page[limit]", encoded = true) limit: Int = 10000,
|
|
|
|
|
@Query("include") includes: String = "media"
|
|
|
|
|
): Observable<JsonObject>
|
|
|
|
|
|
|
|
|
|
@Headers("Content-Type: application/vnd.api+json")
|
|
|
|
|
@POST("library-entries")
|
|
|
|
|
fun addLibManga(
|
|
|
|
|
@Body data: JsonObject
|
|
|
|
|
): Observable<JsonObject>
|
|
|
|
|
|
|
|
|
|
@Headers("Content-Type: application/vnd.api+json")
|
|
|
|
|
@PATCH("library-entries/{id}")
|
|
|
|
|
fun updateLibManga(
|
|
|
|
|
@Path("id") remoteId: Int,
|
|
|
|
|
@Body data: JsonObject
|
|
|
|
|
): Observable<JsonObject>
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private interface LoginRest {
|
|
|
|
|
|
|
|
|
|
@FormUrlEncoded
|
|
|
|
|
@POST("oauth/token")
|
|
|
|
|
fun requestAccessToken(
|
|
|
|
|
@Field("username") username: String,
|
|
|
|
|
@Field("password") password: String,
|
|
|
|
|
@Field("grant_type") grantType: String = "password",
|
|
|
|
|
@Field("client_id") client_id: String = clientId,
|
|
|
|
|
@Field("client_secret") client_secret: String = clientSecret
|
|
|
|
|
): Observable<OAuth>
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
|
private const val clientId = "dd031b32d2f56c990b1425efe6c42ad847e7fe3ab46bf1299f05ecd856bdb7dd"
|
|
|
|
|
private const val clientSecret = "54d7307928f63414defd96399fc31ba847961ceaecef3a5fd93144e960c0e151"
|
|
|
|
|
private const val baseUrl = "https://kitsu.io/api/edge/"
|
|
|
|
|
private const val loginUrl = "https://kitsu.io/api/"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fun refreshTokenRequest(token: String) = POST("${loginUrl}oauth/token",
|
|
|
|
|
body = FormBody.Builder()
|
|
|
|
@ -41,53 +192,7 @@ interface KitsuApi {
|
|
|
|
|
.add("client_secret", clientSecret)
|
|
|
|
|
.add("refresh_token", token)
|
|
|
|
|
.build())
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@FormUrlEncoded
|
|
|
|
|
@POST("oauth/token")
|
|
|
|
|
fun requestAccessToken(
|
|
|
|
|
@Field("username") username: String,
|
|
|
|
|
@Field("password") password: String,
|
|
|
|
|
@Field("grant_type") grantType: String = "password",
|
|
|
|
|
@Field("client_id") client_id: String = clientId,
|
|
|
|
|
@Field("client_secret") client_secret: String = clientSecret
|
|
|
|
|
) : Observable<OAuth>
|
|
|
|
|
|
|
|
|
|
@GET("users")
|
|
|
|
|
fun getCurrentUser(
|
|
|
|
|
@Query("filter[self]", encoded = true) self: Boolean = true
|
|
|
|
|
) : Observable<JsonObject>
|
|
|
|
|
|
|
|
|
|
@GET("manga")
|
|
|
|
|
fun search(
|
|
|
|
|
@Query("filter[text]", encoded = true) query: String
|
|
|
|
|
): Observable<JsonObject>
|
|
|
|
|
|
|
|
|
|
@GET("library-entries")
|
|
|
|
|
fun getLibManga(
|
|
|
|
|
@Query("filter[id]", encoded = true) remoteId: Int,
|
|
|
|
|
@Query("include") includes: String = "media"
|
|
|
|
|
) : Observable<JsonObject>
|
|
|
|
|
|
|
|
|
|
@GET("library-entries")
|
|
|
|
|
fun findLibManga(
|
|
|
|
|
@Query("filter[user_id]", encoded = true) userId: String,
|
|
|
|
|
@Query("filter[media_id]", encoded = true) remoteId: Int,
|
|
|
|
|
@Query("page[limit]", encoded = true) limit: Int = 10000,
|
|
|
|
|
@Query("include") includes: String = "media"
|
|
|
|
|
) : Observable<JsonObject>
|
|
|
|
|
|
|
|
|
|
@Headers("Content-Type: application/vnd.api+json")
|
|
|
|
|
@POST("library-entries")
|
|
|
|
|
fun addLibManga(
|
|
|
|
|
@Body data: JsonObject
|
|
|
|
|
) : Observable<JsonObject>
|
|
|
|
|
|
|
|
|
|
@Headers("Content-Type: application/vnd.api+json")
|
|
|
|
|
@PATCH("library-entries/{id}")
|
|
|
|
|
fun updateLibManga(
|
|
|
|
|
@Path("id") remoteId: Int,
|
|
|
|
|
@Body data: JsonObject
|
|
|
|
|
) : Observable<JsonObject>
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|