From 97df334b18a489e6a7c273b798528eaf2c22ba72 Mon Sep 17 00:00:00 2001 From: hexated Date: Sat, 25 Feb 2023 04:32:34 +0700 Subject: [PATCH] fixed shinobi in sora & fixed Hdfilmcehennemi title --- Hdfilmcehennemi/build.gradle.kts | 2 +- .../kotlin/com/hexated/Hdfilmcehennemi.kt | 2 +- OploverzProvider/build.gradle.kts | 2 +- SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 97 +++++++++---------- .../src/main/kotlin/com/hexated/SoraStream.kt | 2 +- .../main/kotlin/com/hexated/SoraStreamLite.kt | 3 +- .../src/main/kotlin/com/hexated/SoraUtils.kt | 81 ++++++++++++++++ 8 files changed, 134 insertions(+), 57 deletions(-) diff --git a/Hdfilmcehennemi/build.gradle.kts b/Hdfilmcehennemi/build.gradle.kts index af74cb6d..da724dbe 100644 --- a/Hdfilmcehennemi/build.gradle.kts +++ b/Hdfilmcehennemi/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 6 +version = 7 cloudstream { diff --git a/Hdfilmcehennemi/src/main/kotlin/com/hexated/Hdfilmcehennemi.kt b/Hdfilmcehennemi/src/main/kotlin/com/hexated/Hdfilmcehennemi.kt index 821c0abf..767fe732 100644 --- a/Hdfilmcehennemi/src/main/kotlin/com/hexated/Hdfilmcehennemi.kt +++ b/Hdfilmcehennemi/src/main/kotlin/com/hexated/Hdfilmcehennemi.kt @@ -42,7 +42,7 @@ class Hdfilmcehennemi : MainAPI() { } private fun Element.toSearchResult(): SearchResponse? { - val title = this.selectFirst("a")?.text() ?: return null + val title = this.selectFirst("h2.title")?.text() ?: return null val href = fixUrlNull(this.selectFirst("a")?.attr("href")) ?: return null val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("data-src")) return newMovieSearchResponse(title, href, TvType.Movie) { diff --git a/OploverzProvider/build.gradle.kts b/OploverzProvider/build.gradle.kts index 125f0ff5..8715a25c 100644 --- a/OploverzProvider/build.gradle.kts +++ b/OploverzProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 8 +version = 9 cloudstream { diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 41de16b8..5df4d746 100644 --- a/SoraStream/build.gradle.kts +++ b/SoraStream/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 95 +version = 96 cloudstream { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index e6f87ce4..1249e5f5 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -709,61 +709,30 @@ object SoraExtractor : SoraStream() { season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit, ) { - val headers = mapOf( - "lang" to "en", - "versioncode" to "32", - "clienttype" to "android_tem3", - ) - val vipAPI = - base64DecodeAPI("cA==YXA=cy8=Y20=di8=LnQ=b2s=a2w=bG8=aS4=YXA=ZS0=aWw=b2I=LW0=Z2E=Ly8=czo=dHA=aHQ=") - val searchUrl = base64DecodeAPI("b20=LmM=b2s=a2w=bG8=Ly8=czo=dHA=aHQ=") + val (id, type) = getSoraIdAndType(title, year, season) ?: return + val json = fetchSoraEpisodes(id, type, episode) ?: return - val doc = app.get("$searchUrl/search?keyword=$title").document - - val scriptData = doc.select("div.search-list div.search-video-card").map { - Triple( - it.selectFirst("h2.title")?.text().toString(), - it.selectFirst("div.desc")?.text() - ?.substringBefore(".")?.toIntOrNull(), - it.selectFirst("a")?.attr("href")?.split("/") + json.subtitlingList?.map { sub -> + subtitleCallback.invoke( + SubtitleFile( + getVipLanguage(sub.languageAbbr ?: return@map), + sub.subtitlingUrl ?: return@map + ) ) } + } - val script = if (scriptData.size == 1) { - scriptData.firstOrNull() - } else { - scriptData.find { - when (season) { - null -> { - it.first.equals( - title, - true - ) && it.second == year - } - 1 -> { - it.first.contains( - "$title", - true - ) && (it.second == year || it.first.contains("Season $season", true)) - } - else -> { - it.first.contains(Regex("(?i)$title\\s?($season|${season.toRomanNumeral()}|Season\\s$season)")) && it.second == year - } - } - } - } - - val id = script?.third?.last() ?: return - val type = script.third?.get(2) ?: return - - val json = app.get( - "$vipAPI/movieDrama/get?id=${id}&category=${type}", - headers = headers - ).parsedSafe()?.data?.episodeVo?.find { - it.seriesNo == (episode ?: 0) - } ?: return + suspend fun invokeSoraStreamLite( + title: String? = null, + year: Int? = null, + season: Int? = null, + episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit, + ) { + val (id, type) = getSoraIdAndType(title, year, season) ?: return + val json = fetchSoraEpisodes(id, type, episode) ?: return json.subtitlingList?.map { sub -> subtitleCallback.invoke( @@ -774,6 +743,23 @@ object SoraExtractor : SoraStream() { ) } + json.definitionList?.map { video -> + val media = app.get( + "${soraAPI}/media/previewInfo?category=${type}&contentId=${id}&episodeId=${json.id}&definition=${video.code}", + headers = soraHeaders, + ).parsedSafe()?.data + + callback.invoke( + ExtractorLink( + this.name, + this.name, + media?.mediaUrl ?: return@map null, + "", + getSoraQuality(media.currentDefinition ?: ""), + true, + ) + ) + } } suspend fun invokeXmovies( @@ -2415,7 +2401,7 @@ object SoraExtractor : SoraStream() { "$api $tags [$size]", "$api $tags [$size]", path, - "", + if(api in needRefererIndex) apiUrl else "", quality, ) ) @@ -2926,4 +2912,13 @@ data class TgarData( data class Gdflix( @JsonProperty("url") val url: String +) + +data class SorastreamResponse( + @JsonProperty("data") val data: SorastreamVideos? = null, +) + +data class SorastreamVideos( + @JsonProperty("mediaUrl") val mediaUrl: String? = null, + @JsonProperty("currentDefinition") val currentDefinition: String? = null, ) \ 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 ca8fb95d..a323c1a4 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -168,6 +168,7 @@ open class SoraStream : TmdbProvider() { "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=453" to "Hulu", "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=2552" to "Apple TV+", "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=49" to "HBO", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=4330" to "Paramount+", "$tmdbAPI/movie/top_rated?api_key=$apiKey®ion=US" to "Top Rated Movies", "$tmdbAPI/tv/top_rated?api_key=$apiKey®ion=US" to "Top Rated TV Shows", "$tmdbAPI/movie/upcoming?api_key=$apiKey®ion=US" to "Upcoming Movies", @@ -355,7 +356,6 @@ open class SoraStream : TmdbProvider() { res.season, res.episode, subtitleCallback, - callback, ) }, { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index 5af1dcb6..d4005b26 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -21,6 +21,7 @@ import com.hexated.SoraExtractor.invokeRStream import com.hexated.SoraExtractor.invokeSeries9 import com.hexated.SoraExtractor.invokeSmashyStream import com.hexated.SoraExtractor.invokeSoraStream +import com.hexated.SoraExtractor.invokeSoraStreamLite import com.hexated.SoraExtractor.invokeTwoEmbed import com.hexated.SoraExtractor.invokeUniqueStream import com.hexated.SoraExtractor.invokeVidSrc @@ -53,7 +54,7 @@ class SoraStreamLite : SoraStream() { ) }, { - invokeSoraStream( + invokeSoraStreamLite( res.title, res.year, res.season, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 4d38f60a..fdbc1dce 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -1,6 +1,7 @@ package com.hexated import android.util.Base64 +import com.hexated.SoraStream.Companion.base64DecodeAPI import com.hexated.SoraStream.Companion.baymoviesAPI import com.hexated.SoraStream.Companion.consumetCrunchyrollAPI import com.hexated.SoraStream.Companion.filmxyAPI @@ -35,6 +36,15 @@ import kotlin.collections.ArrayList import kotlin.collections.HashMap import kotlin.math.min +val soraAPI = base64DecodeAPI("cA==YXA=cy8=Y20=di8=LnQ=b2s=a2w=bG8=aS4=YXA=ZS0=aWw=b2I=LW0=Z2E=Ly8=czo=dHA=aHQ=") + +val soraHeaders = mapOf( + "lang" to "en", + "versioncode" to "32", + "clienttype" to "android_tem3", + "deviceid" to getDeviceId(), +) + val encodedIndex = arrayOf( "GamMovies", "JSMovies", @@ -67,6 +77,10 @@ val untrimmedIndex = arrayOf( "EdithxMovies", ) +val needRefererIndex = arrayOf( + "ShinobiMovies", +) + val mimeType = arrayOf( "video/x-matroska", "video/mp4", @@ -442,6 +456,56 @@ suspend fun invokeSmashyTwo( ) } +suspend fun getSoraIdAndType(title: String?, year: Int?, season: Int?) : Pair? { + val doc = app.get("${base64DecodeAPI("b20=LmM=b2s=a2w=bG8=Ly8=czo=dHA=aHQ=")}/search?keyword=$title").document + val scriptData = doc.select("div.search-list div.search-video-card").map { + Triple( + it.selectFirst("h2.title")?.text().toString(), + it.selectFirst("div.desc")?.text() + ?.substringBefore(".")?.toIntOrNull(), + it.selectFirst("a")?.attr("href")?.split("/") + ) + } + + val script = if (scriptData.size == 1) { + scriptData.firstOrNull() + } else { + scriptData.find { + when (season) { + null -> { + it.first.equals( + title, + true + ) && it.second == year + } + 1 -> { + it.first.contains( + "$title", + true + ) && (it.second == year || it.first.contains("Season $season", true)) + } + else -> { + it.first.contains(Regex("(?i)$title\\s?($season|${season.toRomanNumeral()}|Season\\s$season)")) && it.second == year + } + } + } + } + + val id = script?.third?.last() ?: return null + val type = script.third?.get(2) ?: return null + + return id to type +} + +suspend fun fetchSoraEpisodes(id: String, type: String, episode: Int?) : EpisodeVo? { + return app.get( + "$soraAPI/movieDrama/get?id=${id}&category=${type}", + headers = soraHeaders + ).parsedSafe()?.data?.episodeVo?.find { + it.seriesNo == (episode ?: 0) + } +} + suspend fun bypassOuo(url: String?): String? { var res = session.get(url ?: return null) run lit@{ @@ -832,6 +896,16 @@ fun getGMoviesQuality(str: String): Int { } } +fun getSoraQuality(quality: String): Int { + return when (quality) { + "GROOT_FD" -> Qualities.P360.value + "GROOT_LD" -> Qualities.P480.value + "GROOT_SD" -> Qualities.P720.value + "GROOT_HD" -> Qualities.P1080.value + else -> Qualities.Unknown.value + } +} + fun getFDoviesQuality(str: String): String { return when { str.contains("1080P", true) -> "1080P" @@ -858,6 +932,13 @@ fun getDbgoLanguage(str: String): String { } } +fun getDeviceId(length: Int = 16): String { + val allowedChars = ('a'..'f') + ('0'..'9') + return (1..length) + .map { allowedChars.random() } + .joinToString("") +} + fun String.encodeUrl(): String { val url = URL(this) val uri = URI(url.protocol, url.userInfo, url.host, url.port, url.path, url.query, url.ref)