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.extractors.helper.AsianEmbedHelper 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 StreamM4u : XStreamCdn() { override val name: String = "StreamM4u" override val mainUrl: String = "https://streamm4u.club" } class Fembed9hd : XStreamCdn() { override var mainUrl = "https://fembed9hd.com" override var name = "Fembed9hd" } class Sbasian : StreamSB() { override var mainUrl = "https://sbasian.pro" override var name = "Sbasian" } class Sbnet : StreamSB() { override var name = "Sbnet" override var mainUrl = "https://sbnet.one" } class Sblongvu : StreamSB() { override var name = "Sblongvu" override var mainUrl = "https://sblongvu.com" } class Keephealth : StreamSB() { override var name = "Keephealth" override var mainUrl = "https://keephealth.info" } class Moviesm4u : Filesim() { override val mainUrl = "https://moviesm4u.com" override val name = "Moviesm4u" } class FileMoonIn : Filesim() { override val mainUrl = "https://filemoon.in" override val name = "FileMoon" } class StreamhideCom : Filesim() { override var name: String = "Streamhide" override var mainUrl: String = "https://streamhide.com" } class Movhide : Filesim() { override var name: String = "Movhide" override var mainUrl: String = "https://movhide.pro" } class Bestx : Chillx() { override val name = "Bestx" override val mainUrl = "https://bestx.stream" } 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) // required 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, ) }