Implement MyAnimeList recommendations (#7)
Co-authored-by: she11sh0cked <she11sh0cked@users.noreply.github.com>
This commit is contained in:
parent
d2b0319d63
commit
7d2ded5944
@ -10,6 +10,7 @@ import com.google.gson.JsonParser
|
|||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||||
import eu.kanade.tachiyomi.source.model.SMangaImpl
|
import eu.kanade.tachiyomi.source.model.SMangaImpl
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
@ -17,10 +18,81 @@ import okhttp3.RequestBody.Companion.toRequestBody
|
|||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.schedulers.Schedulers
|
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()
|
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 =
|
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 body = payload.toString().toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url(apiUrl)
|
.url(anilistEndpoint)
|
||||||
.post(body)
|
.post(body)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
@ -71,7 +143,7 @@ open class RecommendsPager(val title: String) : Pager() {
|
|||||||
val edges = recommendations["edges"].array
|
val edges = recommendations["edges"].array
|
||||||
edges.map {
|
edges.map {
|
||||||
val rec = it["node"]["mediaRecommendation"].obj
|
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 {
|
SMangaImpl().apply {
|
||||||
this.title = rec["title"].obj["romaji"].string
|
this.title = rec["title"].obj["romaji"].string
|
||||||
this.thumbnail_url = rec["coverImage"].obj["large"].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
|
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 {
|
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 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user