diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 0e8ea54c..c0594075 100644 --- a/SoraStream/build.gradle.kts +++ b/SoraStream/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 9 +version = 10 cloudstream { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index ba53108b..9af5a109 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -262,15 +262,69 @@ object SoraExtractor : SoraStream() { } } -// suspend fun invokeOpenvids( -// id: Int? = null, -// season: Int? = null, -// episode: Int? = null, -// subtitleCallback: (SubtitleFile) -> Unit, -// callback: (ExtractorLink) -> Unit -// ) { -// -// } + suspend fun invokeSoraVIP( + id: Int? = null, + season: Int? = null, + episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val providerId = if (season == null) { + val url = "$mainServerAPI/movies/$id/?_data=routes/movies/\$movieId" + val data = app.get(url).parsedSafe()?.detail + app.get( + "$mainServerAPI/api/provider?title=${data?.title ?: data?.name}&type=movie&origTitle=${data?.original_title ?: data?.original_name}&year=${ + (data?.release_date ?: data?.first_air_date)?.substringBefore("-") + }&_data=routes/api/provider" + ) + .parsedSafe()?.provider?.first { it.provider == "Loklok" }?.id + + } else { + val url = "$mainServerAPI/tv-shows/$id/?_data=routes/tv-shows/\$tvId" + val data = app.get(url).parsedSafe()?.detail + app.get( + "$mainServerAPI/api/provider?title=${data?.title ?: data?.name}&type=tv&origTitle=${data?.original_title ?: data?.original_name}&year=${ + (data?.release_date ?: data?.first_air_date)?.substringBefore("-") + }&season=$season&_data=routes/api/provider" + ) + .parsedSafe()?.provider?.first { it.provider == "Loklok" }?.id + + } + + val query = if (season == null) { + "$mainServerAPI/movies/$id/watch?provider=Loklok&id=$providerId&_data=routes/movies/\$movieId.watch" + } else { + "$mainServerAPI/tv-shows/$id/season/$season/episode/$episode?provider=Loklok&id=$providerId&_data=routes/tv-shows/\$tvId.season.\$seasonId.episode.\$episodeId" + } + + val json = app.get( + query, + headers = mapOf("User-Agent" to RandomUserAgent.getRandomUserAgent()) + ).parsedSafe() + + json?.sources?.map { source -> + callback.invoke( + ExtractorLink( + "${this.name} (VIP)", + "${this.name} (VIP)", + source.url ?: return@map null, + "$mainServerAPI/", + source.quality?.toIntOrNull() ?: Qualities.Unknown.value, + isM3u8 = source.isM3U8, + headers = mapOf("Origin" to mainServerAPI) + ) + ) + } + + json?.subtitles?.map { sub -> + subtitleCallback.invoke( + SubtitleFile( + sub.lang.toString(), + sub.url ?: return@map null + ) + ) + } + } suspend fun invokeGogo( aniId: String? = null, @@ -380,12 +434,3 @@ private data class MovieHabRes( @JsonProperty("data") val data: MovieHabData? = null, ) -private data class Sources( - @JsonProperty("url") val url: String? = null, - @JsonProperty("quality") val quality: String? = null, - @JsonProperty("isM3U8") val isM3U8: Boolean = true, -) - -private data class LoadLinks( - @JsonProperty("sources") val sources: ArrayList? = arrayListOf(), -) \ 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 acdfd3ab..93bf72df 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -1,5 +1,6 @@ package com.hexated +import android.util.Log import com.fasterxml.jackson.annotation.JsonProperty import com.hexated.RandomUserAgent.getRandomUserAgent import com.hexated.SoraExtractor.invoke123Movie @@ -8,12 +9,14 @@ import com.hexated.SoraExtractor.invokeGogo import com.hexated.SoraExtractor.invokeLocalSources import com.hexated.SoraExtractor.invokeMovieHab import com.hexated.SoraExtractor.invokeOlgply +import com.hexated.SoraExtractor.invokeSoraVIP import com.hexated.SoraExtractor.invokeTwoEmbed import com.hexated.SoraExtractor.invokeVidSrc import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.metaproviders.TmdbProvider +import com.lagradost.cloudstream3.mvvm.safeApiCall import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.ExtractorLink @@ -26,7 +29,6 @@ open class SoraStream : TmdbProvider() { override val hasDownloadSupport = true override val instantLinkLoading = true override val useMetaLoadResponse = true - override val hasQuickSearch = true override val supportedTypes = setOf( TvType.Movie, TvType.TvSeries, @@ -121,8 +123,6 @@ open class SoraStream : TmdbProvider() { } } - override suspend fun quickSearch(query: String) = search(query) - override suspend fun search(query: String): List { val searchResponse = mutableListOf() @@ -286,16 +286,10 @@ open class SoraStream : TmdbProvider() { headers = mapOf("User-Agent" to getRandomUserAgent()) ).parsedSafe() - json?.subtitles?.map { sub -> - subtitleCallback.invoke( - SubtitleFile( - sub.lang.toString(), - sub.url ?: return@map null - ) - ) - } - argamap( + { + invokeSoraVIP(res.id, res.season, res.episode, subtitleCallback, callback) + }, { if (json?.sources.isNullOrEmpty()) { invokeLocalSources(referer, subtitleCallback, callback) @@ -313,6 +307,14 @@ open class SoraStream : TmdbProvider() { ) ) } + json?.subtitles?.map { sub -> + subtitleCallback.invoke( + SubtitleFile( + sub.lang.toString(), + sub.url ?: return@map null + ) + ) + } } }, { @@ -518,4 +520,26 @@ open class SoraStream : TmdbProvider() { @JsonProperty("detail") val detail: DetailAnime? = null, ) + data class DetailVip( + @JsonProperty("title") val title: String? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("original_title") val original_title: String? = null, + @JsonProperty("original_name") val original_name: String? = null, + @JsonProperty("release_date") val release_date: String? = null, + @JsonProperty("first_air_date") val first_air_date: String? = null, + ) + + data class DetailVipResult( + @JsonProperty("detail") val detail: DetailVip? = null, + ) + + data class Providers( + @JsonProperty("id") val id: String? = null, + @JsonProperty("provider") val provider: String? = null, + ) + + data class ProvidersResult( + @JsonProperty("provider") val provider: ArrayList? = arrayListOf(), + ) + }