feat(lib/megacloud-extractor): Address TODO, fetch indexes only when needed (#2487)
This commit is contained in:
parent
334aa751d3
commit
b693107302
@ -4,16 +4,20 @@ import eu.kanade.tachiyomi.animesource.model.Track
|
|||||||
import eu.kanade.tachiyomi.animesource.model.Video
|
import eu.kanade.tachiyomi.animesource.model.Video
|
||||||
import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES
|
import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES
|
||||||
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
|
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
|
||||||
import okhttp3.Headers
|
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
import kotlinx.coroutines.sync.withLock
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.JsonElement
|
||||||
import kotlinx.serialization.json.jsonPrimitive
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
|
import okhttp3.CacheControl
|
||||||
|
import okhttp3.Headers
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
import kotlinx.serialization.json.JsonElement
|
|
||||||
import okhttp3.CacheControl
|
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
|
||||||
|
|
||||||
class MegaCloudExtractor(private val client: OkHttpClient, private val headers: Headers) {
|
class MegaCloudExtractor(private val client: OkHttpClient, private val headers: Headers) {
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
@ -30,16 +34,26 @@ class MegaCloudExtractor(private val client: OkHttpClient, private val headers:
|
|||||||
private val SOURCES_URL = arrayOf("/embed-2/ajax/e-1/getSources?id=", "/ajax/embed-6-v2/getSources?id=")
|
private val SOURCES_URL = arrayOf("/embed-2/ajax/e-1/getSources?id=", "/ajax/embed-6-v2/getSources?id=")
|
||||||
private val SOURCES_SPLITTER = arrayOf("/e-1/", "/embed-6-v2/")
|
private val SOURCES_SPLITTER = arrayOf("/e-1/", "/embed-6-v2/")
|
||||||
private val SOURCES_KEY = arrayOf("1", "6")
|
private val SOURCES_KEY = arrayOf("1", "6")
|
||||||
|
private val INDEX_PAIRS_MAP = mutableMapOf("1" to emptyList<List<Int>>(), "6" to emptyList<List<Int>>())
|
||||||
|
private val MUTEX = Mutex()
|
||||||
|
|
||||||
|
private inline fun <reified R> runLocked(crossinline block: () -> R) = runBlocking(Dispatchers.IO) {
|
||||||
|
MUTEX.withLock { block() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getIndexPairs(type: String) = runLocked {
|
||||||
|
INDEX_PAIRS_MAP[type].orEmpty().ifEmpty {
|
||||||
|
noCacheClient.newCall(GET("https://raw.githubusercontent.com/Claudemirovsky/keys/e$type/key", cache = cacheControl))
|
||||||
|
.execute()
|
||||||
|
.use { it.body.string() }
|
||||||
|
.let { json.decodeFromString<List<List<Int>>>(it) }
|
||||||
|
.also { INDEX_PAIRS_MAP[type] = it }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cipherTextCleaner(data: String, type: String): Pair<String, String> {
|
private fun cipherTextCleaner(data: String, type: String): Pair<String, String> {
|
||||||
// TODO: fetch the key only when needed, using a thread-safe map
|
val indexPairs = getIndexPairs(type)
|
||||||
// (Like ConcurrentMap?) or MUTEX hacks.
|
|
||||||
val indexPairs = noCacheClient.newCall(GET("https://raw.githubusercontent.com/Claudemirovsky/keys/e$type/key", cache = cacheControl))
|
|
||||||
.execute()
|
|
||||||
.use { it.body.string() }
|
|
||||||
.let { json.decodeFromString<List<List<Int>>>(it) }
|
|
||||||
|
|
||||||
val (password, ciphertext, _) = indexPairs.fold(Triple("", data, 0)) { previous, item ->
|
val (password, ciphertext, _) = indexPairs.fold(Triple("", data, 0)) { previous, item ->
|
||||||
val start = item.first() + previous.third
|
val start = item.first() + previous.third
|
||||||
val end = start + item.last()
|
val end = start + item.last()
|
||||||
@ -56,6 +70,8 @@ class MegaCloudExtractor(private val client: OkHttpClient, private val headers:
|
|||||||
if (attempts > 2) throw Exception("PLEASE NUKE ANIWATCH AND CLOUDFLARE")
|
if (attempts > 2) throw Exception("PLEASE NUKE ANIWATCH AND CLOUDFLARE")
|
||||||
val (ciphertext, password) = cipherTextCleaner(ciphered, type)
|
val (ciphertext, password) = cipherTextCleaner(ciphered, type)
|
||||||
return CryptoAES.decrypt(ciphertext, password).ifEmpty {
|
return CryptoAES.decrypt(ciphertext, password).ifEmpty {
|
||||||
|
// Update index pairs
|
||||||
|
runLocked { INDEX_PAIRS_MAP[type] = emptyList<List<Int>>() }
|
||||||
tryDecrypting(ciphered, type, attempts + 1)
|
tryDecrypting(ciphered, type, attempts + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,7 +83,7 @@ class MegaCloudExtractor(private val client: OkHttpClient, private val headers:
|
|||||||
val subs2 = video.tracks
|
val subs2 = video.tracks
|
||||||
?.filter { it.kind == "captions" }
|
?.filter { it.kind == "captions" }
|
||||||
?.map { Track(it.file, it.label) }
|
?.map { Track(it.file, it.label) }
|
||||||
?: emptyList()
|
.orEmpty()
|
||||||
return playlistUtils.extractFromHls(
|
return playlistUtils.extractFromHls(
|
||||||
masterUrl,
|
masterUrl,
|
||||||
videoNameGen = { "$name - $it - $type" },
|
videoNameGen = { "$name - $it - $type" },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user