From e8110fab6272bc238d7ec1669c0e7c3345c72187 Mon Sep 17 00:00:00 2001 From: alex Date: Mon, 8 Jan 2024 02:17:40 +0700 Subject: [PATCH] fix --- .../kotlin/com/hexated/KuramanimeProvider.kt | 234 ++--- NeonimeProvider/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/SoraStream.kt | 839 ++++++++++++------ .../main/kotlin/com/hexated/SoraStreamLite.kt | 392 +++++--- 4 files changed, 971 insertions(+), 496 deletions(-) diff --git a/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt b/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt index 82d488e4..83bdcfb5 100644 --- a/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt +++ b/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt @@ -20,13 +20,14 @@ class KuramanimeProvider : MainAPI() { override val hasMainPage = true override var lang = "id" override val hasDownloadSupport = true - private var params: AuthParams? = null - private var headers: Map = mapOf() - private var cookies: Map = mapOf() + private var miscUrl: String? = null + private var headers: Map = mapOf() + private var cookies: Map = mapOf() + private var mixPage: Pair? = null override val supportedTypes = setOf( - TvType.Anime, - TvType.AnimeMovie, - TvType.OVA + TvType.Anime, + TvType.AnimeMovie, + TvType.OVA ) companion object { @@ -46,15 +47,15 @@ class KuramanimeProvider : MainAPI() { } override val mainPage = mainPageOf( - "$mainUrl/anime/ongoing?order_by=updated&page=" to "Sedang Tayang", - "$mainUrl/anime/finished?order_by=updated&page=" to "Selesai Tayang", - "$mainUrl/properties/season/summer-2022?order_by=most_viewed&page=" to "Dilihat Terbanyak Musim Ini", - "$mainUrl/anime/movie?order_by=updated&page=" to "Film Layar Lebar", + "$mainUrl/anime/ongoing?order_by=updated&page=" to "Sedang Tayang", + "$mainUrl/anime/finished?order_by=updated&page=" to "Selesai Tayang", + "$mainUrl/properties/season/summer-2022?order_by=most_viewed&page=" to "Dilihat Terbanyak Musim Ini", + "$mainUrl/anime/movie?order_by=updated&page=" to "Film Layar Lebar", ) override suspend fun getMainPage( - page: Int, - request: MainPageRequest + page: Int, + request: MainPageRequest ): HomePageResponse { val document = app.get(request.data + page).document @@ -102,35 +103,40 @@ class KuramanimeProvider : MainAPI() { val title = document.selectFirst(".anime__details__title > h3")!!.text().trim() val poster = document.selectFirst(".anime__details__pic")?.attr("data-setbg") - val tags = document.select("div.anime__details__widget > div > div:nth-child(2) > ul > li:nth-child(1)") - .text().trim().replace("Genre: ", "").split(", ") + val tags = + document.select("div.anime__details__widget > div > div:nth-child(2) > ul > li:nth-child(1)") + .text().trim().replace("Genre: ", "").split(", ") val year = Regex("\\D").replace( - document.select("div.anime__details__widget > div > div:nth-child(1) > ul > li:nth-child(5)") - .text().trim().replace("Musim: ", ""), "" + document.select("div.anime__details__widget > div > div:nth-child(1) > ul > li:nth-child(5)") + .text().trim().replace("Musim: ", ""), "" ).toIntOrNull() val status = getStatus( - document.select("div.anime__details__widget > div > div:nth-child(1) > ul > li:nth-child(3)") - .text().trim().replace("Status: ", "") + document.select("div.anime__details__widget > div > div:nth-child(1) > ul > li:nth-child(3)") + .text().trim().replace("Status: ", "") ) val description = document.select(".anime__details__text > p").text().trim() val episodes = mutableListOf() - for (i in 1..6) { + for (i in 1..10) { val doc = app.get("$url?page=$i").document - val eps = Jsoup.parse(doc.select("#episodeLists").attr("data-content")).select("a.btn.btn-sm.btn-danger") - .mapNotNull { - val name = it.text().trim() - val episode = Regex("(\\d+[.,]?\\d*)").find(name)?.groupValues?.getOrNull(0) - ?.toIntOrNull() - val link = it.attr("href") - Episode(link, episode = episode) - } - if(eps.isEmpty()) break else episodes.addAll(eps) + val eps = Jsoup.parse(doc.select("#episodeLists").attr("data-content")) + .select("a.btn.btn-sm.btn-danger") + .mapNotNull { + val name = it.text().trim() + val episode = Regex("(\\d+[.,]?\\d*)").find(name)?.groupValues?.getOrNull(0) + ?.toIntOrNull() + val link = it.attr("href") + Episode(link, episode = episode) + } + if (eps.isEmpty()) break else episodes.addAll(eps) } - val type = getType(document.selectFirst("div.col-lg-6.col-md-6 ul li:contains(Tipe:) a")?.text()?.lowercase() ?: "tv", episodes.size) + val type = getType( + document.selectFirst("div.col-lg-6.col-md-6 ul li:contains(Tipe:) a")?.text() + ?.lowercase() ?: "tv", episodes.size + ) val recommendations = document.select("div#randomList > a").mapNotNull { val epHref = it.attr("href") val epTitle = it.select("h5.sidebar-title-h5.px-2.py-2").text() @@ -141,7 +147,7 @@ class KuramanimeProvider : MainAPI() { } } - val tracker = APIHolder.getTracker(listOf(title),TrackerType.getTypes(type),year,true) + val tracker = APIHolder.getTracker(listOf(title), TrackerType.getTypes(type), year, true) return newAnimeLoadResponse(title, url, type) { engName = title @@ -160,111 +166,131 @@ class KuramanimeProvider : MainAPI() { } private suspend fun invokeLocalSource( - url: String, - server: String, - ref: String, - callback: (ExtractorLink) -> Unit + url: String, + server: String, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit ) { val document = app.get( - url, - referer = ref, - headers = headers, - cookies = cookies + url, + headers = headers, + cookies = cookies ).document document.select("video#player > source").map { val link = fixUrl(it.attr("src")) val quality = it.attr("size").toIntOrNull() callback.invoke( - ExtractorLink( - fixTitle(server), - fixTitle(server), - link, - referer = "", - quality = quality ?: Qualities.Unknown.value, - headers = mapOf( - "Accept" to "video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5", - "Range" to "bytes=0-", - "Sec-Fetch-Dest" to "video", - "Sec-Fetch-Mode" to "no-cors", - ), - ) + ExtractorLink( + fixTitle(server), + fixTitle(server), + link, + referer = "", + quality = quality ?: Qualities.Unknown.value, + headers = mapOf( + "Accept" to "video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5", + "Range" to "bytes=0-", + "Sec-Fetch-Dest" to "video", + "Sec-Fetch-Mode" to "no-cors", + ), + ) ) } + if(server=="kuramadrive") { + document.select("div#animeDownloadLink a").apmap { + loadExtractor(it.attr("href"), "$mainUrl/", subtitleCallback, callback) + } + } } override suspend fun loadLinks( - data: String, - isCasting: Boolean, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit ): Boolean { val req = app.get(data) val res = req.document + cookies = req.cookies - argamap( - { - val auth = getAuth(data) - headers = auth.authHeader?.associate { it.first to it.second }?.filter { it.key != "Cookie" }!! - cookies = req.cookies - res.select("select#changeServer option").apmap { source -> - val server = source.attr("value") - val query = auth.serverUrl?.queryParameterNames?.map { it } ?: return@apmap - val link = "$data?${query[0]}=${getMisc(auth.authUrl)}&${query[1]}=$server" - if (server.contains(Regex("(?i)kuramadrive|archive"))) { - invokeLocalSource(link, server, data, callback) - } else { - app.get( - link, - referer = data, - headers = headers, - cookies = cookies - ).document.select("div.iframe-container iframe").attr("src").let { videoUrl -> - loadExtractor(fixUrl(videoUrl), "$mainUrl/", subtitleCallback, callback) - } - } - } - }, - { - res.select("div#animeDownloadLink a").apmap { - loadExtractor(it.attr("href"), "$mainUrl/", subtitleCallback, callback) + val bpjs = res.selectFirst("div.col-lg-12.mt-3")?.attr("data-bpjs") ?: return false + + val auth = getMiscUrl(data) + val misc = getMisc(auth) + val mixPage = getMixPage(bpjs) + + res.select("select#changeServer option").apmap { source -> + val server = source.attr("value") + val link = "$data?${mixPage.first}=$misc&${mixPage.second}=$server" + if (server.contains(Regex("(?i)kuramadrive|archive"))) { + invokeLocalSource(link, server, subtitleCallback, callback) + } else { + app.get( + link, + referer = data, + headers = headers, + cookies = cookies + ).document.select("div.iframe-container iframe").attr("src").let { videoUrl -> + loadExtractor(fixUrl(videoUrl), "$mainUrl/", subtitleCallback, callback) } } - ) + } + return true } - private suspend fun fetchAuth(url: String) : AuthParams { - val regex = Regex("""$mainUrl/\S+""") + private suspend fun fetchMiscUrl(url: String): String { + val regex = Regex("""$mainUrl/.*""") val found = WebViewResolver( - Regex("""$url(?!\?page=)\?"""), - additionalUrls = listOf(regex) + Regex("""$mainUrl/assets/\S+.jpg"""), + additionalUrls = listOf(regex), ).resolveUsingWebView( - requestCreator( - "GET", url - ) - ) - val addition = found.second.findLast { it.headers["X-Requested-With"] == "XMLHttpRequest" } - return AuthParams(found.first?.url, addition?.url.toString(), addition?.headers) + requestCreator( + "GET", url + , cookies = cookies, referer = "$mainUrl/", headers = mapOf( + "Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", + "Accept-Language" to "en-US,en;q=0.5", + ) + ) + ).first + headers = found?.headers?.associate { it.first to it.second } ?: mapOf() + return found?.url.toString() } - private suspend fun getAuth(url: String) = params ?: fetchAuth(url).also { params = it } + private suspend fun getMiscUrl(url: String) = miscUrl ?: fetchMiscUrl(url).also { miscUrl = it } + + private suspend fun fetchMixPage(bpjs: String): Pair { + val env = app.get("$mainUrl/assets/js/$bpjs.js").text + val MIX_PAGE_TOKEN_KEY = env.substringAfter("MIX_PAGE_TOKEN_KEY: '").substringBefore("',") + val MIX_STREAM_SERVER_KEY = env.substringAfter("MIX_STREAM_SERVER_KEY: '").substringBefore("',") + return MIX_PAGE_TOKEN_KEY to MIX_STREAM_SERVER_KEY + } + + private suspend fun getMixPage(bpjs: String) = mixPage ?: fetchMixPage(bpjs).also { mixPage = it } private suspend fun getMisc(url: String?): String { - val misc = app.get( - "$url", - headers = headers, - cookies = cookies - ) - cookies = misc.cookies - return misc.parsed() + val res = app.get("$url", headers = headers) + cookies = res.cookies + return res.text.removeBloat() } - data class AuthParams ( - val serverUrl: HttpUrl?, - val authUrl: String?, - val authHeader: Headers?, + private fun getRequestId(length: Int = 6): String { + val allowedChars = ('a'..'z') + ('0'..'9') + return (1..length) + .map { allowedChars.random() } + .joinToString("") + } + + private fun String.removeBloat() : String { + return this.replace("\"", "") + } + + data class AuthParams( + val header: Map?, + val params: List?, + val misc: String, + val miscUrl: String?, ) } \ No newline at end of file diff --git a/NeonimeProvider/build.gradle.kts b/NeonimeProvider/build.gradle.kts index bfa7a96c..90714e5d 100644 --- a/NeonimeProvider/build.gradle.kts +++ b/NeonimeProvider/build.gradle.kts @@ -24,5 +24,5 @@ cloudstream { "OVA", ) - iconUrl = "https://www.google.com/s2/favicons?domain=neonime.watch&sz=%size%" + iconUrl = "https://www.google.com/s2/favicons?domain=neonime.ink&sz=%size%" } \ 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 740cc4de..b9b4b147 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -63,9 +63,9 @@ open class SoraStream : TmdbProvider() { override val useMetaLoadResponse = true override val hasQuickSearch = true override val supportedTypes = setOf( - TvType.Movie, - TvType.TvSeries, - TvType.Anime, + TvType.Movie, + TvType.TvSeries, + TvType.Anime, ) val wpredisInterceptor by lazy { CloudflareKiller() } @@ -147,26 +147,26 @@ open class SoraStream : TmdbProvider() { } override val mainPage = mainPageOf( - "$tmdbAPI/trending/all/day?api_key=$apiKey®ion=US" to "Trending", - "$tmdbAPI/movie/popular?api_key=$apiKey®ion=US" to "Popular Movies", - "$tmdbAPI/tv/popular?api_key=$apiKey®ion=US&with_original_language=en" to "Popular TV Shows", - "$tmdbAPI/tv/airing_today?api_key=$apiKey®ion=US&with_original_language=en" to "Airing Today TV Shows", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=213" to "Netflix", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=1024" to "Amazon", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=2739" to "Disney+", - "$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/discover/tv?api_key=$apiKey&with_networks=3353" to "Peacock", - "$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", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_original_language=ko" to "Korean Shows", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_keywords=210024|222243&sort_by=popularity.desc&air_date.lte=${getDate().today}&air_date.gte=${getDate().today}" to "Airing Today Anime", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_keywords=210024|222243&sort_by=popularity.desc&air_date.lte=${getDate().nextWeek}&air_date.gte=${getDate().today}" to "On The Air Anime", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_keywords=210024|222243" to "Anime", - "$tmdbAPI/discover/movie?api_key=$apiKey&with_keywords=210024|222243" to "Anime Movies", + "$tmdbAPI/trending/all/day?api_key=$apiKey®ion=US" to "Trending", + "$tmdbAPI/movie/popular?api_key=$apiKey®ion=US" to "Popular Movies", + "$tmdbAPI/tv/popular?api_key=$apiKey®ion=US&with_original_language=en" to "Popular TV Shows", + "$tmdbAPI/tv/airing_today?api_key=$apiKey®ion=US&with_original_language=en" to "Airing Today TV Shows", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=213" to "Netflix", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=1024" to "Amazon", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=2739" to "Disney+", + "$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/discover/tv?api_key=$apiKey&with_networks=3353" to "Peacock", + "$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", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_original_language=ko" to "Korean Shows", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_keywords=210024|222243&sort_by=popularity.desc&air_date.lte=${getDate().today}&air_date.gte=${getDate().today}" to "Airing Today Anime", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_keywords=210024|222243&sort_by=popularity.desc&air_date.lte=${getDate().nextWeek}&air_date.gte=${getDate().today}" to "On The Air Anime", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_keywords=210024|222243" to "Anime", + "$tmdbAPI/discover/movie?api_key=$apiKey&with_keywords=210024|222243" to "Anime Movies", ) private fun getImageUrl(link: String?): String? { @@ -180,9 +180,11 @@ open class SoraStream : TmdbProvider() { } override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse { - val adultQuery = if (settingsForProvider.enableAdult) "" else "&without_keywords=190370|13059|226161|195669" + val adultQuery = + if (settingsForProvider.enableAdult) "" else "&without_keywords=190370|13059|226161|195669" val type = if (request.data.contains("/movie")) "movie" else "tv" - val home = app.get("${request.data}$adultQuery&page=$page").parsedSafe()?.results?.mapNotNull { media -> + val home = app.get("${request.data}$adultQuery&page=$page") + .parsedSafe()?.results?.mapNotNull { media -> media.toSearchResponse(type) } ?: throw ErrorLoadingException("Invalid Json reponse") return newHomePageResponse(request.name, home) @@ -190,9 +192,9 @@ open class SoraStream : TmdbProvider() { private fun Media.toSearchResponse(type: String? = null): SearchResponse? { return newMovieSearchResponse( - title ?: name ?: originalTitle ?: return null, - Data(id = id, type = mediaType ?: type).toJson(), - TvType.Movie, + title ?: name ?: originalTitle ?: return null, + Data(id = id, type = mediaType ?: type).toJson(), + TvType.Movie, ) { this.posterUrl = getImageUrl(posterPath) } @@ -201,7 +203,8 @@ open class SoraStream : TmdbProvider() { override suspend fun quickSearch(query: String): List? = search(query) override suspend fun search(query: String): List? { - return app.get("$tmdbAPI/search/multi?api_key=$apiKey&language=en-US&query=$query&page=1&include_adult=${settingsForProvider.enableAdult}").parsedSafe()?.results?.mapNotNull { media -> + return app.get("$tmdbAPI/search/multi?api_key=$apiKey&language=en-US&query=$query&page=1&include_adult=${settingsForProvider.enableAdult}") + .parsedSafe()?.results?.mapNotNull { media -> media.toSearchResponse() } } @@ -216,7 +219,7 @@ open class SoraStream : TmdbProvider() { "$tmdbAPI/tv/${data.id}?api_key=$apiKey&append_to_response=$append" } val res = app.get(resUrl).parsedSafe() - ?: throw ErrorLoadingException("Invalid Json Response") + ?: throw ErrorLoadingException("Invalid Json Response") val title = res.title ?: res.name ?: return null val poster = getOriImageUrl(res.posterPath) @@ -232,27 +235,68 @@ open class SoraStream : TmdbProvider() { val isAsian = !isAnime && (res.original_language == "zh" || res.original_language == "ko") val isBollywood = res.production_countries?.any { it.name == "India" } ?: false - val keywords = res.keywords?.results?.mapNotNull { it.name }.orEmpty().ifEmpty { res.keywords?.keywords?.mapNotNull { it.name } } + val keywords = res.keywords?.results?.mapNotNull { it.name }.orEmpty() + .ifEmpty { res.keywords?.keywords?.mapNotNull { it.name } } val actors = res.credits?.cast?.mapNotNull { cast -> - ActorData(Actor(cast.name ?: cast.originalName - ?: return@mapNotNull null, getImageUrl(cast.profilePath)), roleString = cast.character) + ActorData( + Actor( + cast.name ?: cast.originalName + ?: return@mapNotNull null, getImageUrl(cast.profilePath) + ), roleString = cast.character + ) } ?: return null - val recommendations = res.recommendations?.results?.mapNotNull { media -> media.toSearchResponse() } + val recommendations = + res.recommendations?.results?.mapNotNull { media -> media.toSearchResponse() } - val trailer = res.videos?.results?.map { "https://www.youtube.com/watch?v=${it.key}" }?.randomOrNull() + val trailer = + res.videos?.results?.map { "https://www.youtube.com/watch?v=${it.key}" }?.randomOrNull() return if (type == TvType.TvSeries) { val lastSeason = res.last_episode_to_air?.season_number val episodes = res.seasons?.mapNotNull { season -> - app.get("$tmdbAPI/${data.type}/${data.id}/season/${season.seasonNumber}?api_key=$apiKey").parsedSafe()?.episodes?.map { eps -> - Episode(LinkData(data.id, res.external_ids?.imdb_id, res.external_ids?.tvdb_id, data.type, eps.seasonNumber, eps.episodeNumber, title = title, year = season.airDate?.split("-")?.first()?.toIntOrNull(), orgTitle = orgTitle, isAnime = isAnime, airedYear = year, lastSeason = lastSeason, epsTitle = eps.name, jpTitle = res.alternative_titles?.results?.find { it.iso_3166_1 == "JP" }?.title, date = season.airDate, airedDate = res.releaseDate - ?: res.firstAirDate, isAsian = isAsian, isBollywood = isBollywood, isCartoon = isCartoon).toJson(), name = eps.name + if (isUpcoming(eps.airDate)) " - [UPCOMING]" else "", season = eps.seasonNumber, episode = eps.episodeNumber, posterUrl = getImageUrl(eps.stillPath), rating = eps.voteAverage?.times(10)?.roundToInt(), description = eps.overview).apply { + app.get("$tmdbAPI/${data.type}/${data.id}/season/${season.seasonNumber}?api_key=$apiKey") + .parsedSafe()?.episodes?.map { eps -> + Episode( + LinkData( + data.id, + res.external_ids?.imdb_id, + res.external_ids?.tvdb_id, + data.type, + eps.seasonNumber, + eps.episodeNumber, + title = title, + year = season.airDate?.split("-")?.first()?.toIntOrNull(), + orgTitle = orgTitle, + isAnime = isAnime, + airedYear = year, + lastSeason = lastSeason, + epsTitle = eps.name, + jpTitle = res.alternative_titles?.results?.find { it.iso_3166_1 == "JP" }?.title, + date = season.airDate, + airedDate = res.releaseDate + ?: res.firstAirDate, + isAsian = isAsian, + isBollywood = isBollywood, + isCartoon = isCartoon + ).toJson(), + name = eps.name + if (isUpcoming(eps.airDate)) " - [UPCOMING]" else "", + season = eps.seasonNumber, + episode = eps.episodeNumber, + posterUrl = getImageUrl(eps.stillPath), + rating = eps.voteAverage?.times(10)?.roundToInt(), + description = eps.overview + ).apply { this.addDate(eps.airDate) } } }?.flatten() ?: listOf() - newTvSeriesLoadResponse(title, url, if (isAnime) TvType.Anime else TvType.TvSeries, episodes) { + newTvSeriesLoadResponse( + title, + url, + if (isAnime) TvType.Anime else TvType.TvSeries, + episodes + ) { this.posterUrl = poster this.backgroundPosterUrl = bgPoster this.year = year @@ -269,11 +313,24 @@ open class SoraStream : TmdbProvider() { } } else { newMovieLoadResponse( - title, - url, - TvType.Movie, - LinkData(data.id, res.external_ids?.imdb_id, res.external_ids?.tvdb_id, data.type, title = title, year = year, orgTitle = orgTitle, isAnime = isAnime, jpTitle = res.alternative_titles?.results?.find { it.iso_3166_1 == "JP" }?.title, airedDate = res.releaseDate - ?: res.firstAirDate, isAsian = isAsian, isBollywood = isBollywood).toJson(), + title, + url, + TvType.Movie, + LinkData( + data.id, + res.external_ids?.imdb_id, + res.external_ids?.tvdb_id, + data.type, + title = title, + year = year, + orgTitle = orgTitle, + isAnime = isAnime, + jpTitle = res.alternative_titles?.results?.find { it.iso_3166_1 == "JP" }?.title, + airedDate = res.releaseDate + ?: res.firstAirDate, + isAsian = isAsian, + isBollywood = isBollywood + ).toJson(), ) { this.posterUrl = poster this.backgroundPosterUrl = bgPoster @@ -293,315 +350,537 @@ open class SoraStream : TmdbProvider() { } } - override suspend fun loadLinks(data: String, isCasting: Boolean, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit): Boolean { + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { val res = parseJson(data) argamap( - { - invokeDumpStream(res.title, res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - invokeGoku(res.title, res.year, res.season, res.lastSeason, res.episode, subtitleCallback, callback) - }, - { - invokeVidSrc(res.id, res.season, res.episode, callback) - }, - { - invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeAoneroom(res.title, res.airedYear - ?: res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (res.isAnime) invokeAnimes(res.title, res.epsTitle, res.date, res.airedDate, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeDreamfilm(res.title, res.season, res.episode, subtitleCallback, callback) - }, + { + invokeDumpStream( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + invokeGoku( + res.title, + res.year, + res.season, + res.lastSeason, + res.episode, + subtitleCallback, + callback + ) + }, + { + invokeVidSrc(res.id, res.season, res.episode, callback) + }, + { + invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeAoneroom( + res.title, res.airedYear + ?: res.year, res.season, res.episode, subtitleCallback, callback + ) + }, + { + if (res.isAnime) invokeAnimes( + res.title, + res.epsTitle, + res.date, + res.airedDate, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeDreamfilm( + res.title, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, // { // invokeNoverse(res.title, res.season, res.episode, callback) // }, - { - if (!res.isAnime) invokeFilmxy(res.imdbId, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime && res.isCartoon) invokeKimcartoon(res.title, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime && res.isCartoon) invokeWatchCartoon(res.title, res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeVidsrcto(res.imdbId, res.season, res.episode, subtitleCallback, callback) - }, - { - if (res.isAsian || res.isAnime) invokeKisskh(res.title, res.season, res.episode, res.isAnime, res.lastSeason, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeOmovies(res.title, res.year, res.season, res.episode, callback) - }, - { - if (!res.isAnime) invokeLing(res.title, res.airedYear - ?: res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeUhdmovies(res.title, res.year, res.season, res.episode, callback) - }, - { - if (!res.isAnime) invokeGMovies(res.title, res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeFDMovies(res.title, res.season, res.episode, callback) - }, - { - if (!res.isAnime) invokeM4uhd(res.title, res.airedYear - ?: res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeTvMovies(res.title, res.season, res.episode, callback) - }, - { - if (!res.isAnime) invokeMoviezAdd(moviezAddAPI, "MoviezAdd", res.title, res.year, res.season, res.episode, callback) - }, - { - if (!res.isAnime && res.isBollywood) invokeBollyMaza(bollyMazaAPI, "BollyMaza", res.title, res.year, res.season, res.episode, callback) - }, - { - if (!res.isAnime) invokeRStream(res.id, res.season, res.episode, callback) - }, - { - if (!res.isAnime) invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback) - }, - { - if (!res.isAnime) invokeSmashyStream(res.imdbId, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeWatchsomuch(res.imdbId, res.season, res.episode, subtitleCallback) - }, - { - if (!res.isAnime) invokeNinetv(res.id, res.season, res.episode, subtitleCallback, callback) - }, - { - invokeDahmerMovies(res.title, res.year, res.season, res.episode, callback) - }, - { - invokeCinemaTv(res.imdbId, res.title, res.airedYear - ?: res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeNowTv(res.id, res.imdbId, res.season, res.episode, callback) - }, - { - if (!res.isAnime && res.season == null) invokeRidomovies(res.id, res.imdbId, callback) - }, - { - if (!res.isAnime) invokeAllMovieland(res.imdbId, res.season, res.episode, callback) - }, - { - if (!res.isAnime) invokeEmovies(res.title, res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeVegamovies(res.title, res.year, res.season, res.lastSeason, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime && res.isBollywood) invokeDotmovies(res.title, res.year, res.season, res.lastSeason, res.episode, subtitleCallback, callback) - }, - { - if (res.isBollywood) invokeMultimovies(multimoviesAPI, res.title, res.season, res.episode, subtitleCallback, callback) - }, - { - if (res.isBollywood) invokeMultimovies(multimovies2API, res.title, res.season, res.episode, subtitleCallback, callback) - }, - { - invokeNetmovies(res.title, res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime && res.season == null) invokeDoomovies(res.title, subtitleCallback, callback) - }, - { - if (res.isAsian) invokeDramaday(res.title, res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invoke2embed(res.imdbId, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeHdmovies4u(res.title, res.imdbId, res.season, res.episode, subtitleCallback, callback) - }, - { - invokeZshow(res.title, res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeShowflix(res.title, res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeSFMovies(res.id, res.title, res.airedYear - ?: res.year, res.season, res.episode, callback) - }, - { - invokeMMovies(res.title, res.season, res.episode, subtitleCallback, callback) - }, + { + if (!res.isAnime) invokeFilmxy( + res.imdbId, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime && res.isCartoon) invokeKimcartoon( + res.title, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime && res.isCartoon) invokeWatchCartoon( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeVidsrcto( + res.imdbId, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (res.isAsian || res.isAnime) invokeKisskh( + res.title, + res.season, + res.episode, + res.isAnime, + res.lastSeason, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeOmovies( + res.title, + res.year, + res.season, + res.episode, + callback + ) + }, + { + if (!res.isAnime) invokeLing( + res.title, res.airedYear + ?: res.year, res.season, res.episode, subtitleCallback, callback + ) + }, + { + if (!res.isAnime) invokeUhdmovies( + res.title, + res.year, + res.season, + res.episode, + callback + ) + }, + { + if (!res.isAnime) invokeGMovies( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeFDMovies(res.title, res.season, res.episode, callback) + }, + { + if (!res.isAnime) invokeM4uhd( + res.title, res.airedYear + ?: res.year, res.season, res.episode, subtitleCallback, callback + ) + }, + { + if (!res.isAnime) invokeTvMovies(res.title, res.season, res.episode, callback) + }, + { + if (!res.isAnime) invokeMoviezAdd( + moviezAddAPI, + "MoviezAdd", + res.title, + res.year, + res.season, + res.episode, + callback + ) + }, + { + if (!res.isAnime && res.isBollywood) invokeBollyMaza( + bollyMazaAPI, + "BollyMaza", + res.title, + res.year, + res.season, + res.episode, + callback + ) + }, + { + if (!res.isAnime) invokeRStream(res.id, res.season, res.episode, callback) + }, + { + if (!res.isAnime) invokeFlixon( + res.id, + res.imdbId, + res.season, + res.episode, + callback + ) + }, + { + if (!res.isAnime) invokeSmashyStream( + res.imdbId, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeWatchsomuch( + res.imdbId, + res.season, + res.episode, + subtitleCallback + ) + }, + { + if (!res.isAnime) invokeNinetv( + res.id, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + invokeDahmerMovies(res.title, res.year, res.season, res.episode, callback) + }, + { + invokeCinemaTv( + res.imdbId, res.title, res.airedYear + ?: res.year, res.season, res.episode, subtitleCallback, callback + ) + }, + { + if (!res.isAnime) invokeNowTv(res.id, res.imdbId, res.season, res.episode, callback) + }, + { + if (!res.isAnime && res.season == null) invokeRidomovies( + res.id, + res.imdbId, + callback + ) + }, + { + if (!res.isAnime) invokeAllMovieland(res.imdbId, res.season, res.episode, callback) + }, + { + if (!res.isAnime) invokeEmovies( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeVegamovies( + res.title, + res.year, + res.season, + res.lastSeason, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime && res.isBollywood) invokeDotmovies( + res.title, + res.year, + res.season, + res.lastSeason, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (res.isBollywood) invokeMultimovies( + multimoviesAPI, + res.title, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (res.isBollywood) invokeMultimovies( + multimovies2API, + res.title, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + invokeNetmovies( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime && res.season == null) invokeDoomovies( + res.title, + subtitleCallback, + callback + ) + }, + { + if (res.isAsian) invokeDramaday( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invoke2embed( + res.imdbId, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeHdmovies4u( + res.title, + res.imdbId, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + invokeZshow( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeShowflix( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeSFMovies( + res.id, res.title, res.airedYear + ?: res.year, res.season, res.episode, callback + ) + }, + { + invokeMMovies(res.title, res.season, res.episode, subtitleCallback, callback) + }, ) return true } data class LinkData( - val id: Int? = null, - val imdbId: String? = null, - val tvdbId: Int? = null, - val type: String? = null, - val season: Int? = null, - val episode: Int? = null, - val aniId: String? = null, - val animeId: String? = null, - val title: String? = null, - val year: Int? = null, - val orgTitle: String? = null, - val isAnime: Boolean = false, - val airedYear: Int? = null, - val lastSeason: Int? = null, - val epsTitle: String? = null, - val jpTitle: String? = null, - val date: String? = null, - val airedDate: String? = null, - val isAsian: Boolean = false, - val isBollywood: Boolean = false, - val isCartoon: Boolean = false, + val id: Int? = null, + val imdbId: String? = null, + val tvdbId: Int? = null, + val type: String? = null, + val season: Int? = null, + val episode: Int? = null, + val aniId: String? = null, + val animeId: String? = null, + val title: String? = null, + val year: Int? = null, + val orgTitle: String? = null, + val isAnime: Boolean = false, + val airedYear: Int? = null, + val lastSeason: Int? = null, + val epsTitle: String? = null, + val jpTitle: String? = null, + val date: String? = null, + val airedDate: String? = null, + val isAsian: Boolean = false, + val isBollywood: Boolean = false, + val isCartoon: Boolean = false, ) data class Data( - val id: Int? = null, - val type: String? = null, - val aniId: String? = null, - val malId: Int? = null, + val id: Int? = null, + val type: String? = null, + val aniId: String? = null, + val malId: Int? = null, ) data class Results( - @JsonProperty("results") val results: ArrayList? = arrayListOf(), + @JsonProperty("results") val results: ArrayList? = arrayListOf(), ) data class Media( - @JsonProperty("id") val id: Int? = null, - @JsonProperty("name") val name: String? = null, - @JsonProperty("title") val title: String? = null, - @JsonProperty("original_title") val originalTitle: String? = null, - @JsonProperty("media_type") val mediaType: String? = null, - @JsonProperty("poster_path") val posterPath: String? = null, + @JsonProperty("id") val id: Int? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("title") val title: String? = null, + @JsonProperty("original_title") val originalTitle: String? = null, + @JsonProperty("media_type") val mediaType: String? = null, + @JsonProperty("poster_path") val posterPath: String? = null, ) data class Genres( - @JsonProperty("id") val id: Int? = null, - @JsonProperty("name") val name: String? = null, + @JsonProperty("id") val id: Int? = null, + @JsonProperty("name") val name: String? = null, ) data class Keywords( - @JsonProperty("id") val id: Int? = null, - @JsonProperty("name") val name: String? = null, + @JsonProperty("id") val id: Int? = null, + @JsonProperty("name") val name: String? = null, ) data class KeywordResults( - @JsonProperty("results") val results: ArrayList? = arrayListOf(), - @JsonProperty("keywords") val keywords: ArrayList? = arrayListOf(), + @JsonProperty("results") val results: ArrayList? = arrayListOf(), + @JsonProperty("keywords") val keywords: ArrayList? = arrayListOf(), ) data class Seasons( - @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, + @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( - @JsonProperty("id") val id: Int? = null, - @JsonProperty("name") val name: String? = null, - @JsonProperty("original_name") val originalName: String? = null, - @JsonProperty("character") val character: String? = null, - @JsonProperty("known_for_department") val knownForDepartment: String? = null, - @JsonProperty("profile_path") val profilePath: String? = null, + @JsonProperty("id") val id: Int? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("original_name") val originalName: String? = null, + @JsonProperty("character") val character: String? = null, + @JsonProperty("known_for_department") val knownForDepartment: String? = null, + @JsonProperty("profile_path") val profilePath: String? = null, ) data class Episodes( - @JsonProperty("id") val id: Int? = null, - @JsonProperty("name") val name: String? = null, - @JsonProperty("overview") val overview: String? = null, - @JsonProperty("air_date") val airDate: String? = null, - @JsonProperty("still_path") val stillPath: String? = null, - @JsonProperty("vote_average") val voteAverage: Double? = null, - @JsonProperty("episode_number") val episodeNumber: Int? = null, - @JsonProperty("season_number") val seasonNumber: Int? = null, + @JsonProperty("id") val id: Int? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("overview") val overview: String? = null, + @JsonProperty("air_date") val airDate: String? = null, + @JsonProperty("still_path") val stillPath: String? = null, + @JsonProperty("vote_average") val voteAverage: Double? = null, + @JsonProperty("episode_number") val episodeNumber: Int? = null, + @JsonProperty("season_number") val seasonNumber: Int? = null, ) data class MediaDetailEpisodes( - @JsonProperty("episodes") val episodes: ArrayList? = arrayListOf(), + @JsonProperty("episodes") val episodes: ArrayList? = arrayListOf(), ) data class Trailers( - @JsonProperty("key") val key: String? = null, + @JsonProperty("key") val key: String? = null, ) data class ResultsTrailer( - @JsonProperty("results") val results: ArrayList? = arrayListOf(), + @JsonProperty("results") val results: ArrayList? = arrayListOf(), ) data class AltTitles( - @JsonProperty("iso_3166_1") val iso_3166_1: String? = null, - @JsonProperty("title") val title: String? = null, - @JsonProperty("type") val type: String? = null, + @JsonProperty("iso_3166_1") val iso_3166_1: String? = null, + @JsonProperty("title") val title: String? = null, + @JsonProperty("type") val type: String? = null, ) data class ResultsAltTitles( - @JsonProperty("results") val results: ArrayList? = arrayListOf(), + @JsonProperty("results") val results: ArrayList? = arrayListOf(), ) data class ExternalIds( - @JsonProperty("imdb_id") val imdb_id: String? = null, - @JsonProperty("tvdb_id") val tvdb_id: Int? = null, + @JsonProperty("imdb_id") val imdb_id: String? = null, + @JsonProperty("tvdb_id") val tvdb_id: Int? = null, ) data class Credits( - @JsonProperty("cast") val cast: ArrayList? = arrayListOf(), + @JsonProperty("cast") val cast: ArrayList? = arrayListOf(), ) data class ResultsRecommendations( - @JsonProperty("results") val results: ArrayList? = arrayListOf(), + @JsonProperty("results") val results: ArrayList? = arrayListOf(), ) data class LastEpisodeToAir( - @JsonProperty("episode_number") val episode_number: Int? = null, - @JsonProperty("season_number") val season_number: Int? = null, + @JsonProperty("episode_number") val episode_number: Int? = null, + @JsonProperty("season_number") val season_number: Int? = null, ) data class ProductionCountries( - @JsonProperty("name") val name: String? = null, + @JsonProperty("name") val name: String? = null, ) data class MediaDetail( - @JsonProperty("id") val id: Int? = null, - @JsonProperty("imdb_id") val imdbId: String? = null, - @JsonProperty("title") val title: String? = null, - @JsonProperty("name") val name: String? = null, - @JsonProperty("original_title") val originalTitle: String? = null, - @JsonProperty("original_name") val originalName: String? = null, - @JsonProperty("poster_path") val posterPath: String? = null, - @JsonProperty("backdrop_path") val backdropPath: String? = null, - @JsonProperty("release_date") val releaseDate: String? = null, - @JsonProperty("first_air_date") val firstAirDate: String? = null, - @JsonProperty("overview") val overview: String? = null, - @JsonProperty("runtime") val runtime: Int? = null, - @JsonProperty("vote_average") val vote_average: Any? = null, - @JsonProperty("original_language") val original_language: String? = null, - @JsonProperty("status") val status: String? = null, - @JsonProperty("genres") val genres: ArrayList? = arrayListOf(), - @JsonProperty("keywords") val keywords: KeywordResults? = null, - @JsonProperty("last_episode_to_air") val last_episode_to_air: LastEpisodeToAir? = null, - @JsonProperty("seasons") val seasons: ArrayList? = arrayListOf(), - @JsonProperty("videos") val videos: ResultsTrailer? = null, - @JsonProperty("external_ids") val external_ids: ExternalIds? = null, - @JsonProperty("credits") val credits: Credits? = null, - @JsonProperty("recommendations") val recommendations: ResultsRecommendations? = null, - @JsonProperty("alternative_titles") val alternative_titles: ResultsAltTitles? = null, - @JsonProperty("production_countries") val production_countries: ArrayList? = arrayListOf(), + @JsonProperty("id") val id: Int? = null, + @JsonProperty("imdb_id") val imdbId: String? = null, + @JsonProperty("title") val title: String? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("original_title") val originalTitle: String? = null, + @JsonProperty("original_name") val originalName: String? = null, + @JsonProperty("poster_path") val posterPath: String? = null, + @JsonProperty("backdrop_path") val backdropPath: String? = null, + @JsonProperty("release_date") val releaseDate: String? = null, + @JsonProperty("first_air_date") val firstAirDate: String? = null, + @JsonProperty("overview") val overview: String? = null, + @JsonProperty("runtime") val runtime: Int? = null, + @JsonProperty("vote_average") val vote_average: Any? = null, + @JsonProperty("original_language") val original_language: String? = null, + @JsonProperty("status") val status: String? = null, + @JsonProperty("genres") val genres: ArrayList? = arrayListOf(), + @JsonProperty("keywords") val keywords: KeywordResults? = null, + @JsonProperty("last_episode_to_air") val last_episode_to_air: LastEpisodeToAir? = null, + @JsonProperty("seasons") val seasons: ArrayList? = arrayListOf(), + @JsonProperty("videos") val videos: ResultsTrailer? = null, + @JsonProperty("external_ids") val external_ids: ExternalIds? = null, + @JsonProperty("credits") val credits: Credits? = null, + @JsonProperty("recommendations") val recommendations: ResultsRecommendations? = null, + @JsonProperty("alternative_titles") val alternative_titles: ResultsAltTitles? = null, + @JsonProperty("production_countries") val production_countries: ArrayList? = arrayListOf(), ) } diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index 2ea87243..03d63963 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -42,121 +42,291 @@ import com.lagradost.cloudstream3.utils.ExtractorLink class SoraStreamLite : SoraStream() { override var name = "SoraStream-Lite" - override suspend fun loadLinks(data: String, isCasting: Boolean, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit): Boolean { + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { val res = AppUtils.parseJson(data) argamap( - { - if (!res.isAnime) invokeWatchsomuch(res.imdbId, res.season, res.episode, subtitleCallback) - }, - { - invokeDumpStream(res.title, res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeNinetv(res.id, res.season, res.episode, subtitleCallback, callback) - }, - { - invokeGoku(res.title, res.year, res.season, res.lastSeason, res.episode, subtitleCallback, callback) - }, - { - invokeVidSrc(res.id, res.season, res.episode, callback) - }, - { - invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime && res.isCartoon) invokeWatchCartoon(res.title, res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (res.isAnime) invokeAnimes(res.title, res.epsTitle, res.date, res.airedDate, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeDreamfilm(res.title, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeFilmxy(res.imdbId, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeOmovies(res.title, res.year, res.season, res.episode, callback) - }, - { - if (!res.isAnime && res.isCartoon) invokeKimcartoon(res.title, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeSmashyStream(res.imdbId, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeVidsrcto(res.imdbId, res.season, res.episode, subtitleCallback, callback) - }, - { - if (res.isAsian || res.isAnime) invokeKisskh(res.title, res.season, res.episode, res.isAnime, res.lastSeason, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeLing(res.title, res.airedYear - ?: res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeM4uhd(res.title, res.airedYear - ?: res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeRStream(res.id, res.season, res.episode, callback) - }, - { - if (!res.isAnime) invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback) - }, - { - invokeCinemaTv(res.imdbId, res.title, res.airedYear - ?: res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeNowTv(res.id, res.imdbId, res.season, res.episode, callback) - }, - { - if (!res.isAnime) invokeAoneroom(res.title, res.airedYear - ?: res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime && res.season == null) invokeRidomovies(res.id, res.imdbId, callback) - }, - { - if (!res.isAnime) invokeEmovies(res.title, res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (res.isBollywood) invokeMultimovies(multimoviesAPI, res.title, res.season, res.episode, subtitleCallback, callback) - }, - { - if (res.isBollywood) invokeMultimovies(multimovies2API, res.title, res.season, res.episode, subtitleCallback, callback) - }, - { - invokeNetmovies(res.title, res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeAllMovieland(res.imdbId, res.season, res.episode, callback) - }, - { - if (!res.isAnime && res.season == null) invokeDoomovies(res.title, subtitleCallback, callback) - }, - { - if (res.isAsian) invokeDramaday(res.title, res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invoke2embed(res.imdbId, res.season, res.episode, subtitleCallback, callback) - }, - { - invokeZshow(res.title, res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeShowflix(res.title, res.year, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeSFMovies(res.id, res.title, res.airedYear - ?: res.year, res.season, res.episode, callback) - }, - { - invokeMMovies(res.title, res.season, res.episode, subtitleCallback, callback) - }, + { + if (!res.isAnime) invokeWatchsomuch( + res.imdbId, + res.season, + res.episode, + subtitleCallback + ) + }, + { + invokeDumpStream( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeNinetv( + res.id, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + invokeGoku( + res.title, + res.year, + res.season, + res.lastSeason, + res.episode, + subtitleCallback, + callback + ) + }, + { + invokeVidSrc(res.id, res.season, res.episode, callback) + }, + { + invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime && res.isCartoon) invokeWatchCartoon( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (res.isAnime) invokeAnimes( + res.title, + res.epsTitle, + res.date, + res.airedDate, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeDreamfilm( + res.title, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeFilmxy( + res.imdbId, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeOmovies( + res.title, + res.year, + res.season, + res.episode, + callback + ) + }, + { + if (!res.isAnime && res.isCartoon) invokeKimcartoon( + res.title, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeSmashyStream( + res.imdbId, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeVidsrcto( + res.imdbId, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (res.isAsian || res.isAnime) invokeKisskh( + res.title, + res.season, + res.episode, + res.isAnime, + res.lastSeason, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeLing( + res.title, res.airedYear + ?: res.year, res.season, res.episode, subtitleCallback, callback + ) + }, + { + if (!res.isAnime) invokeM4uhd( + res.title, res.airedYear + ?: res.year, res.season, res.episode, subtitleCallback, callback + ) + }, + { + if (!res.isAnime) invokeRStream(res.id, res.season, res.episode, callback) + }, + { + if (!res.isAnime) invokeFlixon( + res.id, + res.imdbId, + res.season, + res.episode, + callback + ) + }, + { + invokeCinemaTv( + res.imdbId, res.title, res.airedYear + ?: res.year, res.season, res.episode, subtitleCallback, callback + ) + }, + { + if (!res.isAnime) invokeNowTv(res.id, res.imdbId, res.season, res.episode, callback) + }, + { + if (!res.isAnime) invokeAoneroom( + res.title, res.airedYear + ?: res.year, res.season, res.episode, subtitleCallback, callback + ) + }, + { + if (!res.isAnime && res.season == null) invokeRidomovies( + res.id, + res.imdbId, + callback + ) + }, + { + if (!res.isAnime) invokeEmovies( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (res.isBollywood) invokeMultimovies( + multimoviesAPI, + res.title, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (res.isBollywood) invokeMultimovies( + multimovies2API, + res.title, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + invokeNetmovies( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeAllMovieland(res.imdbId, res.season, res.episode, callback) + }, + { + if (!res.isAnime && res.season == null) invokeDoomovies( + res.title, + subtitleCallback, + callback + ) + }, + { + if (res.isAsian) invokeDramaday( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invoke2embed( + res.imdbId, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + invokeZshow( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeShowflix( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, + { + if (!res.isAnime) invokeSFMovies( + res.id, res.title, res.airedYear + ?: res.year, res.season, res.episode, callback + ) + }, + { + invokeMMovies(res.title, res.season, res.episode, subtitleCallback, callback) + }, ) return true