diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index d8a2821c..8a839f56 100644 --- a/SoraStream/build.gradle.kts +++ b/SoraStream/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 79 +version = 80 cloudstream { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 96aab85f..72d4815d 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2089,7 +2089,7 @@ object SoraExtractor : SoraStream() { "cf_cache_token" to "UKsVpQqBMxB56gBfhYKbfCVkRIXMh42pk6G4DdkXXoVh7j4BjV" ) val query = getIndexQuery(title, year, season, episode) - val search = app.get("$baymoviesAPI/0:search?q=$query&page_token=&page_index=0", headers = headers) + val search = app.get("$baymoviesAPI/0:search?q=$query&page_token=&page_index=0", headers = headers).text val media = searchIndex(title, season, episode, year, search) ?: return media.apmap { file -> @@ -2129,6 +2129,26 @@ object SoraExtractor : SoraStream() { } + suspend fun invokeGammovies( + apiUrl: String, + api: String, + title: String? = null, + year: Int? = null, + season: Int? = null, + episode: Int? = null, + callback: (ExtractorLink) -> Unit, + ) { + invokeChillmovies( + apiUrl, + api, + title, + year, + season, + episode, + callback, + ) + } + suspend fun invokeChillmovies0( apiUrl: String, api: String, @@ -2169,7 +2189,7 @@ object SoraExtractor : SoraStream() { ) } - suspend fun invokeChillmovies( + private suspend fun invokeChillmovies( apiUrl: String, api: String, title: String? = null, @@ -2183,15 +2203,34 @@ object SoraExtractor : SoraStream() { """{"q":"$query","password":null,"page_token":null,"page_index":0}""".toRequestBody( RequestBodyTypes.JSON.toMediaTypeOrNull() ) - val search = app.post("${apiUrl}search", requestBody = body) + val data = mapOf( + "q" to query, + "page_token" to "", + "page_index" to "0" + ) + val search = if (api == "Gammovies") { + decodeIndexJson(app.post("${apiUrl}search", data = data).text) + } else { + app.post("${apiUrl}search", requestBody = body).text + } val media = searchIndex(title, season, episode, year, search) ?: return media.apmap { file -> val pathBody = """{"id":"${file.id ?: return@apmap null}"}""".toRequestBody( RequestBodyTypes.JSON.toMediaTypeOrNull() ) - val path = app.post("${apiUrl}id2path", requestBody = pathBody).text.let { + val pathData = mapOf( + "id" to file.id, + ) + val path = (if (api == "Gammovies") { + app.post( + "${apiUrl}id2path", data = pathData + ) + } else { + app.post("${apiUrl}id2path", requestBody = pathBody) + }).text.let { fixUrl(it, apiUrl) }.encodeUrl() + if (!app.get(path).isSuccessful) return@apmap null val size = file.size?.toDouble() ?: return@apmap null val sizeFile = "%.2f GB".format(bytesToGigaBytes(size)) val quality = diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index b9f4e152..f0205213 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -28,6 +28,7 @@ import com.hexated.SoraExtractor.invokeFDMovies import com.hexated.SoraExtractor.invokeFlixon import com.hexated.SoraExtractor.invokeFwatayako import com.hexated.SoraExtractor.invokeGMovies +import com.hexated.SoraExtractor.invokeGammovies import com.hexated.SoraExtractor.invokeKisskh import com.hexated.SoraExtractor.invokeLing import com.hexated.SoraExtractor.invokeM4uhd @@ -110,6 +111,7 @@ open class SoraStream : TmdbProvider() { const val baymoviesAPI = "https://thebayindexpublicgroupapi.zindex.eu.org" const val chillmovies0API = "https://chill.aicirou.workers.dev/0:" const val chillmovies1API = "https://chill.aicirou.workers.dev/1:" + const val gamMoviesAPI = "https://drive.gamick.workers.dev/0:" fun getType(t: String?): TvType { return when (t) { @@ -566,6 +568,17 @@ open class SoraStream : TmdbProvider() { callback ) }, + { + invokeGammovies( + gamMoviesAPI, + "Gammovies", + res.title, + res.year, + res.season, + res.episode, + callback + ) + }, ) return true diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 9d245fcd..5416e516 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -633,7 +633,7 @@ fun searchIndex( season: Int? = null, episode: Int? = null, year: Int? = null, - response: NiceResponse + response: String ): List? { val (dotSlug, spaceSlug) = getTitleSlug(title) val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) @@ -642,7 +642,7 @@ fun searchIndex( "video/mp4", "video/x-msvideo" ) - return response.parsedSafe()?.data?.files?.filter { media -> + return tryParseJson(response)?.data?.files?.filter { media -> (if (season == null) { media.name?.contains("$year") == true } else { @@ -680,6 +680,11 @@ var arrayofworkers = (.*)""".toRegex() return BaymoviesConfig(country, downloadTime, workers) } +// taken from https://github.com/821938089/cloudstream-extensions/blob/6e41697cbf816d2f57d9922d813c538e3192f708/PiousIndexProvider/src/main/kotlin/com/horis/cloudstreamplugins/PiousIndexProvider.kt#L175-L179 +fun decodeIndexJson(json: String): String { + val slug = json.reversed().substring(24) + return base64Decode(slug.substring(0, slug.length - 20)) +} fun String?.fixTitle(): String? { return this?.replace(Regex("[!%:'?,]|( &)"), "")?.replace(" ", "-")?.lowercase() ?.replace("-–-", "-")