fixed SoraVIP

This commit is contained in:
hexated 2022-11-04 22:54:25 +07:00
parent 0af97ed6b4
commit 657cd57e3c
3 changed files with 99 additions and 80 deletions

View file

@ -1,5 +1,5 @@
// use an integer for version numbers
version = 22
version = 23
cloudstream {

View file

@ -302,45 +302,30 @@ object SoraExtractor : SoraStream() {
}
suspend fun invokeSoraVIP(
id: Int? = null,
title: String? = null,
orgTitle: String? = null,
year: Int? = null,
season: Int? = null,
episode: Int? = null,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
val apiUrl = base64DecodeAPI("aQ==YXA=cC8=YXA=bC4=Y2U=ZXI=LnY=b2s=a2w=bG8=Ly8=czo=dHA=aHQ=")
val url = if(season == null) {
"$mainServerAPI/movies/$id/?_data=routes/movies/\$movieId"
"$apiUrl/search/one?title=$title&orgTitle=$orgTitle&year=$year"
} else {
"$mainServerAPI/tv-shows/$id/?_data=routes/tv-shows/\$tvId"
}
val data = app.get(url).parsedSafe<DetailVipResult>()?.detail
val title = data?.title ?: data?.name
val origTitle = data?.original_title ?: data?.original_name
val providerId = if (season == null) {
val airDate = (data?.release_date ?: data?.first_air_date)?.substringBefore("-")
app.get(
"$mainServerAPI/api/provider?title=$title&type=movie&origTitle=$origTitle&year=$airDate&_data=routes/api/provider"
)
.parsedSafe<ProvidersResult>()?.provider?.first { it.provider == "Loklok" }?.id
} else {
val airDate = data?.seasons?.first { it.season_number == season }?.air_date?.substringBefore("-")
app.get(
"$mainServerAPI/api/provider?title=$title&type=tv&origTitle=$origTitle&year=$airDate&season=$season&_data=routes/api/provider"
)
.parsedSafe<ProvidersResult>()?.provider?.first { it.provider == "Loklok" }?.id
"$apiUrl/search/one?title=$title&orgTitle=$orgTitle&year=$year&season=$season"
}
val query = if (season == null) {
"$mainServerAPI/movies/$id/watch?provider=Loklok&id=$providerId&_data=routes/movies/\$movieId.watch"
val id = app.get(url).parsedSafe<DetailVipResult>()?.data?.id
val sourcesUrl = if(season == null) {
"$apiUrl/movie/detail?id=$id"
} else {
"$mainServerAPI/tv-shows/$id/season/$season/episode/$episode?provider=Loklok&id=$providerId&_data=routes/tv-shows/\$tvId.season.\$seasonId.episode.\$episodeId"
"$apiUrl/tv/detail?id=$id&episodeId=${episode?.minus(1)}"
}
val json = app.get(
query,
headers = mapOf("User-Agent" to RandomUserAgent.getRandomUserAgent())
).parsedSafe<LoadLinks>()
val json = app.get(sourcesUrl).parsedSafe<LoadVIPLinks>()
json?.sources?.map { source ->
callback.invoke(
@ -348,10 +333,9 @@ object SoraExtractor : SoraStream() {
"${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)
"$apiUrl/",
source.quality ?: Qualities.Unknown.value,
isM3u8 = source.url.contains(".m3u8"),
)
)
}
@ -359,7 +343,7 @@ object SoraExtractor : SoraStream() {
json?.subtitles?.map { sub ->
subtitleCallback.invoke(
SubtitleFile(
getLanguage(sub.lang.toString()),
getLanguage(sub.language.toString()),
sub.url ?: return@map null
)
)

View file

@ -35,6 +35,7 @@ open class SoraStream : TmdbProvider() {
override val hasDownloadSupport = true
override val instantLinkLoading = true
override val useMetaLoadResponse = true
override val hasChromecastSupport = true
override val supportedTypes = setOf(
TvType.Movie,
TvType.TvSeries,
@ -83,14 +84,15 @@ open class SoraStream : TmdbProvider() {
}
}
private fun base64DecodeAPI(api: String): String {
fun base64DecodeAPI(api: String): String {
return api.chunked(4).map { base64Decode(it) }.reversed().joinToString("")
}
}
private suspend fun checkMainServer() {
val check = app.get(mainServerAPI)
mainServerAPI = if(check.isSuccessful) {
mainServerAPI = if (check.isSuccessful) {
mainServerAPI
} else {
base64DecodeAPI("cHA=LmE=ZWw=cmM=dmU=Ny4=bjQ=cmE=aHQ=YW4=a2g=ZS0=dmk=bW8=eC0=bWk=cmU=Ly8=czo=dHA=aHQ=")
@ -128,7 +130,7 @@ open class SoraStream : TmdbProvider() {
page: Int,
request: MainPageRequest
): HomePageResponse {
checkMainServer()
// checkMainServer()
val type = if (request.data.contains("/movie")) "movie" else "tv"
val home = app.get(request.data + page)
.parsedSafe<Results>()?.results
@ -168,12 +170,12 @@ open class SoraStream : TmdbProvider() {
).parsedSafe<Results>()?.results?.mapNotNull { media ->
media.toSearchResponse()
}
if(mainResponse?.isNotEmpty() == true) searchResponse.addAll(mainResponse)
if (mainResponse?.isNotEmpty() == true) searchResponse.addAll(mainResponse)
val animeResponse =
app.get("$mainServerAPI/search/anime/$query?_data=routes/search/anime/\$animeKeyword")
.parsedSafe<SearchAnime>()?.searchResults?.results?.mapNotNull { anime -> anime.toSearchResponse() }
if(animeResponse?.isNotEmpty() == true) searchResponse.addAll(animeResponse)
// val animeResponse =
// app.get("$mainServerAPI/search/anime/$query?_data=routes/search/anime/\$animeKeyword")
// .parsedSafe<SearchAnime>()?.searchResults?.results?.mapNotNull { anime -> anime.toSearchResponse() }
// if (animeResponse?.isNotEmpty() == true) searchResponse.addAll(animeResponse)
return searchResponse
}
@ -222,9 +224,11 @@ open class SoraStream : TmdbProvider() {
.parsedSafe<Detail>()?.pageProps
?: throw ErrorLoadingException("Invalid Json Response")
val res = responses.result ?: return null
val title = res.title ?: res.name ?: res.originalTitle ?: res.originalName ?: return null
val year = (res.releaseDate ?: res.firstAirDate)?.split("-")?.first()?.toIntOrNull()
val title = res.title ?: res.name ?: return null
val orgTitle = res.originalTitle ?: res.originalName ?: return null
val type = getType(data.type)
val year = (res.releaseDate ?: res.firstAirDate)?.split("-")?.first()?.toIntOrNull()
val actors = responses.cast?.mapNotNull { cast ->
ActorData(
Actor(
@ -254,7 +258,8 @@ open class SoraStream : TmdbProvider() {
eps.seasonNumber,
eps.episodeNumber,
title = title,
year = year,
year = season.airDate?.split("-")?.first()?.toIntOrNull(),
orgTitle = orgTitle,
).toJson(),
name = eps.name,
season = eps.seasonNumber,
@ -293,6 +298,7 @@ open class SoraStream : TmdbProvider() {
data.type,
title = title,
year = year,
orgTitle = orgTitle,
).toJson(),
) {
this.posterUrl = getOriImageUrl(res.backdropPath)
@ -327,7 +333,15 @@ open class SoraStream : TmdbProvider() {
argamap(
{
invokeSoraVIP(res.id, res.season, res.episode, subtitleCallback, callback)
invokeSoraVIP(
res.title,
res.orgTitle,
res.year,
res.season,
res.episode,
subtitleCallback,
callback
)
},
{
val json = app.get(
@ -336,9 +350,6 @@ open class SoraStream : TmdbProvider() {
headers = mapOf("User-Agent" to getRandomUserAgent())
).parsedSafe<LoadLinks>()
if (json?.sources.isNullOrEmpty()) {
invokeLocalSources(referer, subtitleCallback, callback)
} else {
json?.sources?.map { source ->
callback.invoke(
ExtractorLink(
@ -355,12 +366,11 @@ open class SoraStream : TmdbProvider() {
json?.subtitles?.map { sub ->
subtitleCallback.invoke(
SubtitleFile(
sub.lang.toString(),
getLanguage(sub.lang.toString()),
sub.url ?: return@map null
)
)
}
}
},
{
invokeTwoEmbed(res.id, res.season, res.episode, subtitleCallback, callback)
@ -397,7 +407,11 @@ open class SoraStream : TmdbProvider() {
// )
// },
{
if (res.aniId?.isNotEmpty() == true) invokeGogo(res.aniId, res.animeId, callback)
if (res.aniId?.isNotEmpty() == true) invokeGogo(
res.aniId,
res.animeId,
callback
)
},
{
invokeHDMovieBox(res.title, res.season, res.episode, callback)
@ -406,17 +420,31 @@ open class SoraStream : TmdbProvider() {
invokeSeries9(res.title, res.season, res.episode, subtitleCallback, callback)
},
{
invokeIdlix(res.title, res.year, res.season, res.episode, subtitleCallback, callback)
invokeIdlix(
res.title,
res.year,
res.season,
res.episode,
subtitleCallback,
callback
)
},
{
invokeNoverse(res.title, res.season, res.episode, callback)
},
{
invokeUniqueStream(res.title, res.year, res.season, res.episode, subtitleCallback, callback)
invokeUniqueStream(
res.title,
res.year,
res.season,
res.episode,
subtitleCallback,
callback
)
},
{
invokeFilmxy(res.imdbId, res.season, res.episode, subtitleCallback, callback)
}
},
)
return true
@ -432,6 +460,7 @@ open class SoraStream : TmdbProvider() {
val animeId: String? = null,
val title: String? = null,
val year: Int? = null,
val orgTitle: String? = null,
)
data class Data(
@ -444,6 +473,7 @@ open class SoraStream : TmdbProvider() {
data class Subtitles(
@JsonProperty("url") val url: String? = null,
@JsonProperty("lang") val lang: String? = null,
@JsonProperty("language") val language: String? = null,
)
data class Sources(
@ -457,6 +487,16 @@ open class SoraStream : TmdbProvider() {
@JsonProperty("subtitles") val subtitles: ArrayList<Subtitles>? = arrayListOf(),
)
data class SourcesVIP(
@JsonProperty("url") val url: String? = null,
@JsonProperty("quality") val quality: Int? = null,
)
data class LoadVIPLinks(
@JsonProperty("sources") val sources: ArrayList<SourcesVIP>? = arrayListOf(),
@JsonProperty("subtitles") val subtitles: ArrayList<Subtitles>? = arrayListOf(),
)
data class Results(
@JsonProperty("results") val results: ArrayList<Media>? = arrayListOf(),
)
@ -479,6 +519,7 @@ open class SoraStream : TmdbProvider() {
@JsonProperty("id") val id: Int? = null,
@JsonProperty("name") val name: String? = null,
@JsonProperty("season_number") val seasonNumber: Int? = null,
@JsonProperty("air_date") val airDate: String? = null,
)
data class Cast(
@ -609,18 +650,12 @@ open class SoraStream : TmdbProvider() {
@JsonProperty("season_number") val season_number: Int? = 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,
@JsonProperty("seasons") val seasons: ArrayList<SeasonsVip>? = arrayListOf(),
data class DataVip(
@JsonProperty("id") val id: String? = null,
)
data class DetailVipResult(
@JsonProperty("detail") val detail: DetailVip? = null,
@JsonProperty("data") val data: DataVip? = null,
)
data class Providers(