diff --git a/.run/ZoroThemeGenerator.run.xml b/.run/ZoroThemeGenerator.run.xml
new file mode 100644
index 000000000..f406bf701
--- /dev/null
+++ b/.run/ZoroThemeGenerator.run.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/megacloud-extractor/build.gradle.kts b/lib/megacloud-extractor/build.gradle.kts
new file mode 100644
index 000000000..c657a290e
--- /dev/null
+++ b/lib/megacloud-extractor/build.gradle.kts
@@ -0,0 +1,21 @@
+plugins {
+ id("com.android.library")
+ kotlin("android")
+ id("kotlinx-serialization")
+}
+
+android {
+ compileSdk = AndroidConfig.compileSdk
+ namespace = "eu.kanade.tachiyomi.lib.megacloudextractor"
+
+ defaultConfig {
+ minSdk = AndroidConfig.minSdk
+ }
+}
+
+dependencies {
+ compileOnly(libs.bundles.common)
+ implementation(project(":lib-cryptoaes"))
+ implementation(project(":lib-playlist-utils"))
+}
+// BUMPS: 0
diff --git a/src/en/aniwatch/src/eu/kanade/tachiyomi/animeextension/en/zoro/extractors/AniWatchExtractor.kt b/lib/megacloud-extractor/src/main/java/eu/kanade/tachiyomi/lib/megacloudextractor/MegaCloudExtractor.kt
similarity index 57%
rename from src/en/aniwatch/src/eu/kanade/tachiyomi/animeextension/en/zoro/extractors/AniWatchExtractor.kt
rename to lib/megacloud-extractor/src/main/java/eu/kanade/tachiyomi/lib/megacloudextractor/MegaCloudExtractor.kt
index a248f22e3..cfa01bf12 100644
--- a/src/en/aniwatch/src/eu/kanade/tachiyomi/animeextension/en/zoro/extractors/AniWatchExtractor.kt
+++ b/lib/megacloud-extractor/src/main/java/eu/kanade/tachiyomi/lib/megacloudextractor/MegaCloudExtractor.kt
@@ -1,19 +1,30 @@
-package eu.kanade.tachiyomi.animeextension.en.zoro.extractors
+package eu.kanade.tachiyomi.lib.megacloudextractor
-import eu.kanade.tachiyomi.animeextension.en.zoro.dto.SourceResponseDto
-import eu.kanade.tachiyomi.animeextension.en.zoro.dto.VideoDto
-import eu.kanade.tachiyomi.animeextension.en.zoro.dto.VideoLink
+import eu.kanade.tachiyomi.animesource.model.Track
+import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES
+import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
+import okhttp3.Headers
import eu.kanade.tachiyomi.network.GET
-import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.OkHttpClient
import uy.kohesive.injekt.injectLazy
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.json.JsonElement
+import okhttp3.CacheControl
+import okhttp3.HttpUrl.Companion.toHttpUrl
-class AniWatchExtractor(private val client: OkHttpClient) {
+class MegaCloudExtractor(private val client: OkHttpClient, private val headers: Headers) {
private val json: Json by injectLazy()
+ private val playlistUtils by lazy { PlaylistUtils(client, headers) }
+
+ private val cacheControl = CacheControl.Builder().noStore().build()
+ private val noCacheClient = client.newBuilder()
+ .cache(null)
+ .build()
+
companion object {
private val SERVER_URL = arrayOf("https://megacloud.tv", "https://rapid-cloud.co")
private val SOURCES_URL = arrayOf("/embed-2/ajax/e-1/getSources?id=", "/ajax/embed-6-v2/getSources?id=")
@@ -24,7 +35,7 @@ class AniWatchExtractor(private val client: OkHttpClient) {
private fun cipherTextCleaner(data: String, type: String): Pair {
// TODO: fetch the key only when needed, using a thread-safe map
// (Like ConcurrentMap?) or MUTEX hacks.
- val indexPairs = client.newCall(GET("https://raw.githubusercontent.com/Claudemirovsky/keys/e$type/key"))
+ val indexPairs = noCacheClient.newCall(GET("https://raw.githubusercontent.com/Claudemirovsky/keys/e$type/key", cache = cacheControl))
.execute()
.use { it.body.string() }
.let { json.decodeFromString>>(it) }
@@ -49,7 +60,23 @@ class AniWatchExtractor(private val client: OkHttpClient) {
}
}
- fun getVideoDto(url: String): VideoDto {
+ fun getVideosFromUrl(url: String, type: String, name: String): List