fix(lib/lycoris&lulu) Repair decode json and work LuluStream #810

Merged
Hayanek merged 14 commits from fix-lycoris into main 2025-04-06 13:41:23 -05:00
2 changed files with 19 additions and 15 deletions
Showing only changes of commit 9a8ea456b4 - Show all commits

View file

@ -5,13 +5,11 @@ import eu.kanade.tachiyomi.network.GET
import android.util.Base64
import eu.kanade.tachiyomi.util.asJsoup
import eu.kanade.tachiyomi.util.parseAs
import kotlinx.serialization.json.Json
import kotlinx.serialization.Serializable
import okhttp3.Headers
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import uy.kohesive.injekt.injectLazy
import java.nio.charset.Charset
class LycorisCafeExtractor(private val client: OkHttpClient) {
@ -20,8 +18,6 @@ class LycorisCafeExtractor(private val client: OkHttpClient) {
private val GETLNKURL = "https://www.lycoris.cafe/api/watch/getLink"
private val json: Json by injectLazy()
// Credit: https://github.com/skoruppa/docchi-stremio-addon/blob/main/app/players/lycoris.py
fun getVideosFromUrl(url: String, headers: Headers, prefix: String): List<Video> {
@ -34,17 +30,25 @@ class LycorisCafeExtractor(private val client: OkHttpClient) {
GET(url, headers = embedHeaders),
).execute().asJsoup()
cuong-tran commented 2025-03-12 11:51:48 -05:00 (Migrated from github.com)

this will send a string "null" to json.decode and cause a crash

this will send a string `"null"` to json.decode and cause a crash
cuong-tran commented 2025-03-12 11:52:59 -05:00 (Migrated from github.com)

use script.parseAs<ScriptBody>()

use `script.parseAs<ScriptBody>()`
cuong-tran commented 2025-03-12 11:53:47 -05:00 (Migrated from github.com)

same here

same here
cuong-tran commented 2025-03-12 11:54:37 -05:00 (Migrated from github.com)
        val linkList: String? = fetchAndDecodeVideo(client, data.episodeInfo.id.toString(), isSecondary = false)

also fix fetchAndDecodeVideo() & decodeVideoLinks() so they both return String?

```suggestion val linkList: String? = fetchAndDecodeVideo(client, data.episodeInfo.id.toString(), isSecondary = false) ``` also fix `fetchAndDecodeVideo()` & `decodeVideoLinks()` so they both return `String?`
cuong-tran commented 2025-03-12 12:18:42 -05:00 (Migrated from github.com)
        val fhdLink = fetchAndDecodeVideo(client, data.episodeInfo.FHD.toString(), isSecondary = true)
        val sdLink = fetchAndDecodeVideo(client, data.episodeInfo.SD.toString(), isSecondary = true)
        val hdLink = fetchAndDecodeVideo(client, data.episodeInfo.HD.toString(), isSecondary = true)
```suggestion val fhdLink = fetchAndDecodeVideo(client, data.episodeInfo.FHD.toString(), isSecondary = true) val sdLink = fetchAndDecodeVideo(client, data.episodeInfo.SD.toString(), isSecondary = true) val hdLink = fetchAndDecodeVideo(client, data.episodeInfo.HD.toString(), isSecondary = true) ```
cuong-tran commented 2025-03-12 12:27:09 -05:00 (Migrated from github.com)
            if (!fhdLink.isNullOrBlank()) {
```suggestion if (!fhdLink.isNullOrBlank()) { ```
Hayanek commented 2025-03-12 12:49:49 -05:00 (Migrated from github.com)

with this I was aware of it but had no idea how to fix it so that such a problem would not occur

with this I was aware of it but had no idea how to fix it so that such a problem would not occur
cuong-tran commented 2025-03-12 23:47:41 -05:00 (Migrated from github.com)

Add ?. before toString and conditional action if it's null

Add `?.` before `toString` and conditional action if it's null
val script = document.select("script[type='application/json']").first()?.data()?.toString() ?: return emptyList()
val script = document.selectFirst("script[type='application/json']")?.data() ?: return emptyList()
cuong-tran commented 2025-03-13 08:15:11 -05:00 (Migrated from github.com)
    private fun decodeVideoLinks(encodedUrl: String): String? {
        if (encodedUrl.isBlank()) {
```suggestion private fun decodeVideoLinks(encodedUrl: String): String? { if (encodedUrl.isBlank()) { ```
cuong-tran commented 2025-03-24 00:41:52 -05:00 (Migrated from github.com)
        val script = document.selectFirst("script[type='application/json']")?.data() ?: return emptyList()
```suggestion val script = document.selectFirst("script[type='application/json']")?.data() ?: return emptyList() ```
cuong-tran commented 2025-03-24 01:03:44 -05:00 (Migrated from github.com)
        val linkList = data.episodeInfo.id?.let { fetchAndDecodeVideo(client, data.episodeInfo.id.toString(), isSecondary = false) }

        val fhdLink = data.episodeInfo.FHD?.let { fetchAndDecodeVideo(client, data.episodeInfo.FHD, isSecondary = true) }
        val sdLink = data.episodeInfo.SD?.let { fetchAndDecodeVideo(client, data.episodeInfo.SD, isSecondary = true) }
        val hdLink = data.episodeInfo.HD?.let { fetchAndDecodeVideo(client, data.episodeInfo.HD, isSecondary = true) }
```suggestion val linkList = data.episodeInfo.id?.let { fetchAndDecodeVideo(client, data.episodeInfo.id.toString(), isSecondary = false) } val fhdLink = data.episodeInfo.FHD?.let { fetchAndDecodeVideo(client, data.episodeInfo.FHD, isSecondary = true) } val sdLink = data.episodeInfo.SD?.let { fetchAndDecodeVideo(client, data.episodeInfo.SD, isSecondary = true) } val hdLink = data.episodeInfo.HD?.let { fetchAndDecodeVideo(client, data.episodeInfo.HD, isSecondary = true) } ```
cuong-tran commented 2025-03-24 01:04:12 -05:00 (Migrated from github.com)
```suggestion ```
cuong-tran commented 2025-03-24 01:04:54 -05:00 (Migrated from github.com)
            } ?: hdLink?.takeIf { it.contains("https://") }?.let {
                videos.add(Video(it, "${prefix}lycoris.cafe - 720p", it))
            }
```suggestion } ?: hdLink?.takeIf { it.contains("https://") }?.let { videos.add(Video(it, "${prefix}lycoris.cafe - 720p", it)) } ```
cuong-tran commented 2025-03-24 01:05:40 -05:00 (Migrated from github.com)
            } ?: sdLink?.takeIf { it.contains("https://") }?.let {
```suggestion } ?: sdLink?.takeIf { it.contains("https://") }?.let { ```
cuong-tran commented 2025-03-24 01:05:47 -05:00 (Migrated from github.com)

could we use checkLinks() instead of it.contains()?

could we use `checkLinks()` instead of `it.contains()`?
cuong-tran commented 2025-03-24 01:05:55 -05:00 (Migrated from github.com)

could we use checkLinks() instead of it.contains()?

could we use `checkLinks()` instead of `it.contains()`?
val scriptData = script.parseAs<ScriptBody>()
val data = scriptData.body.parseAs<ScriptEpisode>()
val linkList: String? = fetchAndDecodeVideo(client, data.episodeInfo.id.toString(), isSecondary = false)
val linkList = data.episodeInfo.id?.let {
fetchAndDecodeVideo(client, data.episodeInfo.id.toString(), isSecondary = false)
}
val fhdLink = fetchAndDecodeVideo(client, data.episodeInfo.FHD.toString(), isSecondary = true)
val sdLink = fetchAndDecodeVideo(client, data.episodeInfo.SD.toString(), isSecondary = true)
val hdLink = fetchAndDecodeVideo(client, data.episodeInfo.HD.toString(), isSecondary = true)
val fhdLink = data.episodeInfo.FHD?.let {
fetchAndDecodeVideo(client, data.episodeInfo.FHD, isSecondary = true)
}
val sdLink = data.episodeInfo.SD?.let {
fetchAndDecodeVideo(client, data.episodeInfo.SD, isSecondary = true)
}
val hdLink = data.episodeInfo.HD?.let {
fetchAndDecodeVideo(client, data.episodeInfo.HD, isSecondary = true)
}
if (linkList.isNullOrBlank() || linkList == "{}") {
cuong-tran commented 2025-03-12 12:15:19 -05:00 (Migrated from github.com)
        } else {
```suggestion } else { ```
cuong-tran commented 2025-03-12 12:21:44 -05:00 (Migrated from github.com)
            val videoLinks = linkList.parseAs<VideoLinksApi>()
```suggestion val videoLinks = linkList.parseAs<VideoLinksApi>() ```
cuong-tran commented 2025-03-12 12:27:35 -05:00 (Migrated from github.com)
            if (!sdLink.isNullOrBlank()) {
```suggestion if (!sdLink.isNullOrBlank()) { ```
cuong-tran commented 2025-03-12 12:28:12 -05:00 (Migrated from github.com)
            }?: fhdLink?.takeIf { it.contains("https://") }?.let {
```suggestion }?: fhdLink?.takeIf { it.contains("https://") }?.let { ```
cuong-tran commented 2025-03-12 12:28:33 -05:00 (Migrated from github.com)
            }?: hdLink?.takeIf { it.contains("https://") }?.let {
```suggestion }?: hdLink?.takeIf { it.contains("https://") }?.let { ```
cuong-tran commented 2025-03-12 12:28:49 -05:00 (Migrated from github.com)
            }?: sdLink?.takeIf { it.contains("https://") }?.let {
```suggestion }?: sdLink?.takeIf { it.contains("https://") }?.let { ```
if (!fhdLink.isNullOrBlank()) {
@ -56,25 +60,24 @@ class LycorisCafeExtractor(private val client: OkHttpClient) {
if (!sdLink.isNullOrBlank()) {
videos.add(Video(sdLink, "${prefix}lycoris.cafe - 480p", sdLink))
}
} else {
val videoLinks = linkList.parseAs<VideoLinksApi>()
videoLinks.FHD?.takeIf { checkLinks(client, it) }?.let {
videos.add(Video(it, "${prefix}lycoris.cafe - 1080p", it))
}?: fhdLink?.takeIf { it.contains("https://") }?.let {
} ?: fhdLink?.takeIf { checkLinks(client, it) }?.let {
videos.add(Video(it, "${prefix}lycoris.cafe - 1080p", it))
}
videoLinks.HD?.takeIf { checkLinks(client, it) }?.let {
videos.add(Video(it, "${prefix}lycoris.cafe - 720p", it))
}?: hdLink?.takeIf { it.contains("https://") }?.let {
} ?: hdLink?.takeIf { checkLinks(client, it) }?.let {
videos.add(Video(it, "${prefix}lycoris.cafe - 720p", it))
}
videoLinks.SD?.takeIf { checkLinks(client, it) }?.let {
videos.add(Video(it, "${prefix}lycoris.cafe - 480p", it))
}?: sdLink?.takeIf { it.contains("https://") }?.let {
} ?: sdLink?.takeIf { checkLinks(client, it) }?.let {
videos.add(Video(it, "${prefix}lycoris.cafe - 480p", it))
}
}
@ -125,7 +128,7 @@ class LycorisCafeExtractor(private val client: OkHttpClient) {
client.newCall(GET(url))
.execute()
.use { response ->
val data = response.body.string() ?: ""
val data = response.body.string()
return decodeVideoLinks(data)
}
}
@ -142,6 +145,7 @@ class LycorisCafeExtractor(private val client: OkHttpClient) {
// 1. Obsługa kontynuacji linii (backslash + newline)
val withoutLineContinuation = text.replace("\\\n", "")
cuong-tran commented 2025-03-24 01:06:48 -05:00 (Migrated from github.com)

Move regex outside and make it lazy load

Move regex outside and make it lazy load
Hayanek commented 2025-03-24 10:42:33 -05:00 (Migrated from github.com)

I'll be honest I have no idea why, and how I could do it.

I'll be honest I have no idea why, and how I could do it.
cuong-tran commented 2025-03-24 15:26:12 -05:00 (Migrated from github.com)

move out so it's only needed to be initialized once, not every time the function is called.

Example:

private val wordRegex by lazy { Regex("""\w+""") }
move out so it's only needed to be initialized once, not every time the function is called. Example: ```kotlin private val wordRegex by lazy { Regex("""\w+""") } ```
Hayanek commented 2025-03-24 16:10:12 -05:00 (Migrated from github.com)

Will it be good this way?

private val wordsRegex by lazy { 
        Regex(
        """\\U([0-9a-fA-F]{8})|""" +     // \UXXXXXXXX
            """\\u([0-9a-fA-F]{4})|""" +     // \uXXXX
            """\\x([0-9a-fA-F]{2})|""" +     // \xHH
            """\\([0-7]{1,3})|""" +          // \OOO (octal)
            """\\([btnfr"'$\\])"""         // \n, \t, itd.
        ) 
    }

or do I have to knock them all down one by one :(

Will it be good this way? ```kotlin private val wordsRegex by lazy { Regex( """\\U([0-9a-fA-F]{8})|""" + // \UXXXXXXXX """\\u([0-9a-fA-F]{4})|""" + // \uXXXX """\\x([0-9a-fA-F]{2})|""" + // \xHH """\\([0-7]{1,3})|""" + // \OOO (octal) """\\([btnfr"'$\\])""" // \n, \t, itd. ) } ``` or do I have to knock them all down one by one :(
cuong-tran commented 2025-03-24 22:24:12 -05:00 (Migrated from github.com)

Just move the whole thing out like that is OK

Just move the whole thing out like that is OK
// 2. Regex do wykrywania wszystkich sekwencji escape
val regex = Regex(
"""\\U([0-9a-fA-F]{8})|""" + // \UXXXXXXXX

View file

@ -1,7 +1,7 @@
ext {
extName = 'Docchi'
extClass = '.Docchi'
extVersionCode = 2
extVersionCode = 3
isNsfw = true
}