From 9812b2ebd6f93e4840f56a3ac31ba145b34099c6 Mon Sep 17 00:00:00 2001 From: Blatzar Date: Thu, 26 Aug 2021 19:01:14 +0200 Subject: [PATCH] added AsiaFlixProvider.kt (more sources are possible) --- .../com/lagradost/cloudstream3/MainAPI.kt | 6 +- .../movieproviders/AsiaFlixProvider.kt | 184 ++++++++++++++++++ 2 files changed, 186 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/com/lagradost/cloudstream3/movieproviders/AsiaFlixProvider.kt diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt index c3387f7c..157e252a 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt @@ -6,10 +6,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.json.JsonMapper import com.fasterxml.jackson.module.kotlin.KotlinModule import com.lagradost.cloudstream3.animeproviders.* -import com.lagradost.cloudstream3.movieproviders.AllMoviesForYouProvider -import com.lagradost.cloudstream3.movieproviders.HDMProvider -import com.lagradost.cloudstream3.movieproviders.TrailersToProvider -import com.lagradost.cloudstream3.movieproviders.VMoveeProvider +import com.lagradost.cloudstream3.movieproviders.* import com.lagradost.cloudstream3.utils.ExtractorLink import java.util.* @@ -43,6 +40,7 @@ object APIHolder { VMoveeProvider(), WatchCartoonOnlineProvider(), AllMoviesForYouProvider(), + AsiaFlixProvider(), ) fun getApiFromName(apiName: String?): MainAPI { diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/AsiaFlixProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/AsiaFlixProvider.kt new file mode 100644 index 00000000..e6390f89 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/AsiaFlixProvider.kt @@ -0,0 +1,184 @@ +package com.lagradost.cloudstream3.movieproviders + +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.module.kotlin.readValue +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.animeproviders.GogoanimeProvider.Companion.getStatus +import com.lagradost.cloudstream3.utils.DataStore.toKotlinObject +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.getQualityFromName +import khttp.get + +class AsiaFlixProvider : MainAPI() { + override val mainUrl: String + get() = "https://asiaflix.app" + override val name: String + get() = "AsiaFlix" + override val hasQuickSearch: Boolean + get() = false + override val hasMainPage: Boolean + get() = true + override val hasDownloadSupport: Boolean + get() = false + override val hasChromecastSupport: Boolean + get() = false + + private val apiUrl = "https://api.asiaflix.app/api/v2" + + data class DashBoardObject( + @JsonProperty("sectionName") val sectionName: String, + @JsonProperty("type") val type: String?, + @JsonProperty("data") val data: List? + ) + + data class Episodes( + @JsonProperty("_id") val _id: String, + @JsonProperty("epUrl") val epUrl: String?, + @JsonProperty("number") val number: Int?, + @JsonProperty("type") val type: String?, + @JsonProperty("extracted") val extracted: String?, + @JsonProperty("videoUrl") val videoUrl: String? + ) + + + data class Data( + @JsonProperty("_id") val _id: String, + @JsonProperty("name") val name: String, + @JsonProperty("altNames") val altNames: String?, + @JsonProperty("image") val image: String?, + @JsonProperty("tvStatus") val tvStatus: String?, + @JsonProperty("genre") val genre: String?, + @JsonProperty("releaseYear") val releaseYear: Int?, + @JsonProperty("createdAt") val createdAt: Long?, + @JsonProperty("episodes") val episodes: List?, + @JsonProperty("views") val views: Int? + ) + + + data class DramaPage( + @JsonProperty("_id") val _id: String, + @JsonProperty("name") val name: String, + @JsonProperty("altNames") val altNames: String?, + @JsonProperty("synopsis") val synopsis: String?, + @JsonProperty("image") val image: String?, + @JsonProperty("language") val language: String?, + @JsonProperty("dramaUrl") val dramaUrl: String?, + @JsonProperty("published") val published: Boolean?, + @JsonProperty("tvStatus") val tvStatus: String?, + @JsonProperty("firstAirDate") val firstAirDate: String?, + @JsonProperty("genre") val genre: String?, + @JsonProperty("releaseYear") val releaseYear: Int?, + @JsonProperty("createdAt") val createdAt: Long?, + @JsonProperty("modifiedAt") val modifiedAt: Long?, + @JsonProperty("episodes") val episodes: List, + @JsonProperty("__v") val __v: Int?, + @JsonProperty("cdnImage") val cdnImage: String?, + @JsonProperty("views") val views: Int? + ) + + private fun Data.toSearchResponse(): TvSeriesSearchResponse { + return TvSeriesSearchResponse( + name, + _id, + this@AsiaFlixProvider.name, + TvType.TvSeries, + image, + releaseYear, + episodes?.size, + ) + } + + private fun Episodes.toTvSeriesEpisode(): TvSeriesEpisode? { + return videoUrl?.let { + TvSeriesEpisode( + null, + null, + number, + it + ) + } + } + + private fun DramaPage.toLoadResponse(): TvSeriesLoadResponse { + return TvSeriesLoadResponse( + name, + _id, + this@AsiaFlixProvider.name, + TvType.TvSeries, + episodes.mapNotNull { it.toTvSeriesEpisode() }.sortedBy { it.episode }, + image, + releaseYear, + synopsis, + getStatus(tvStatus ?: ""), + null, + null, + genre?.split(",")?.map { it.trim() } + ) + } + + override fun getMainPage(): HomePageResponse { + val headers = mapOf("X-Requested-By" to "asiaflix-web") + val response = get("$apiUrl/dashboard", headers = headers).text + + val customMapper = mapper.copy().configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true) + // Hack, because it can either be object or a list + val cleanedResponse = Regex(""""data":(\{.*?),\{"sectionName"""").replace(response) { + """"data":null},{"sectionName"""" + } + + val dashBoard = customMapper.readValue?>(cleanedResponse) + + val listItems = dashBoard?.mapNotNull { + it.data?.map { data -> + data.toSearchResponse() + }?.let { searchResponse -> + HomePageList(it.sectionName, searchResponse) + } + } + return HomePageResponse(listItems ?: listOf()) + } + + data class Link( + @JsonProperty("url") val url: String?, + ) + + override fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + if (isCasting) return false + val headers = mapOf("X-Requested-By" to "asiaflix-web") + get("$apiUrl/utility/get-stream-links?url=$data", headers = headers).text.toKotlinObject().url?.let { +// val fixedUrl = "https://api.asiaflix.app/api/v2/utility/cors-proxy/playlist/${URLEncoder.encode(it, StandardCharsets.UTF_8.toString())}" + callback.invoke( + ExtractorLink( + name, + name, + it, + "https://asianload.me/", + getQualityFromName(it), + it.endsWith(".m3u8") + ) + ) + } + return true + } + + override fun search(query: String): List? { + val headers = mapOf("X-Requested-By" to "asiaflix-web") + val url = "$apiUrl/drama/search?q=$query" + val response = get(url, headers = headers).text + return mapper.readValue?>(response)?.map { it.toSearchResponse() } + } + + override fun load(url: String): LoadResponse { + val headers = mapOf("X-Requested-By" to "asiaflix-web") + val requestUrl = "$apiUrl/drama?id=${url.split("/").lastOrNull()}" + val response = get(requestUrl, headers = headers).text + val dramaPage = response.toKotlinObject() + return dramaPage.toLoadResponse() + } +} \ No newline at end of file