From 8a31e3acb00232303d9133316d7e399c5747e107 Mon Sep 17 00:00:00 2001 From: Olivia Date: Thu, 25 Jan 2024 14:56:40 +0700 Subject: [PATCH] sora: fix few sources --- .../src/main/kotlin/com/hexated/Extractors.kt | 6 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 141 +++++------------- .../src/main/kotlin/com/hexated/SoraParser.kt | 9 -- .../src/main/kotlin/com/hexated/SoraStream.kt | 16 +- .../main/kotlin/com/hexated/SoraStreamLite.kt | 16 +- .../kotlin/com/hexated/SoraStreamPlugin.kt | 2 +- .../src/main/kotlin/com/hexated/SoraUtils.kt | 83 ++++------- 7 files changed, 69 insertions(+), 204 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt index b11a7d31..8026449c 100644 --- a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt +++ b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt @@ -436,9 +436,9 @@ class Streamwish : Filesim() { override var mainUrl = "https://streamwish.to" } -class Wishfast : Filesim() { - override val name = "Wishfast" - override var mainUrl = "https://wishfast.top" +class UqloadsXyz : Filesim() { + override val name = "Uqloads" + override var mainUrl = "https://uqloads.xyz" } class FilelionsTo : Filesim() { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 6a0422a7..b19d9a1d 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -124,8 +124,8 @@ object SoraExtractor : SoraStream() { httpsify(srcrcp), referer = iframedoc ).document.selectFirst("script:containsData(Playerjs)")?.data() - val video = script?.substringAfter("file:\"#2")?.substringBefore("\"") - ?.replace(Regex("/.*?=?="), "")?.let { base64Decode(it) } + val video = script?.substringAfter("file:\"#9")?.substringBefore("\"") + ?.replace(Regex("/@#@\\S+?=?="), "")?.let { base64Decode(it) } callback.invoke( ExtractorLink( @@ -135,66 +135,6 @@ object SoraExtractor : SoraStream() { ) } - suspend fun invokeDbgo( - id: String? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { - - val iframeDbgo: String? - val script = if (season == null) { - val doc = app.get("$dbgoAPI/imdb.php?id=$id").document - iframeDbgo = doc.select("div.myvideo iframe").attr("src") - app.get(iframeDbgo, referer = "$dbgoAPI/").document.select("script") - .find { it.data().contains("CDNplayerConfig =") }?.data() - } else { - val doc = app.get("$dbgoAPI/tv-imdb.php?id=$id&s=$season").document - iframeDbgo = doc.select("div.myvideo iframe").attr("src") - val token = app.get( - iframeDbgo, - referer = "$dbgoAPI/" - ).document.selectFirst("select#translator-name option")?.attr("data-token") - app.get("https://voidboost.net/serial/$token/iframe?s=$season&e=$episode&h=dbgo.fun").document.select( - "script" - ).find { it.data().contains("CDNplayerConfig =") }?.data() - } ?: return - - val source = - Regex("['|\"]file['|\"]:\\s['|\"](#\\S+?)['|\"]").find(script)?.groupValues?.get(1) - ?: return - val subtitle = - Regex("['|\"]subtitle['|\"]:\\s['|\"](\\S+?)['|\"]").find(script)?.groupValues?.get(1) - - val ref = getBaseUrl(iframeDbgo) - decryptStreamUrl(source).split(",").map { links -> - val quality = Regex("\\[(\\d*p.*?)]").find(links)?.groupValues?.getOrNull(1)?.trim() - ?: return@map null - 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, - "$ref/", - getQuality(quality), - isM3u8 = link.contains(".m3u8"), - headers = mapOf("Origin" to ref) - ) - ) - } - } - - subtitle?.split(",")?.map { sub -> - val language = Regex("\\[(.*)]").find(sub)?.groupValues?.getOrNull(1) ?: return@map null - val link = sub.replace("[$language]", "").trim() - subtitleCallback.invoke(SubtitleFile(getDbgoLanguage(language), link)) - } - - } - suspend fun invokeDreamfilm( title: String? = null, season: Int? = null, @@ -1787,21 +1727,21 @@ object SoraExtractor : SoraStream() { } suspend fun invokeSmashyStream( - imdbId: String? = null, + tmdbId: Int? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit, ) { val url = if (season == null) { - "$smashyStreamAPI/playere.php?imdb=$imdbId" + "$smashyStreamAPI/playere.php?tmdb=$tmdbId" } else { - "$smashyStreamAPI/playere.php?imdb=$imdbId&season=$season&episode=$episode" + "$smashyStreamAPI/playere.php?tmdb=$tmdbId&season=$season&episode=$episode" } app.get( url, - referer = "https://smashystream.com/" + referer = "https://smashystream.xyz/" ).document.select("div#_default-servers a.server").map { it.attr("data-url") to it.text() }.apmap { @@ -1809,11 +1749,9 @@ object SoraExtractor : SoraStream() { "Player F" -> { invokeSmashyFfix(it.second, it.first, url, subtitleCallback, callback) } - - "Player D (Hindi)" -> { - invokeSmashyD(it.first, url, callback) + "Player SU" -> { + invokeSmashySu(it.second, it.first, url, subtitleCallback, callback) } - else -> return@apmap } } @@ -2145,7 +2083,7 @@ object SoraExtractor : SoraStream() { ?: return val ref = getBaseUrl(framesrc) val id = framesrc.substringAfter("id=").substringBefore("&") - loadExtractor("https://wishfast.top/e/$id", "$ref/", subtitleCallback, callback) + loadExtractor("https://uqloads.xyz/e/$id", "$ref/", subtitleCallback, callback) } @@ -2181,7 +2119,7 @@ object SoraExtractor : SoraStream() { episodeSelector: String, ) { fun String.decrypt(key: String): List? { - return tryParseJson>(base64Decode(this).decodePrimewireXor(key)) + return tryParseJson>(base64Decode(this).xorDecrypt(key)) } val slug = getEpisodeSlug(season, episode) @@ -2193,7 +2131,10 @@ object SoraExtractor : SoraStream() { val savedCookies = mapOf( base64Decode("X2lkZW50aXR5Z29tb3ZpZXM3") to base64Decode("NTJmZGM3MGIwMDhjMGIxZDg4MWRhYzBmMDFjY2E4MTllZGQ1MTJkZTAxY2M4YmJjMTIyNGVkNGFhZmI3OGI1MmElM0EyJTNBJTdCaSUzQTAlM0JzJTNBMTglM0ElMjJfaWRlbnRpdHlnb21vdmllczclMjIlM0JpJTNBMSUzQnMlM0E1MiUzQSUyMiU1QjIwNTAzNjYlMkMlMjJIblZSUkFPYlRBU09KRXI0NVl5Q004d2lIb2wwVjFrbyUyMiUyQzI1OTIwMDAlNUQlMjIlM0IlN0Q="), ) - val doc = app.get("$api/search/$query").document + + var res = app.get("$api/search/$query") + val cookies = savedCookies + res.cookies + val doc = res.document val media = doc.select("div.$mediaSelector").map { Triple(it.attr("data-filmName"), it.attr("data-year"), it.select("a").attr("href")) }.let { el -> @@ -2216,31 +2157,29 @@ object SoraExtractor : SoraStream() { val iframe = if (season == null) { media.third } else { - val res = app.get(fixUrl(media.third, api)) - res.document.selectFirst("div#$episodeSelector a:contains(Episode ${slug.second})") + app.get(fixUrl(media.third, api), cookies = cookies) + .document.selectFirst("div#$episodeSelector a:contains(Episode ${slug.second})") ?.attr("href") - } ?: return - - val res = app.get(fixUrl(iframe, api), verify = false) - val cookies = savedCookies + res.cookies + } + res = app.get(fixUrl(iframe ?: return, api), cookies = cookies) val url = res.document.select("meta[property=og:url]").attr("content") val headers = mapOf("X-Requested-With" to "XMLHttpRequest") val qualities = intArrayOf(2160, 1440, 1080, 720, 480, 360) - val (serverId, episodeId) = if(season == null) { + val (serverId, episodeId) = if (season == null) { url.substringAfterLast("/") to "0" } else { - url.substringBeforeLast("/").substringAfterLast("/") to url.substringAfterLast("/").substringBefore("-") + url.substringBeforeLast("/").substringAfterLast("/") to url.substringAfterLast("/") + .substringBefore("-") } val serverRes = app.get( "$api/user/servers/$serverId?ep=$episodeId", cookies = cookies, referer = url, headers = headers - ) - val serverDoc = serverRes.document - serverDoc.select("ul li").apmap { el -> + ).document + serverRes.select("ul li").apmap { el -> val server = el.attr("data-value") val encryptedData = app.get( "$url?server=$server&_=$unixTimeMS", @@ -2428,37 +2367,25 @@ object SoraExtractor : SoraStream() { suspend fun invokeRidomovies( tmdbId: Int? = null, imdbId: String? = null, - title: String? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit, ) { - val slug = if (season == null) { - app.get("$ridomoviesAPI/core/api/search?q=$imdbId") - .parsedSafe()?.data?.items?.find { - it.contentable?.tmdbId == tmdbId || it.contentable?.imdbId == imdbId - }?.slug - } else { - app.get("$ridomoviesAPI/tv/${title.createSlug()}/season-$season/episode-$episode").text.substringAfterLast( - """postid\":\"""" - ).substringBefore("""\"""") - } ?: return - val url = if (season == null) { - "$ridomoviesAPI/core/api/movies/$slug/videos" - } else { - "$ridomoviesAPI/core/api/episodes/$slug/videos" - } + val mediaSlug = app.get("$ridomoviesAPI/core/api/search?q=$imdbId").parsedSafe()?.data?.items?.find { + it.contentable?.tmdbId == tmdbId || it.contentable?.imdbId == imdbId + }?.slug ?: return + + val id = season?.let { + val episodeUrl = "$ridomoviesAPI/tv/$mediaSlug/season-$it/episode-$episode" + app.get(episodeUrl).text.substringAfterLast("""postid\":\"""").substringBefore("""\""") + } ?: mediaSlug + + val url = "$ridomoviesAPI/core/api/${if (season == null) "movies" else "episodes"}/$id/videos" app.get(url).parsedSafe()?.data?.apmap { link -> val iframe = Jsoup.parse(link.url ?: return@apmap).select("iframe").attr("data-src") if (iframe.startsWith("https://closeload.top")) { - val unpacked = - getAndUnpack( - app.get( - iframe, - referer = "$ridomoviesAPI/" - ).text - ) + val unpacked = getAndUnpack(app.get(iframe, referer = "$ridomoviesAPI/").text) val video = Regex("=\"(aHR.*?)\";").find(unpacked)?.groupValues?.get(1) callback.invoke( ExtractorLink( diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index 199833bf..b09fa747 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -460,15 +460,6 @@ data class SmashySources( @JsonProperty("subtitleUrls") var subtitleUrls: String? = null, ) -data class SmashyDSources( - @JsonProperty("sourceUrls") var sourceUrls: ArrayList? = arrayListOf(), -) - -data class SmashyDSourcesUrls( - @JsonProperty("file") var file: String? = null, - @JsonProperty("title") var title: String? = null, -) - data class AoneroomResponse( @JsonProperty("data") val data: Data? = null, ) { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 045ad668..8d3033c4 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -6,7 +6,6 @@ import com.hexated.SoraExtractor.invokeAllMovieland import com.hexated.SoraExtractor.invokeAnimes import com.hexated.SoraExtractor.invokeAoneroom import com.hexated.SoraExtractor.invokeBollyMaza -import com.hexated.SoraExtractor.invokeDbgo import com.hexated.SoraExtractor.invokeFilmxy import com.hexated.SoraExtractor.invokeKimcartoon import com.hexated.SoraExtractor.invokeVidSrc @@ -384,9 +383,6 @@ open class SoraStream : TmdbProvider() { { invokeVidSrc(res.id, res.season, res.episode, callback) }, - { - invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback) - }, { if (!res.isAnime) invokeAoneroom( res.title, res.airedYear @@ -547,7 +543,7 @@ open class SoraStream : TmdbProvider() { }, { if (!res.isAnime) invokeSmashyStream( - res.imdbId, + res.id, res.season, res.episode, subtitleCallback, @@ -587,7 +583,6 @@ open class SoraStream : TmdbProvider() { if (!res.isAnime) invokeRidomovies( res.id, res.imdbId, - res.title, res.season, res.episode, subtitleCallback, @@ -715,15 +710,6 @@ open class SoraStream : TmdbProvider() { callback ) }, -// { -// if (!res.isAnime) invokeSFMovies( -// res.id, res.title, res.airedYear -// ?: res.year, res.season, res.episode, callback -// ) -// }, -// { -// invokeMMovies(res.title, res.season, res.episode, subtitleCallback, callback) -// }, { if (!res.isAnime) invokeMoflix(res.id, res.season, res.episode, callback) }, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index ace55c04..9c09c047 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -4,7 +4,6 @@ import com.hexated.SoraExtractor.invoke2embed import com.hexated.SoraExtractor.invokeAllMovieland import com.hexated.SoraExtractor.invokeAnimes import com.hexated.SoraExtractor.invokeAoneroom -import com.hexated.SoraExtractor.invokeDbgo import com.hexated.SoraExtractor.invokeDoomovies import com.hexated.SoraExtractor.invokeDramaday import com.hexated.SoraExtractor.invokeDreamfilm @@ -95,9 +94,6 @@ class SoraStreamLite : SoraStream() { { invokeVidSrc(res.id, res.season, res.episode, callback) }, - { - invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback) - }, { if (!res.isAnime && res.isCartoon) invokeWatchCartoon( res.title, @@ -158,7 +154,7 @@ class SoraStreamLite : SoraStream() { }, { if (!res.isAnime) invokeSmashyStream( - res.imdbId, + res.id, res.season, res.episode, subtitleCallback, @@ -228,7 +224,6 @@ class SoraStreamLite : SoraStream() { if (!res.isAnime) invokeRidomovies( res.id, res.imdbId, - res.title, res.season, res.episode, subtitleCallback, @@ -324,15 +319,6 @@ class SoraStreamLite : SoraStream() { callback ) }, -// { -// if (!res.isAnime) invokeSFMovies( -// res.id, res.title, res.airedYear -// ?: res.year, res.season, res.episode, callback -// ) -// }, -// { -// invokeMMovies(res.title, res.season, res.episode, subtitleCallback, callback) -// }, ) return true diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt index abc461c1..32957fd2 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt @@ -25,7 +25,7 @@ class SoraStreamPlugin: Plugin() { registerExtractorAPI(Streamwish()) registerExtractorAPI(FilelionsTo()) registerExtractorAPI(Embedwish()) - registerExtractorAPI(Wishfast()) + registerExtractorAPI(UqloadsXyz()) registerExtractorAPI(Uploadever()) registerExtractorAPI(Netembed()) registerExtractorAPI(Flaswish()) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 9e52fc36..3b1921db 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -18,17 +18,12 @@ import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.nicehttp.NiceResponse import com.lagradost.nicehttp.RequestBodyTypes -import com.lagradost.nicehttp.Requests.Companion.await import com.lagradost.nicehttp.requestCreator import kotlinx.coroutines.delay import okhttp3.FormBody import okhttp3.HttpUrl.Companion.toHttpUrl -import okhttp3.Interceptor import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.OkHttpClient -import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody -import okhttp3.Response import org.jsoup.nodes.Document import java.math.BigInteger import java.net.* @@ -38,7 +33,6 @@ import java.security.spec.PKCS8EncodedKeySpec import java.security.spec.X509EncodedKeySpec import java.text.SimpleDateFormat import java.util.* -import java.util.concurrent.TimeUnit import javax.crypto.Cipher import javax.crypto.spec.GCMParameterSpec import javax.crypto.spec.IvParameterSpec @@ -427,19 +421,39 @@ suspend fun invokeSmashyFfix( } -suspend fun invokeSmashyD( +suspend fun invokeSmashySu( + name: String, url: String, ref: String, + subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit, ) { val json = app.get(url, referer = ref, headers = mapOf("X-Requested-With" to "XMLHttpRequest")) - .parsedSafe() - json?.sourceUrls?.apmap { - M3u8Helper.generateM3u8( - "Smashy [Player D ${it.title}]", - it.file ?: return@apmap, - "" - ).forEach(callback) + .parsedSafe() + json?.sourceUrls?.firstOrNull()?.removeSuffix(",")?.split(",")?.forEach { links -> + val quality = Regex("\\[(\\S+)]").find(links)?.groupValues?.getOrNull(1) ?: return@forEach + val trimmedLink = links.removePrefix("[$quality]").trim() + callback.invoke( + ExtractorLink( + "Smashy [$name]", + "Smashy [$name]", + trimmedLink, + "", + quality.toIntOrNull() ?: Qualities.Unknown.value, + INFER_TYPE + ) + ) + } + + json?.subtitleUrls?.removeSuffix(",")?.split(",")?.forEach { sub -> + val lang = "\\[(.*)]".toRegex().find(sub)?.groupValues?.get(1) + val subUrl = sub.replace("[$lang]", "").trim() + subtitleCallback.invoke( + SubtitleFile( + lang ?: return@forEach, + subUrl + ) + ) } } @@ -1038,7 +1052,7 @@ fun decodeIndexJson(json: String): String { return base64Decode(slug.substring(0, slug.length - 20)) } -fun String.decodePrimewireXor(key: String): String { +fun String.xorDecrypt(key: String): String { val sb = StringBuilder() var i = 0 while (i < this.length) { @@ -1152,14 +1166,6 @@ fun getVipLanguage(str: String): String { } } -fun getDbgoLanguage(str: String): String { - return when (str) { - "Русский" -> "Russian" - "Українська" -> "Ukrainian" - else -> str - } -} - fun fixCrunchyrollLang(language: String?): String? { return SubtitleHelper.fromTwoLettersToLanguage(language ?: return null) ?: SubtitleHelper.fromTwoLettersToLanguage(language.substringBefore("-")) @@ -1216,37 +1222,6 @@ fun base64DecodeAPI(api: String): String { return api.chunked(4).map { base64Decode(it) }.reversed().joinToString("") } -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) - -} - fun fixUrl(url: String, domain: String): String { if (url.startsWith("http")) { return url