package com.streamflixreborn.streamflix.extractors import android.text.Html import android.util.Base64 import androidx.core.net.toUri import com.tanasi.retrofit_jsoup.converter.JsoupConverterFactory import com.streamflixreborn.streamflix.models.Video import com.streamflixreborn.streamflix.utils.DnsResolver import com.streamflixreborn.streamflix.utils.UserPreferences import okhttp3.OkHttpClient import org.jsoup.nodes.Document import retrofit2.Retrofit import retrofit2.http.GET import retrofit2.http.Header import retrofit2.http.Url import java.util.concurrent.TimeUnit class VidsrcNetExtractor : Extractor() { override val name = "Vidsrc.net" override val mainUrl = "https://vidsrc-embed.ru" override val aliasUrls = listOf("https://vsembed.ru") fun server(videoType: Video.Type): Video.Server { return Video.Server( id = name, name = name, src = when (videoType) { is Video.Type.Episode -> "$mainUrl/embed/tv?tmdb=${videoType.tvShow.id}&season=${videoType.season.number}&episode=${videoType.number}" is Video.Type.Movie -> "$mainUrl/embed/movie?tmdb=${videoType.id}" }, ) } override suspend fun extract(link: String): Video { val service = Service.build(mainUrl) val iframedoc = service.get(link) .selectFirst("iframe#player_iframe")?.attr("src") ?.let { if (it.startsWith("//")) "https:$it" else it } ?: throw Exception("Can't retrieve rcp") val doc = service.get(iframedoc, link) val prorcp = Regex("src: '(/prorcp/.*?)'") .find(doc.toString())?.groupValues?.get(1) ?.let { iframedoc.substringBefore("/rcp") + it } ?: throw Exception("Can't retrieve prorcp") val script = service.get( prorcp, referer = iframedoc ).toString() val playerId = Regex("Playerjs.*file: ([a-zA-Z0-9]*?) ,") .find(script)?.groupValues?.get(1) ?: ""; val decryptedData = if (playerId.isNotBlank()) { val encryptedSource = Regex("""
""") .find(script)?.groupValues?.get(1) ?: throw Exception("Can't retrieve encrypted source") decrypt(playerId, encryptedSource) } else { Regex("""Playerjs.*file: "([^"]*?)" ,""") .find(script)?.groupValues?.get(1) } if (decryptedData.isNullOrBlank()) throw Exception("Can't retrieve file") val streamUrl = decryptedData.split(" or ") .firstOrNull() ?.replace(Regex("\\{[a-z]\\d+\\}"), "quibblezoomfable.com") ?: throw Exception("No stream found after decryption") /* Now try to extract subtitles */ val regex = Regex( """default_subtitles\s*=\s*["']([^"']+)["']""", RegexOption.DOT_MATCHES_ALL ) val subtitlesRaw = regex.find(script)?.groupValues?.get(1)?:"" val subtitles = if (subtitlesRaw.isNotBlank()) { val base = iframedoc.toUri() val baseUrl = "${base.scheme}://${base.host}" /* Subtitles are selected based on the provider's language, except when the language is English */ val preferredSubtitle = if (subtitlesRaw.isNotEmpty() && !UserPreferences.providerLanguage.isNullOrEmpty() && UserPreferences.providerLanguage != "en") UserPreferences.providerLanguage.orEmpty() else "" var alreadySet = false @Suppress("DEPRECATION") subtitlesRaw.split(",") .mapNotNull { item -> val language = item.substringAfter("[") .substringBefore("]") val url = item.substringAfter("]") if (!url.startsWith("/")) return@mapNotNull null Video.Subtitle( label = Html.fromHtml(language).toString(), file = "${baseUrl}/${url}", default = if (alreadySet == false && preferredSubtitle.isNotEmpty() && language.contains( preferredSubtitle, ignoreCase = true )) { alreadySet = true true } else false ) } } else emptyList() return Video( source = streamUrl, subtitles = subtitles, headers = mapOf( "Referer" to iframedoc ), ) } private fun decrypt(id: String, encrypted: String): String { return when (id) { "NdonQLf1Tzyx7bMG" -> NdonQLf1Tzyx7bMG(encrypted) "sXnL9MQIry" -> sXnL9MQIry(encrypted) "IhWrImMIGL" -> IhWrImMIGL(encrypted) "xTyBxQyGTA" -> xTyBxQyGTA(encrypted) "ux8qjPHC66" -> ux8qjPHC66(encrypted) "eSfH1IRMyL" -> eSfH1IRMyL(encrypted) "KJHidj7det" -> KJHidj7det(encrypted) "o2VSUnjnZl" -> o2VSUnjnZl(encrypted) "Oi3v1dAlaM" -> Oi3v1dAlaM(encrypted) "TsA2KGDGux" -> TsA2KGDGux(encrypted) "JoAHUMCLXV" -> JoAHUMCLXV(encrypted) else -> throw Exception("Encryption type not implemented yet: $id") } } private fun NdonQLf1Tzyx7bMG(a: String): String { val b = 3 val c = mutableListOf