feat(en/oppaistream): Fetch Anilist covers (#2055)

This commit is contained in:
Nitin Dahale
2023-08-17 16:35:32 +05:30
committed by GitHub
parent 3ee344ab54
commit 07f45857a6
2 changed files with 114 additions and 2 deletions

View File

@ -5,7 +5,7 @@ ext {
extName = 'Oppai Stream' extName = 'Oppai Stream'
pkgNameSuffix = 'en.oppaistream' pkgNameSuffix = 'en.oppaistream'
extClass = '.OppaiStream' extClass = '.OppaiStream'
extVersionCode = 1 extVersionCode = 2
containsNsfw = true containsNsfw = true
} }

View File

@ -16,6 +16,12 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.FormBody
import okhttp3.Headers import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -131,16 +137,92 @@ class OppaiStream : ParsedAnimeHttpSource(), ConfigurableAnimeSource {
} }
} }
// Function to fetch thumbnail URL using AniList GraphQL API
// Only use in animeDetailsParse.
private fun fetchThumbnailUrlByTitle(title: String): Pair<String?, MutableList<String>>? {
val client = OkHttpClient()
val query = """
query {
Media(search: "$title", type: ANIME, isAdult: true) {
coverImage {
extraLarge
large
}
studios {
nodes {
name
}
}
}
}
""".trimIndent()
val requestBody = FormBody.Builder()
.add("query", query)
.build()
val request = Request.Builder()
.url("https://graphql.anilist.co")
.post(requestBody)
.build()
val response = client.newCall(request).execute()
val responseString = response.body?.string()
return parseThumbnailUrlFromResponse(responseString)
}
private fun parseThumbnailUrlFromResponse(responseString: String?): Pair<String?, MutableList<String>>? {
val responseJson = Json.parseToJsonElement(responseString ?: "") as? JsonObject ?: return null
val data = responseJson["data"] as? JsonObject ?: return null
val media = data["Media"] as? JsonObject ?: return null
val coverImage = media["coverImage"] as? JsonObject ?: return null
val coverURL = when (preferences.getString(PREF_COVER_QUALITY, "large")) {
"extraLarge" -> coverImage["extraLarge"]?.jsonPrimitive?.content
"large" -> coverImage["large"]?.jsonPrimitive?.content
else -> null
}
val studiosList = mutableListOf<String>()
val studios = media["studios"]?.jsonObject?.get("nodes")?.jsonArray
studios?.forEach { studio ->
val name = studio.jsonObject["name"]?.jsonPrimitive?.content
if (!name.isNullOrEmpty()) {
studiosList.add(name)
}
}
return Pair(coverURL, studiosList)
}
override fun getFilterList() = FILTERS override fun getFilterList() = FILTERS
// details // details
override fun animeDetailsParse(document: Document): SAnime { override fun animeDetailsParse(document: Document): SAnime {
return SAnime.create().apply { return SAnime.create().apply {
// Fetch from from Anilist when "Anilist Cover" is selected in settings
val selectedCoverSource = preferences.getString(PREF_COVER_SOURCE, "Anilist-Cover")
val newTitle = document.select("div.effect-title").text().replace(Regex("[^a-zA-Z0-9\\s!.:\"]"), " ")
val thumbnailUrl = if (selectedCoverSource == "Anilist-Cover") {
fetchThumbnailUrlByTitle(newTitle)
} else {
null // Use default cover
}
title = document.select("div.effect-title").text() title = document.select("div.effect-title").text()
description = document.select("div.description").text() description = document.select("div.description").text()
genre = document.select("div.tags a").joinToString { it.text() } genre = document.select("div.tags a").joinToString { it.text() }
author = document.select("div.content a.red").joinToString { it.text() } author = document.select("div.content a.red").joinToString { it.text() }
thumbnail_url = document.select("#player").attr("data-poster")
// thumbnail_url = document.select("#player").attr("data-poster")
// Match local studios with anilist studios to increase the accuracy of the poster
val matchingStudios = document.select("div.content a.red").map { it.text() }
val matchedStudio = thumbnailUrl?.second?.find { it in matchingStudios }
thumbnail_url = if (matchedStudio != null) thumbnailUrl.first else document.select("#player").attr("data-poster")
} }
} }
@ -198,6 +280,30 @@ class OppaiStream : ParsedAnimeHttpSource(), ConfigurableAnimeSource {
}.let { }.let {
screen.addPreference(it) screen.addPreference(it)
} }
// Add cover source preference
ListPreference(screen.context).apply {
key = PREF_COVER_SOURCE
title = PREF_COVER_SOURCE_TITLE
entries = arrayOf("Default Cover", "Anilist Cover")
entryValues = arrayOf("Default-Cover", "Anilist-Cover")
summary = "This feature is experimental. It uses a covers for Anilist. If you see the default cover after switching to AniList cover, try clearing the cache in Settings > Advanced > Clear Anime Database > Oppai Steam. It only fetch Anilist covers in anime details page."
setDefaultValue("Anilist-Cover")
}.let {
screen.addPreference(it)
}
// Add cover source preference
ListPreference(screen.context).apply {
key = PREF_COVER_QUALITY
title = PREF_COVER_QUALITY_TITLE
entries = arrayOf("Extra Large", "Large")
entryValues = arrayOf("extraLarge", "large")
summary = "%s"
setDefaultValue("large")
}.let {
screen.addPreference(it)
}
} }
companion object { companion object {
@ -206,5 +312,11 @@ class OppaiStream : ParsedAnimeHttpSource(), ConfigurableAnimeSource {
private const val PREF_QUALITY = "preferred_quality" private const val PREF_QUALITY = "preferred_quality"
private const val PREF_QUALITY_TITLE = "Preferred quality" private const val PREF_QUALITY_TITLE = "Preferred quality"
private const val PREF_COVER_SOURCE = "preferred_cover_source"
private const val PREF_COVER_SOURCE_TITLE = "Preferred cover source - Beta"
private const val PREF_COVER_QUALITY = "preferred_cover_quality"
private const val PREF_COVER_QUALITY_TITLE = "Preferred cover quality - Beta"
} }
} }