fix(lib/chillx-extractor): update key & small refactor (#1888)
This commit is contained in:
parent
554b06ba6e
commit
1f8de21098
@ -1,6 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("com.android.library")
|
id("com.android.library")
|
||||||
kotlin("android")
|
kotlin("android")
|
||||||
|
id("kotlinx-serialization")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
@ -683,7 +683,7 @@ import android.util.Base64
|
|||||||
import eu.kanade.tachiyomi.animesource.model.Video
|
import eu.kanade.tachiyomi.animesource.model.Video
|
||||||
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.decodeFromString
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
import kotlinx.serialization.json.jsonPrimitive
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
@ -707,37 +707,16 @@ class ChillxExtractor(private val client: OkHttpClient, private val headers: Hea
|
|||||||
).execute().asJsoup().html()
|
).execute().asJsoup().html()
|
||||||
|
|
||||||
val master = Regex("""MasterJS\s*=\s*'([^']+)""").find(document)?.groupValues?.get(1)
|
val master = Regex("""MasterJS\s*=\s*'([^']+)""").find(document)?.groupValues?.get(1)
|
||||||
val aesJson = Json.decodeFromString<JsonObject>(base64Decode(master ?: return null).toString(Charsets.UTF_8))
|
val aesJson = Json.decodeFromString<CryptoInfo>(base64Decode(master ?: return null).toString(Charsets.UTF_8))
|
||||||
|
|
||||||
val encData =
|
val decrypt = cryptoAESHandler(aesJson ?: return null, KEY)
|
||||||
try {
|
|
||||||
AESData(
|
|
||||||
aesJson["ciphertext"]!!.jsonPrimitive.content,
|
|
||||||
aesJson["iv"]!!.jsonPrimitive.content,
|
|
||||||
aesJson["salt"]!!.jsonPrimitive.content,
|
|
||||||
aesJson["iterations"]!!.jsonPrimitive.content,
|
|
||||||
)
|
|
||||||
} catch(_: Exception) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
val decrypt = cryptoAESHandler(encData ?: return null, KEY)
|
|
||||||
val playlistUrl = Regex("""sources:\s*\[\{"file":"([^"]+)""").find(decrypt)?.groupValues?.get(1) ?: return null
|
val playlistUrl = Regex("""sources:\s*\[\{"file":"([^"]+)""").find(decrypt)?.groupValues?.get(1) ?: return null
|
||||||
|
|
||||||
val tracks = Regex("""tracks:\s*\[(.+)]""").find(decrypt)?.groupValues?.get(1)
|
val tracks = Regex("""tracks:\s*\[(.+)]""").find(decrypt)?.groupValues?.get(1)
|
||||||
val trackJson = Json.decodeFromString<JsonObject>(tracks ?: return null)
|
|
||||||
// TODO: Add subtitle support when a site is found that uses it
|
|
||||||
val trackData =
|
|
||||||
try {
|
|
||||||
|
|
||||||
SubtitleTrack(
|
// TODO: Add subtitle support when a site is found that uses it
|
||||||
trackJson["file"]!!.jsonPrimitive.content,
|
val trackJson = Json.decodeFromString<SubtitleTrack>(tracks ?: return null)
|
||||||
trackJson["label"]!!.jsonPrimitive.content,
|
|
||||||
trackJson["kind"]!!.jsonPrimitive.content,
|
|
||||||
)
|
|
||||||
} catch(_: Exception) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
val masterHeaders = Headers.headersOf(
|
val masterHeaders = Headers.headersOf(
|
||||||
"Accept", "*/*",
|
"Accept", "*/*",
|
||||||
@ -752,8 +731,8 @@ class ChillxExtractor(private val client: OkHttpClient, private val headers: Hea
|
|||||||
val response = client.newCall(GET(playlistUrl, headers = masterHeaders)).execute()
|
val response = client.newCall(GET(playlistUrl, headers = masterHeaders)).execute()
|
||||||
val masterPlaylist = response.body.string()
|
val masterPlaylist = response.body.string()
|
||||||
|
|
||||||
masterPlaylist?.substringAfter("#EXT-X-STREAM-INF:")
|
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:")
|
||||||
?.split("#EXT-X-STREAM-INF:")?.map {
|
.split("#EXT-X-STREAM-INF:").map {
|
||||||
val quality = it.substringAfter("RESOLUTION=").split(",")[0].split("\n")[0].substringAfter("x") + "p"
|
val quality = it.substringAfter("RESOLUTION=").split(",")[0].split("\n")[0].substringAfter("x") + "p"
|
||||||
|
|
||||||
var videoUrl = it.substringAfter("\n").substringBefore("\n")
|
var videoUrl = it.substringAfter("\n").substringBefore("\n")
|
||||||
@ -771,14 +750,14 @@ class ChillxExtractor(private val client: OkHttpClient, private val headers: Hea
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun cryptoAESHandler(
|
private fun cryptoAESHandler(
|
||||||
data: AESData,
|
data: CryptoInfo,
|
||||||
pass: String,
|
pass: String,
|
||||||
): String {
|
): String {
|
||||||
val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512")
|
val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512")
|
||||||
val spec = PBEKeySpec(
|
val spec = PBEKeySpec(
|
||||||
pass.toCharArray(),
|
pass.toCharArray(),
|
||||||
data.salt?.hexToByteArray(),
|
data.salt?.hexToByteArray(),
|
||||||
data.iterations?.toIntOrNull() ?: 1,
|
data.iterations ?: 1,
|
||||||
256
|
256
|
||||||
)
|
)
|
||||||
val key = factory.generateSecret(spec)
|
val key = factory.generateSecret(spec)
|
||||||
@ -795,6 +774,14 @@ class ChillxExtractor(private val client: OkHttpClient, private val headers: Hea
|
|||||||
return Base64.decode(string, Base64.DEFAULT)
|
return Base64.decode(string, Base64.DEFAULT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class CryptoInfo(
|
||||||
|
val ciphertext: String? = null,
|
||||||
|
val iv: String? = null,
|
||||||
|
val salt: String? = null,
|
||||||
|
val iterations: Int? = null,
|
||||||
|
)
|
||||||
|
|
||||||
private fun String.hexToByteArray(): ByteArray {
|
private fun String.hexToByteArray(): ByteArray {
|
||||||
check(length % 2 == 0) { "Must have an even length" }
|
check(length % 2 == 0) { "Must have an even length" }
|
||||||
return chunked(2)
|
return chunked(2)
|
||||||
@ -803,13 +790,7 @@ class ChillxExtractor(private val client: OkHttpClient, private val headers: Hea
|
|||||||
.toByteArray()
|
.toByteArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
data class AESData(
|
@Serializable
|
||||||
val ciphertext: String? = null,
|
|
||||||
val iv: String? = null,
|
|
||||||
val salt: String? = null,
|
|
||||||
val iterations: String? = null,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class SubtitleTrack(
|
data class SubtitleTrack(
|
||||||
val file: String? = null,
|
val file: String? = null,
|
||||||
val label: String? = null,
|
val label: String? = null,
|
||||||
@ -817,6 +798,6 @@ class ChillxExtractor(private val client: OkHttpClient, private val headers: Hea
|
|||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val KEY = "4VqE3#N7zt&HEP^a"
|
private const val KEY = "11x&W5UBrcqn\$9Yl"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user