From 3ca01b9b81a29ab4bf6341692ca9f8239b3a82d4 Mon Sep 17 00:00:00 2001 From: hexated Date: Sat, 8 Apr 2023 21:14:42 +0700 Subject: [PATCH] sora: added ninetv --- SoraStream/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Extractors.kt | 128 ++++++++++++++++++ .../main/kotlin/com/hexated/SoraExtractor.kt | 18 +++ .../src/main/kotlin/com/hexated/SoraStream.kt | 5 + .../main/kotlin/com/hexated/SoraStreamLite.kt | 10 ++ .../kotlin/com/hexated/SoraStreamPlugin.kt | 2 + 6 files changed, 164 insertions(+), 1 deletion(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 16fe6939..295981ff 100644 --- a/SoraStream/build.gradle.kts +++ b/SoraStream/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 113 +version = 114 cloudstream { diff --git a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt index 2d7d0403..6ad3a2fa 100644 --- a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt +++ b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt @@ -1,8 +1,19 @@ package com.hexated +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.extractors.Filesim import com.lagradost.cloudstream3.extractors.StreamSB import com.lagradost.cloudstream3.extractors.XStreamCdn +import com.lagradost.cloudstream3.utils.AppUtils +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.Qualities +import javax.crypto.Cipher +import javax.crypto.SecretKeyFactory +import javax.crypto.spec.IvParameterSpec +import javax.crypto.spec.PBEKeySpec +import javax.crypto.spec.SecretKeySpec class Sbnet : StreamSB() { override var name = "Sbnet" @@ -27,4 +38,121 @@ class Keephealth : StreamSB() { class FileMoonIn : Filesim() { override val mainUrl = "https://filemoon.in" override val name = "FileMoon" +} + +class Watchx : Chillx() { + override val name = "Watchx" + override val mainUrl = "https://watchx.top" +} + +open class Chillx : ExtractorApi() { + override val name = "Chillx" + override val mainUrl = "https://chillx.top" + override val requiresReferer = true + + companion object { + private const val KEY = "4VqE3#N7zt&HEP^a" + } + + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val master = Regex("MasterJS\\s*=\\s*'([^']+)").find( + app.get( + url, + referer = referer + ).text + )?.groupValues?.get(1) + val encData = AppUtils.tryParseJson(base64Decode(master ?: return)) + val decrypt = cryptoAESHandler(encData ?: return, KEY, false) + + val source = Regex("""sources:\s*\[\{"file":"([^"]+)""").find(decrypt)?.groupValues?.get(1) + val tracks = Regex("""tracks:\s*\[(.+)]""").find(decrypt)?.groupValues?.get(1) + + val headers = mapOf( + "Accept" to "*/*", + "Connection" to "keep-alive", + "Sec-Fetch-Dest" to "empty", + "Sec-Fetch-Mode" to "cors", + "Sec-Fetch-Site" to "cross-site", + "Origin" to mainUrl, + ) + + callback.invoke( + ExtractorLink( + name, + name, + source ?: return, + "$mainUrl/", + Qualities.P1080.value, + headers = headers, + isM3u8 = true + ) + ) + + AppUtils.tryParseJson>("[$tracks]") + ?.filter { it.kind == "captions" }?.map { track -> + subtitleCallback.invoke( + SubtitleFile( + track.label ?: "", + track.file ?: return@map null + ) + ) + } + } + + private fun cryptoAESHandler( + data: AESData, + pass: String, + encrypt: Boolean = true + ): String { + val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512") + val spec = PBEKeySpec( + pass.toCharArray(), + data.salt?.hexToByteArray(), + data.iterations?.toIntOrNull() ?: 1, + 256 + ) + val key = factory.generateSecret(spec) + val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") + return if (!encrypt) { + cipher.init( + Cipher.DECRYPT_MODE, + SecretKeySpec(key.encoded, "AES"), + IvParameterSpec(data.iv?.hexToByteArray()) + ) + String(cipher.doFinal(base64DecodeArray(data.ciphertext.toString()))) + } else { + cipher.init( + Cipher.ENCRYPT_MODE, + SecretKeySpec(key.encoded, "AES"), + IvParameterSpec(data.iv?.hexToByteArray()) + ) + base64Encode(cipher.doFinal(data.ciphertext?.toByteArray())) + } + } + + private fun String.hexToByteArray(): ByteArray { + check(length % 2 == 0) { "Must have an even length" } + return chunked(2) + .map { it.toInt(16).toByte() } + + .toByteArray() + } + + data class AESData( + @JsonProperty("ciphertext") val ciphertext: String? = null, + @JsonProperty("iv") val iv: String? = null, + @JsonProperty("salt") val salt: String? = null, + @JsonProperty("iterations") val iterations: String? = null, + ) + + data class Tracks( + @JsonProperty("file") val file: String? = null, + @JsonProperty("label") val label: String? = null, + @JsonProperty("kind") val kind: String? = null, + ) } \ No newline at end of file diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index f5afbe1e..c06415db 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2767,6 +2767,24 @@ object SoraExtractor : SoraStream() { } } + suspend fun invokeNinetv( + tmdbId: Int? = null, + season: Int? = null, + episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val url = if (season == null) { + "$nineTvAPI/movie/$tmdbId" + } else { + "$nineTvAPI/tv/$tmdbId-$season-$episode" + } + + val iframe = app.get(url).document.selectFirst("iframe")?.attr("src") ?: return + loadExtractor(iframe, "$nineTvAPI/", subtitleCallback, callback) + + } + } diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 9830418c..718b02ab 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -38,6 +38,7 @@ import com.hexated.SoraExtractor.invokeM4uhd import com.hexated.SoraExtractor.invokeMovie123Net import com.hexated.SoraExtractor.invokeMoviesbay import com.hexated.SoraExtractor.invokeMoviezAdd +import com.hexated.SoraExtractor.invokeNinetv import com.hexated.SoraExtractor.invokePapaonMovies1 import com.hexated.SoraExtractor.invokePapaonMovies2 import com.hexated.SoraExtractor.invokeRStream @@ -120,6 +121,7 @@ open class SoraStream : TmdbProvider() { const val ask4MoviesAPI = "https://ask4movie.mx" const val biliBiliAPI = "https://api-vn.kaguya.app/server" const val watchOnlineAPI = "https://watchonline.ag" + const val nineTvAPI = "https://api.9animetv.live" // INDEX SITE const val baymoviesAPI = "https://opengatewayindex.pages.dev" // dead const val chillmovies0API = "https://chill.aicirou.workers.dev/0:" // dead @@ -630,6 +632,9 @@ open class SoraStream : TmdbProvider() { subtitleCallback ) }, + { + if (!res.isAnime) invokeNinetv(res.id, res.season, res.episode, subtitleCallback, callback) + }, { if (!res.isAnime) invokeBlackmovies( blackMoviesAPI, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index 7609eec1..68af1f78 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -17,6 +17,7 @@ import com.hexated.SoraExtractor.invokeLing import com.hexated.SoraExtractor.invokeM4uhd import com.hexated.SoraExtractor.invokeMovie123Net import com.hexated.SoraExtractor.invokeMovieHab +import com.hexated.SoraExtractor.invokeNinetv import com.hexated.SoraExtractor.invokeRStream import com.hexated.SoraExtractor.invokeSeries9 import com.hexated.SoraExtractor.invokeSmashyStream @@ -63,6 +64,15 @@ class SoraStreamLite : SoraStream() { callback ) }, + { + if (!res.isAnime) invokeNinetv( + res.id, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, { invokeTwoEmbed(res.id, res.season, res.episode, subtitleCallback, callback) }, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt index cbc68a5c..fd843743 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt @@ -16,5 +16,7 @@ class SoraStreamPlugin: Plugin() { registerExtractorAPI(Keephealth()) registerExtractorAPI(FileMoonIn()) registerExtractorAPI(Sbnet()) + registerExtractorAPI(Chillx()) + registerExtractorAPI(Watchx()) } } \ No newline at end of file