fix(lib/lycoris): fix parse json

This commit is contained in:
Hayanek 2025-03-11 01:26:23 +01:00
parent 340de27023
commit fcf3e8a428

View file

@ -10,7 +10,6 @@ import okhttp3.Headers
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import uy.kohesive.injekt.injectLazy
import java.nio.charset.Charset import java.nio.charset.Charset
class LycorisCafeExtractor(private val client: OkHttpClient) { class LycorisCafeExtractor(private val client: OkHttpClient) {
@ -19,7 +18,7 @@ class LycorisCafeExtractor(private val client: OkHttpClient) {
private val GETLNKURL = "https://www.lycoris.cafe/api/watch/getLink" private val GETLNKURL = "https://www.lycoris.cafe/api/watch/getLink"
private val json: Json by injectLazy() private val json = Json { ignoreUnknownKeys = true }
// Credit: https://github.com/skoruppa/docchi-stremio-addon/blob/main/app/players/lycoris.py // Credit: https://github.com/skoruppa/docchi-stremio-addon/blob/main/app/players/lycoris.py
fun getVideosFromUrl(url: String, headers: Headers, prefix: String): List<Video> { fun getVideosFromUrl(url: String, headers: Headers, prefix: String): List<Video> {
@ -33,40 +32,17 @@ class LycorisCafeExtractor(private val client: OkHttpClient) {
GET(url, headers = embedHeaders), GET(url, headers = embedHeaders),
).execute().asJsoup() ).execute().asJsoup()
val scripts = document.select("script") val script = document.select("script[type='application/json']").first()?.data().toString()
val episodeDataPattern = Regex("episodeInfo\\s*:\\s*(\\{.*?\\}),", RegexOption.DOT_MATCHES_ALL) val scriptData = json.decodeFromString<ScriptBody>(script)
var episodeData: String? = null
for (script in scripts) { val data = json.decodeFromString<ScriptEpisode>(scriptData.body)
val content = script.data()
val match = episodeDataPattern.find(content)
if (match != null) { var linkList: String? = fetchAndDecodeVideo(client, data.episodeInfo.id.toString(), isSecondary = false).toString()
episodeData = match.groupValues[1]
break
}
}
val result = mutableMapOf<String, String?>()
val patterns = listOf(
"id" to Regex("id\\s*:\\s*(\\d+)"),
"FHD" to Regex("FHD\\s*:\\s*\"([^\"]+)\""),
"HD" to Regex("HD\\s*:\\s*\"([^\"]+)\""),
"SD" to Regex("SD\\s*:\\s*\"([^\"]+)\"")
)
patterns.forEach { (key, pattern) ->
result[key] = episodeData?.let { pattern.find(it)?.groups?.get(1)?.value }
}
var linkList: String? = fetchAndDecodeVideo(client, result["id"].toString(), isSecondary = false).toString()
val fhdLink = fetchAndDecodeVideo(client, result["FHD"].toString(), isSecondary = true).toString()
val sdLink = fetchAndDecodeVideo(client, result["SD"].toString(), isSecondary = true).toString()
val hdLink = fetchAndDecodeVideo(client, result["HD"].toString(), isSecondary = true).toString()
val fhdLink = fetchAndDecodeVideo(client, data.episodeInfo.FHD.toString(), isSecondary = true).toString()
val sdLink = fetchAndDecodeVideo(client, data.episodeInfo.SD.toString(), isSecondary = true).toString()
val hdLink = fetchAndDecodeVideo(client, data.episodeInfo.HD.toString(), isSecondary = true).toString()
if (linkList.isNullOrBlank() || linkList == "{}") { if (linkList.isNullOrBlank() || linkList == "{}") {
if (fhdLink.isNotEmpty()) { if (fhdLink.isNotEmpty()) {
@ -78,20 +54,28 @@ class LycorisCafeExtractor(private val client: OkHttpClient) {
if (sdLink.isNotEmpty()) { if (sdLink.isNotEmpty()) {
videos.add(Video(sdLink, "${prefix}lycoris.cafe - 480p", sdLink)) videos.add(Video(sdLink, "${prefix}lycoris.cafe - 480p", sdLink))
} }
}else { }else {
val videoLinks = Json.decodeFromString<VideoLinks>(linkList) val videoLinks = json.decodeFromString<VideoLinksApi>(linkList)
videoLinks.FHD?.takeIf { checkLinks(client, it) }?.let { videoLinks.FHD?.takeIf { checkLinks(client, it) }?.let {
videos.add(Video(it, "${prefix}lycoris.cafe - 1080p", it)) videos.add(Video(it, "${prefix}lycoris.cafe - 1080p", it))
}?: videos.add(Video(fhdLink, "${prefix}lycoris.cafe - 1080p", fhdLink)) }?: fhdLink.takeIf { it.contains("https://") }?.let {
videos.add(Video(it, "${prefix}lycoris.cafe - 1080p", it))
}
videoLinks.HD?.takeIf { checkLinks(client, it) }?.let { videoLinks.HD?.takeIf { checkLinks(client, it) }?.let {
videos.add(Video(it, "${prefix}lycoris.cafe - 720p", it)) videos.add(Video(it, "${prefix}lycoris.cafe - 720p", it))
}?: videos.add(Video(hdLink, "${prefix}lycoris.cafe - 720p", hdLink)) }?: hdLink.takeIf { it.contains("https://") }?.let {
videos.add(Video(it, "${prefix}lycoris.cafe - 720p", it))
}
videoLinks.SD?.takeIf { checkLinks(client, it) }?.let { videoLinks.SD?.takeIf { checkLinks(client, it) }?.let {
videos.add(Video(it, "${prefix}lycoris.cafe - 480p", it)) videos.add(Video(it, "${prefix}lycoris.cafe - 480p", it))
}?: videos.add(Video(sdLink, "${prefix}lycoris.cafe - 480p", sdLink)) }?: sdLink.takeIf { it.contains("https://") }?.let {
videos.add(Video(it, "${prefix}lycoris.cafe - 480p", it))
}
} }
return videos return videos
@ -146,6 +130,8 @@ class LycorisCafeExtractor(private val client: OkHttpClient) {
} }
private fun checkLinks(client: OkHttpClient, link: String): Boolean { private fun checkLinks(client: OkHttpClient, link: String): Boolean {
if (!link.contains("https://")) return false
client.newCall(GET(link)).execute().use { response -> client.newCall(GET(link)).execute().use { response ->
return response.code.toString() == "200" return response.code.toString() == "200"
} }
@ -208,16 +194,32 @@ class LycorisCafeExtractor(private val client: OkHttpClient) {
} }
@Serializable @Serializable
data class VideoLinks( data class ScriptBody(
val body: String
)
@Serializable
data class ScriptEpisode(
val episodeInfo: EpisodeInfo
)
@Serializable
data class EpisodeInfo(
val id: Int? = null,
val FHD: String? = null,
val HD: String? = null,
val SD: String? = null,
)
@Serializable
data class VideoLinksApi(
val HD: String? = null, val HD: String? = null,
val SD: String? = null, val SD: String? = null,
val FHD: String? = null, val FHD: String? = null,
val Source: String? = null, val Source: String? = null,
val preview: String? = null,
val SourceMKV: String? = null val SourceMKV: String? = null
) )
} }