diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 35025bda..2c720109 100644 --- a/SoraStream/build.gradle.kts +++ b/SoraStream/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 4 +version = 5 cloudstream { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 6e604f6b..b66a9d22 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -1,16 +1,12 @@ package com.hexated import android.util.Log -import com.lagradost.cloudstream3.APIHolder -import com.lagradost.cloudstream3.SubtitleFile -import com.lagradost.cloudstream3.apmap -import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.network.WebViewResolver -import com.lagradost.cloudstream3.utils.AppUtils -import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.Qualities -import com.lagradost.cloudstream3.utils.loadExtractor +import com.lagradost.cloudstream3.utils.* import com.lagradost.nicehttp.requestCreator +import java.net.URI +import java.util.ArrayList object SoraExtractor : SoraStream() { @@ -102,38 +98,151 @@ object SoraExtractor : SoraStream() { loadExtractor(url, null, subtitleCallback, callback) } - private suspend fun loadLinksWithWebView( - url: String, - callback: (ExtractorLink) -> Unit - ) { - val foundVideo = WebViewResolver( - Regex("""\.m3u8|i7njdjvszykaieynzsogaysdgb0hm8u1mzubmush4maopa4wde\.com""") - ).resolveUsingWebView( - requestCreator( - "GET", url, referer = "https://olgply.com/" - ) - ).first ?: return - - callback.invoke( - ExtractorLink( - "Olgply", - "Olgply", - foundVideo.url.toString(), - "", - Qualities.Unknown.value, - true - ) - ) - } - suspend fun invokeOlgply( id: Int? = null, season: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit ) { - val url = "https://olgply.xyz/${id}${season?.let { "/$it" } ?: ""}${episode?.let { "/$it" } ?: ""}" + val url = + "https://olgply.xyz/${id}${season?.let { "/$it" } ?: ""}${episode?.let { "/$it" } ?: ""}" loadLinksWithWebView(url, callback) } + suspend fun invokeDbgo( + id: String? = null, + season: Int? = null, + episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val url = if (season == null) { + "$dbgoAPI/imdb.php?id=$id" + } else { + "$dbgoAPI/imdbse.php?id=$id&s=$season&e=$episode" + } + + val doc = app.get(url).document + val iframe = doc.select("div.myvideo iframe").attr("src") + val script = app.get(iframe, referer = "$dbgoAPI/").document.select("script") + .find { it.data().contains("CDNplayerConfig =") }?.data() + + val source = + Regex("['|\"]file['|\"]:\\s['|\"](#\\S+?)['|\"]").find(script.toString())?.groupValues?.get( + 1 + ) + val subtitle = + Regex("['|\"]subtitle['|\"]:\\s['|\"](\\S+?)['|\"]").find(script.toString())?.groupValues?.get( + 1 + ) + + decryptStreamUrl(source.toString()).split(",").map { links -> + val quality = + Regex("\\[([0-9]*p.*?)]").find(links)?.groupValues?.getOrNull(1).toString().trim() + links.replace("[$quality]", "").split("or").map { it.trim() } + .map { link -> + val name = if (link.contains(".m3u8")) "Dbgo (Main)" else "Dbgo (Backup)" + callback.invoke( + ExtractorLink( + name, + name, + link, + "${getBaseUrl(iframe)}/", + getQuality(quality), + isM3u8 = link.contains(".m3u8"), + headers = mapOf( + "Origin" to getBaseUrl(iframe) + ) + ) + ) + } + } + + subtitle?.split(",")?.map { sub -> + val language = + Regex("\\[(.*)]").find(sub)?.groupValues?.getOrNull(1) + .toString() + val link = sub.replace("[$language]", "").trim() + subtitleCallback.invoke( + SubtitleFile( + language, + link + ) + ) + } + + } + +} + +private fun getQuality(str: String): Int { + return when (str) { + "360p" -> Qualities.P240.value + "480p" -> Qualities.P360.value + "720p" -> Qualities.P480.value + "1080p" -> Qualities.P720.value + "1080p Ultra" -> Qualities.P1080.value + else -> getQualityFromName(str) + } +} + +private fun getBaseUrl(url: String): String { + return URI(url).let { + "${it.scheme}://${it.host}" + } +} + +private fun decryptStreamUrl(data: String): String { + + fun getTrash(arr: List, item: Int): List { + val trash = ArrayList>() + for (i in 1..item) { + trash.add(arr) + } + return trash.reduce { acc, list -> + val temp = ArrayList() + acc.forEach { ac -> + list.forEach { li -> + temp.add(ac.plus(li)) + } + } + return@reduce temp + } + } + + val trashList = listOf("@", "#", "!", "^", "$") + val trashSet = getTrash(trashList, 2) + getTrash(trashList, 3) + var trashString = data.replace("#2", "").split("//_//").joinToString("") + + trashSet.forEach { + val temp = base64Encode(it.toByteArray()) + trashString = trashString.replace(temp, "") + } + + return base64Decode(trashString) + +} + +suspend fun loadLinksWithWebView( + url: String, + callback: (ExtractorLink) -> Unit +) { + val foundVideo = WebViewResolver( + Regex("""\.m3u8|i7njdjvszykaieynzsogaysdgb0hm8u1mzubmush4maopa4wde\.com""") + ).resolveUsingWebView( + requestCreator( + "GET", url, referer = "https://olgply.com/" + ) + ).first ?: return + + callback.invoke( + ExtractorLink( + "Olgply", + "Olgply", + foundVideo.url.toString(), + "", + Qualities.Unknown.value, + true + ) + ) } \ No newline at end of file diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 30225d33..9dd383a0 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -2,6 +2,7 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty import com.hexated.RandomUserAgent.getRandomUserAgent +import com.hexated.SoraExtractor.invokeDbgo import com.hexated.SoraExtractor.invokeLocalSources import com.hexated.SoraExtractor.invokeOlgply import com.hexated.SoraExtractor.invokeTwoEmbed @@ -31,9 +32,11 @@ open class SoraStream : TmdbProvider() { private const val tmdbAPI = "https://api.themoviedb.org/3" private const val apiKey = "b030404650f279792a8d3287232358e3" // PLEASE DON'T STEAL val mainAPI = base64DecodeAPI("cHA=LmE=ZWw=cmM=dmU=aC4=dGM=d2E=eHA=Ly8=czo=dHA=aHQ=") - val mainServerAPI = base64DecodeAPI("cA==YXA=bC4=Y2U=ZXI=LnY=aWU=b3Y=LW0=cmE=c28=Ly8=czo=dHA=aHQ=") + val mainServerAPI = + base64DecodeAPI("cA==YXA=bC4=Y2U=ZXI=LnY=aWU=b3Y=LW0=cmE=c28=Ly8=czo=dHA=aHQ=") const val twoEmbedAPI = "https://www.2embed.to" const val vidSrcAPI = "https://v2.vidsrc.me" + const val dbgoAPI = " https://dbgo.fun" fun getType(t: String?): TvType { return when (t) { @@ -253,6 +256,9 @@ open class SoraStream : TmdbProvider() { }, { invokeOlgply(res.id, res.season, res.episode, callback) + }, + { + invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback) })