From 5654e312460f0ea13dbaf6d9e10401bce03440ca Mon Sep 17 00:00:00 2001 From: hexated Date: Sat, 19 Aug 2023 03:48:57 +0700 Subject: [PATCH] sora: fix UHD? --- .github/workflows/build.yml | 4 +- SoraStream/build.gradle.kts | 4 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 49 +++++++++++-------- .../src/main/kotlin/com/hexated/SoraParser.kt | 36 +------------- .../src/main/kotlin/com/hexated/SoraStream.kt | 6 +-- .../main/kotlin/com/hexated/SoraStreamLite.kt | 4 +- .../src/main/kotlin/com/hexated/SoraUtils.kt | 42 ++++++++++++---- .../kotlin/com/hexated/YomoviesProvider.kt | 2 +- 8 files changed, 71 insertions(+), 76 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3d905d0f..2ea8a425 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,7 +54,7 @@ jobs: ANICHI_SERVER: ${{ secrets.ANICHI_SERVER }} ANICHI_ENDPOINT: ${{ secrets.ANICHI_ENDPOINT }} ANICHI_APP: ${{ secrets.ANICHI_APP }} - GOMOVIES_KEY: ${{ secrets.GOMOVIES_KEY }} + PRIMEWIRE_KEY: ${{ secrets.PRIMEWIRE_KEY }} run: | cd $GITHUB_WORKSPACE/src echo SORA_API=$SORA_API >> local.properties @@ -69,7 +69,7 @@ jobs: echo ANICHI_SERVER=$ANICHI_SERVER >> local.properties echo ANICHI_ENDPOINT=$ANICHI_ENDPOINT >> local.properties echo ANICHI_APP=$ANICHI_APP >> local.properties - echo GOMOVIES_KEY=$GOMOVIES_KEY >> local.properties + echo PRIMEWIRE_KEY=$PRIMEWIRE_KEY >> local.properties - name: Build Plugins run: | diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index b579a1b1..b2614d35 100644 --- a/SoraStream/build.gradle.kts +++ b/SoraStream/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.konan.properties.Properties // use an integer for version numbers -version = 156 +version = 157 android { defaultConfig { @@ -14,7 +14,7 @@ android { buildConfigField("String", "SORATED", "\"${properties.getProperty("SORATED")}\"") buildConfigField("String", "DUMP_API", "\"${properties.getProperty("DUMP_API")}\"") buildConfigField("String", "DUMP_KEY", "\"${properties.getProperty("DUMP_KEY")}\"") - buildConfigField("String", "GOMOVIES_KEY", "\"${properties.getProperty("GOMOVIES_KEY")}\"") + buildConfigField("String", "PRIMEWIRE_KEY", "\"${properties.getProperty("PRIMEWIRE_KEY")}\"") buildConfigField("String", "CRUNCHYROLL_BASIC_TOKEN", "\"${properties.getProperty("CRUNCHYROLL_BASIC_TOKEN")}\"") buildConfigField("String", "CRUNCHYROLL_REFRESH_TOKEN", "\"${properties.getProperty("CRUNCHYROLL_REFRESH_TOKEN")}\"") diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 8004b826..527338ac 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -1127,13 +1127,19 @@ object SoraExtractor : SoraStream() { link ?: return@apmap ) val base = getBaseUrl(driveLink ?: return@apmap) - val resDoc = app.get(driveLink).document - val bitLink = resDoc.selectFirst("a.btn.btn-outline-success")?.attr("href") - val downloadLink = if (bitLink.isNullOrEmpty()) { - val backupIframe = resDoc.select("a.btn.btn-outline-warning").attr("href") - extractBackupUHD(backupIframe ?: return@apmap) - } else { - extractMirrorUHD(bitLink, base) + val driveReq = app.get(driveLink) + val driveRes = driveReq.document + val bitLink = driveRes.select("a.btn.btn-outline-success").attr("href") + val downloadLink = when { + driveRes.select("button.btn.btn-success").text() + .contains("Direct Download", true) -> extractDirectUHD(driveLink, driveReq) + bitLink.isNullOrEmpty() -> { + val backupIframe = driveRes.select("a.btn.btn-outline-warning").attr("href") + extractBackupUHD(backupIframe ?: return@apmap) + } + else -> { + extractMirrorUHD(bitLink, base) + } } val tags = getUhdTags(quality) @@ -2138,7 +2144,7 @@ object SoraExtractor : SoraStream() { } - suspend fun invokeGomovies( + suspend fun invokePrimewire( title: String? = null, year: Int? = null, season: Int? = null, @@ -2152,9 +2158,9 @@ object SoraExtractor : SoraStream() { "$title Season $season" } - val doc = app.get("$gomoviesAPI/search/$query").document + val doc = app.get("$primewireAPI/search/$query").document - val media = doc.select("div._gory div.g_yFsxmKnYLvpKDTrdbizeYMWy").map { + val media = doc.select("div.RvnMfoxhgm").map { Triple( it.attr("data-filmName"), it.attr("data-year"), @@ -2183,21 +2189,21 @@ object SoraExtractor : SoraStream() { app.get( fixUrl( media.third, - gomoviesAPI + primewireAPI ) - ).document.selectFirst("div#g_MXOzFGouZrOAUioXjpddqkZK a:contains(Episode ${slug.second})") + ).document.selectFirst("div#vvqUtffkId a:contains(Episode ${slug.second})") ?.attr("href") } ?: return - val res = app.get(fixUrl(iframe, gomoviesAPI), verify = false) + val res = app.get(fixUrl(iframe, primewireAPI), verify = false) val match = "var url = '(/user/servers/.*?\\?ep=.*?)';".toRegex().find(res.text) val serverUrl = match?.groupValues?.get(1) ?: return - val cookies = res.okhttpResponse.headers.getGomoviesCookies() + val cookies = res.okhttpResponse.headers.getPrimewireCookies() 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) app.get( - "$gomoviesAPI$serverUrl", + "$primewireAPI$serverUrl", cookies = cookies, referer = url, headers = headers ).document.select("ul li").amap { el -> val server = el.attr("data-value") @@ -2207,16 +2213,16 @@ object SoraExtractor : SoraStream() { referer = url, headers = headers ).text - val json = base64Decode(encryptedData).decryptGomoviesJson() - val links = tryParseJson>(json) ?: return@amap + val json = base64Decode(encryptedData).decodePrimewireXor() + val links = tryParseJson>(json) ?: return@amap links.forEach { video -> qualities.filter { it <= video.max.toInt() }.forEach { callback( ExtractorLink( - "Gomovies", - "Gomovies", + "Primewire", + "Primewire", video.src.split("360", limit = 3).joinToString(it.toString()), - "$gomoviesAPI/", + "$primewireAPI/", it, ) ) @@ -2535,7 +2541,8 @@ object SoraExtractor : SoraStream() { ) { val referer = "https://2now.tv/" val slug = getEpisodeSlug(season, episode) - val url = if (season == null) "$nowTvAPI/$tmdbId.mp4" else "$nowTvAPI/tv/$tmdbId/s${season}e${slug.second}.mp4" + val url = + if (season == null) "$nowTvAPI/$tmdbId.mp4" else "$nowTvAPI/tv/$tmdbId/s${season}e${slug.second}.mp4" if (!app.get(url, referer = referer).isSuccessful) return callback.invoke( ExtractorLink( diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index 382d507c..8387ccb9 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -9,12 +9,6 @@ data class FDMovieIFrame( val type: String, ) -data class BaymoviesConfig( - val country: String, - val downloadTime: String, - val workers: List -) - data class AniIds( var id: Int? = null, var idMal: Int? = null @@ -37,26 +31,7 @@ data class AniSearch( @JsonProperty("data") var data: AniData? = AniData() ) -data class Tmdb2Anilist( - @JsonProperty("tmdb_id") val tmdb_id: String? = null, - @JsonProperty("anilist_id") val anilist_id: String? = null, - @JsonProperty("mal_id") val mal_id: String? = null, -) - -data class Movie123Media( - @JsonProperty("url") val url: String? = null, -) - -data class Movie123Data( - @JsonProperty("t") val t: String? = null, - @JsonProperty("s") val s: String? = null, -) - -data class Movie123Search( - @JsonProperty("data") val data: ArrayList? = arrayListOf(), -) - -data class GomoviesSources( +data class PrimewireSources( @JsonProperty("src") val src: String, @JsonProperty("file") val file: String? = null, @JsonProperty("label") val label: Int? = null, @@ -202,15 +177,6 @@ data class IndexSearch( @JsonProperty("data") val data: IndexData? = null, ) -data class SorastreamResponse( - @JsonProperty("data") val data: SorastreamVideos? = null, -) - -data class SorastreamVideos( - @JsonProperty("mediaUrl") val mediaUrl: String? = null, - @JsonProperty("currentDefinition") val currentDefinition: String? = null, -) - data class BiliBiliEpisodes( @JsonProperty("id") val id: Int? = null, @JsonProperty("sourceId") val sourceId: String? = null, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 3d27c454..0b26e62c 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -25,7 +25,6 @@ import com.hexated.SoraExtractor.invokeFmovies import com.hexated.SoraExtractor.invokeFwatayako import com.hexated.SoraExtractor.invokeGMovies import com.hexated.SoraExtractor.invokeGoku -import com.hexated.SoraExtractor.invokeGomovies import com.hexated.SoraExtractor.invokeKisskh import com.hexated.SoraExtractor.invokeLing import com.hexated.SoraExtractor.invokeM4uhd @@ -46,6 +45,7 @@ import com.hexated.SoraExtractor.invokeMoment import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokeNetmovies import com.hexated.SoraExtractor.invokePobmovies +import com.hexated.SoraExtractor.invokePrimewire import com.hexated.SoraExtractor.invokeTvMovies import com.hexated.SoraExtractor.invokeUhdmovies import com.hexated.SoraExtractor.invokeWatchOnline @@ -111,7 +111,6 @@ open class SoraStream : TmdbProvider() { const val flixonAPI = "https://flixon.lol" const val smashyStreamAPI = "https://embed.smashystream.com" const val watchSomuchAPI = "https://watchsomuch.tv" // sub only - val gomoviesAPI = base64DecodeAPI("bQ==Y28=ZS4=aW4=bmw=LW8=ZXM=dmk=bW8=Z28=Ly8=czo=dHA=aHQ=") const val ask4MoviesAPI = "https://ask4movie.nl" const val biliBiliAPI = "https://api-vn.otakuz.live/server" const val watchOnlineAPI = "https://watchonline.ag" @@ -129,6 +128,7 @@ open class SoraStream : TmdbProvider() { const val netmoviesAPI = "https://netmovies.to" const val momentAPI = "https://moment-explanation-i-244.site" const val doomoviesAPI = "https://doomovies.net" + const val primewireAPI = "https://real-primewire.club" // INDEX SITE const val dahmerMoviesAPI = "https://edytjedhgmdhm.abfhaqrhbnf.workers.dev" @@ -615,7 +615,7 @@ open class SoraStream : TmdbProvider() { ) }, { - invokeGomovies(res.title, res.year, res.season, res.episode, callback) + invokePrimewire(res.title, res.year, res.season, res.episode, callback) }, // { // if (!res.isAnime) invokeGdbotMovies( diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index 1558a2f7..63cc091b 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -10,7 +10,6 @@ import com.hexated.SoraExtractor.invokeFlixon import com.hexated.SoraExtractor.invokeFmovies import com.hexated.SoraExtractor.invokeFwatayako import com.hexated.SoraExtractor.invokeGoku -import com.hexated.SoraExtractor.invokeGomovies import com.hexated.SoraExtractor.invokeHDMovieBox import com.hexated.SoraExtractor.invokeIdlix import com.hexated.SoraExtractor.invokeKimcartoon @@ -32,6 +31,7 @@ import com.hexated.SoraExtractor.invokeFourCartoon import com.hexated.SoraExtractor.invokeMoment import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokeNetmovies +import com.hexated.SoraExtractor.invokePrimewire import com.hexated.SoraExtractor.invokeVidSrc import com.hexated.SoraExtractor.invokeWatchOnline import com.hexated.SoraExtractor.invokeWatchsomuch @@ -268,7 +268,7 @@ class SoraStreamLite : SoraStream() { invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback) }, { - invokeGomovies(res.title, res.year, res.season, res.episode, callback) + invokePrimewire(res.title, res.year, res.season, res.episode, callback) }, { if (!res.isAnime) invokeAsk4Movies( diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 23eea4c4..c918810b 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -165,6 +165,34 @@ suspend fun extractMirrorUHD(url: String, ref: String): String? { ) } +suspend fun extractDirectUHD(url: String, niceResponse: NiceResponse): String? { + val document = niceResponse.document + val script = document.selectFirst("script:containsData(cf_token)")?.data() ?: return null + val actionToken = script.substringAfter("\"key\", \"").substringBefore("\");") + val cfToken = script.substringAfter("cf_token = \"").substringBefore("\";") + val body = FormBody.Builder() + .addEncoded("action", "direct") + .addEncoded("key", actionToken) + .addEncoded("action_token", cfToken) + .build() + val cookies = mapOf("PHPSESSID" to "${niceResponse.cookies["PHPSESSID"]}") + val direct = app.post( + url, + requestBody = body, + cookies = cookies, + referer = url, + headers = mapOf( + "x-token" to "driveleech.org" + ) + ).parsedSafe>()?.get("url") + + return app.get( + direct ?: return null, cookies = cookies, + referer = url + ).text.substringAfter("worker_url = '").substringBefore("';") + +} + suspend fun extractBackupUHD(url: String): String? { val resumeDoc = app.get(url) @@ -425,14 +453,8 @@ suspend fun invokeSmashyFfix( ref: String, callback: (ExtractorLink) -> Unit, ) { - val script = - app.get(url, referer = ref).document.selectFirst("script:containsData(player =)")?.data() - ?: return - - val source = - Regex("['\"]?file['\"]?:\\s*\"([^\"]+)").find(script)?.groupValues?.get( - 1 - ) ?: return + val res = app.get(url, referer = ref).text + val source = Regex("['\"]?file['\"]?:\\s*\"([^\"]+)").find(res)?.groupValues?.get(1) ?: return source.split(",").map { links -> val quality = Regex("\\[(\\d+)]").find(links)?.groupValues?.getOrNull(1)?.trim() @@ -1283,7 +1305,7 @@ fun decodeIndexJson(json: String): String { return base64Decode(slug.substring(0, slug.length - 20)) } -fun String.decryptGomoviesJson(key: String = BuildConfig.GOMOVIES_KEY): String { +fun String.decodePrimewireXor(key: String = BuildConfig.PRIMEWIRE_KEY): String { val sb = StringBuilder() var i = 0 while (i < this.length) { @@ -1297,7 +1319,7 @@ fun String.decryptGomoviesJson(key: String = BuildConfig.GOMOVIES_KEY): String { return sb.toString() } -fun Headers.getGomoviesCookies(cookieKey: String = "set-cookie"): Map { +fun Headers.getPrimewireCookies(cookieKey: String = "set-cookie"): Map { val cookieList = this.filter { it.first.equals(cookieKey, ignoreCase = true) }.mapNotNull { it.second.split(";").firstOrNull() diff --git a/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt b/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt index 1b2bd2a0..9f9fce7c 100644 --- a/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt +++ b/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt @@ -10,7 +10,7 @@ import org.jsoup.nodes.Element import java.net.URI open class YomoviesProvider : MainAPI() { - override var mainUrl = "https://yomovies.baby" + override var mainUrl = "https://yomovies.ltd" private var directUrl = "" override var name = "Yomovies" override val hasMainPage = true