Implement MyAnimeList recommendations (#7)

Co-authored-by: she11sh0cked <she11sh0cked@users.noreply.github.com>
This commit is contained in:
she11sh0cked 2020-05-17 21:38:38 +02:00 committed by GitHub
parent d2b0319d63
commit 7d2ded5944
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -10,6 +10,7 @@ import com.google.gson.JsonParser
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.SMangaImpl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
@ -17,10 +18,81 @@ import okhttp3.RequestBody.Companion.toRequestBody
import rx.Observable
import rx.schedulers.Schedulers
open class RecommendsPager(val title: String) : Pager() {
open class RecommendsPager(val title: String, val preferredApi: API = API.MYANIMELIST) : Pager() {
private val client = OkHttpClient.Builder().build()
override fun requestNext(): Observable<MangasPage> {
private fun myAnimeList(): Observable<List<SMangaImpl>>? {
fun getId(): Observable<String> {
val endpoint =
myAnimeListEndpoint.toHttpUrlOrNull()
?: throw Exception("Could not convert endpoint url")
val urlBuilder = endpoint.newBuilder()
urlBuilder.addPathSegment("search")
urlBuilder.addPathSegment("manga")
urlBuilder.addQueryParameter("q", title)
val url = urlBuilder.build().toUrl()
val request = Request.Builder()
.url(url)
.get()
.build()
return client.newCall(request)
.asObservableSuccess().subscribeOn(Schedulers.io())
.map { netResponse ->
val responseBody = netResponse.body?.string().orEmpty()
if (responseBody.isEmpty()) {
throw Exception("Null Response")
}
val response = JsonParser.parseString(responseBody).obj
val results = response["results"].array
val firstResult = results[0].obj
val id = firstResult["mal_id"].string
if (id.isEmpty()) {
throw Exception("Not found")
}
id
}
}
return getId().map { id ->
val endpoint =
myAnimeListEndpoint.toHttpUrlOrNull()
?: throw Exception("Could not convert endpoint url")
val urlBuilder = endpoint.newBuilder()
urlBuilder.addPathSegment("manga")
urlBuilder.addPathSegment(id)
urlBuilder.addPathSegment("recommendations")
val url = urlBuilder.build().toUrl()
val request = Request.Builder()
.url(url)
.get()
.build()
client.newCall(request)
.asObservableSuccess().subscribeOn(Schedulers.io())
.map { netResponse ->
val responseBody = netResponse.body?.string().orEmpty()
if (responseBody.isEmpty()) {
throw Exception("Null Response")
}
val response = JsonParser.parseString(responseBody).obj
val recommendations = response["recommendations"].array
recommendations.map { rec ->
Log.d("MYANIMELIST RECOMMEND", "${rec["title"].string}")
SMangaImpl().apply {
this.title = rec["title"].string
this.thumbnail_url = rec["image_url"].string
this.initialized = true
this.url = rec["url"].string
}
}
}.toBlocking().first()
}
}
private fun anilist(): Observable<List<SMangaImpl>>? {
val query =
"""
{
@ -53,7 +125,7 @@ open class RecommendsPager(val title: String) : Pager() {
)
val body = payload.toString().toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
val request = Request.Builder()
.url(apiUrl)
.url(anilistEndpoint)
.post(body)
.build()
@ -71,7 +143,7 @@ open class RecommendsPager(val title: String) : Pager() {
val edges = recommendations["edges"].array
edges.map {
val rec = it["node"]["mediaRecommendation"].obj
Log.d("RECOMMEND", "${rec["title"].obj["romaji"].string}")
Log.d("ANILIST RECOMMEND", "${rec["title"].obj["romaji"].string}")
SMangaImpl().apply {
this.title = rec["title"].obj["romaji"].string
this.thumbnail_url = rec["coverImage"].obj["large"].string
@ -79,13 +151,39 @@ open class RecommendsPager(val title: String) : Pager() {
this.url = rec["siteUrl"].string
}
}
}.map {
MangasPage(it, false)
}.doOnNext {
onPageReceived(it)
}
}
override fun requestNext(): Observable<MangasPage> {
val apiList = API.values().toMutableList()
apiList.removeAt(apiList.indexOf(preferredApi))
apiList.add(0, preferredApi)
var recommendations: Observable<List<SMangaImpl>>? = null
for (api in apiList) {
recommendations = when (api) {
API.MYANIMELIST -> myAnimeList()
API.ANILIST -> anilist()
}
?: throw Exception("Could not get recommendations")
val recommendationsBlocking = recommendations.toBlocking().first()
if (recommendationsBlocking.isNotEmpty()) {
break
}
}
return recommendations!!.map {
MangasPage(it, false)
}.doOnNext {
onPageReceived(it)
}
}
companion object {
const val apiUrl = "https://graphql.anilist.co/"
private const val myAnimeListEndpoint = "https://api.jikan.moe/v3/"
private const val anilistEndpoint = "https://graphql.anilist.co/"
enum class API { MYANIMELIST, ANILIST }
}
}