From 2f9c76d9b5fc09b9bf12512ace7028bb7815006a Mon Sep 17 00:00:00 2001 From: LagradOst Date: Tue, 2 Nov 2021 16:09:29 +0100 Subject: [PATCH] updated anime API for dub/sub --- .../com/lagradost/cloudstream3/MainAPI.kt | 86 +++++++----- .../animeproviders/AllAnimeProvider.kt | 130 +++++++++--------- .../animeproviders/AnimeFlickProvider.kt | 24 ++-- .../animeproviders/AnimePaheProvider.kt | 40 +++--- .../animeproviders/DubbedAnimeProvider.kt | 22 +-- .../animeproviders/GogoanimeProvider.kt | 30 ++-- .../animeproviders/KawaiifuProvider.kt | 24 +--- .../animeproviders/TenshiProvider.kt | 31 ++--- .../animeproviders/WcoProvider.kt | 26 ++-- .../animeproviders/ZoroProvider.kt | 26 ++-- .../cloudstream3/ui/result/ResultFragment.kt | 28 +++- .../cloudstream3/ui/result/ResultViewModel.kt | 56 +++++--- app/src/main/res/layout/fragment_result.xml | 19 ++- 13 files changed, 280 insertions(+), 262 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt index ddc36dda..a312f170 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt @@ -255,7 +255,8 @@ fun sortSubs(urls: List): List { /** https://www.imdb.com/title/tt2861424/ -> tt2861424 */ fun imdbUrlToId(url: String): String? { - return Regex("/title/(tt[0-9]*)").find(url)?.groupValues?.get(1) ?: Regex("tt[0-9]{5,}").find(url)?.groupValues?.get(0) + return Regex("/title/(tt[0-9]*)").find(url)?.groupValues?.get(1) + ?: Regex("tt[0-9]{5,}").find(url)?.groupValues?.get(0) } fun imdbUrlToIdNullable(url: String?): String? { @@ -390,12 +391,12 @@ fun LoadResponse?.isAnimeBased(): Boolean { data class AnimeEpisode( val url: String, - val name: String? = null, - val posterUrl: String? = null, - val date: String? = null, - val rating: Int? = null, - val descript: String? = null, - val episode: Int? = null, + var name: String? = null, + var posterUrl: String? = null, + var date: String? = null, + var rating: Int? = null, + var description: String? = null, + var episode: Int? = null, ) data class TorrentLoadResponse( @@ -416,32 +417,47 @@ data class TorrentLoadResponse( ) : LoadResponse data class AnimeLoadResponse( - val engName: String?, - val japName: String?, + var engName: String? = null, + var japName: String? = null, override val name: String, override val url: String, override val apiName: String, override val type: TvType, - override val posterUrl: String?, - override val year: Int?, + override var posterUrl: String? = null, + override var year: Int? = null, - val dubEpisodes: List?, - val subEpisodes: List?, - val showStatus: ShowStatus?, + var episodes: HashMap> = hashMapOf(), + var showStatus: ShowStatus? = null, - override val plot: String?, - override val tags: List? = null, - val synonyms: List? = null, + override var plot: String? = null, + override var tags: List? = null, + var synonyms: List? = null, - val malId: Int? = null, - val anilistId: Int? = null, - override val rating: Int? = null, - override val duration: String? = null, - override val trailerUrl: String? = null, - override val recommendations: List? = null, + var malId: Int? = null, + var anilistId: Int? = null, + override var rating: Int? = null, + override var duration: String? = null, + override var trailerUrl: String? = null, + override var recommendations: List? = null, ) : LoadResponse +fun AnimeLoadResponse.addEpisodes(status : DubStatus, episodes : List?) { + if(episodes == null) return + this.episodes[status] = episodes +} + +fun MainAPI.newAnimeLoadResponse( + name: String, + url: String, + type: TvType, + initializer: AnimeLoadResponse.() -> Unit = { } +): AnimeLoadResponse { + val builder = AnimeLoadResponse(name = name, url = url, apiName = this.name, type = type) + builder.initializer() + return builder +} + data class MovieLoadResponse( override val name: String, override val url: String, @@ -449,11 +465,11 @@ data class MovieLoadResponse( override val type: TvType, val dataUrl: String, - override val posterUrl: String?, - override val year: Int?, - override val plot: String?, + override val posterUrl: String? = null, + override val year: Int? = null, + override val plot: String? = null, - val imdbId: String?, + val imdbId: String? = null, override val rating: Int? = null, override val tags: List? = null, override val duration: String? = null, @@ -462,9 +478,9 @@ data class MovieLoadResponse( ) : LoadResponse data class TvSeriesEpisode( - val name: String?, - val season: Int?, - val episode: Int?, + val name: String? = null, + val season: Int? = null, + val episode: Int? = null, val data: String, val posterUrl: String? = null, val date: String? = null, @@ -479,12 +495,12 @@ data class TvSeriesLoadResponse( override val type: TvType, val episodes: List, - override val posterUrl: String?, - override val year: Int?, - override val plot: String?, + override val posterUrl: String? = null, + override val year: Int? = null, + override val plot: String? = null, - val showStatus: ShowStatus?, - val imdbId: String?, + val showStatus: ShowStatus? = null, + val imdbId: String? = null, override val rating: Int? = null, override val tags: List? = null, override val duration: String? = null, diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt index 9fb45c00..19cbe536 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt @@ -1,21 +1,19 @@ package com.lagradost.cloudstream3.animeproviders -import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.utils.* -import com.lagradost.cloudstream3.network.get -import com.lagradost.cloudstream3.network.text -import com.lagradost.cloudstream3.utils.ExtractorLink -import org.jsoup.Jsoup -import java.util.* - import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.module.kotlin.readValue -import kotlin.collections.ArrayList +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.network.get +import com.lagradost.cloudstream3.network.text +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.M3u8Helper +import com.lagradost.cloudstream3.utils.getQualityFromName +import org.jsoup.Jsoup import org.mozilla.javascript.Context import org.mozilla.javascript.Scriptable import java.net.URI import java.net.URLDecoder -import com.lagradost.cloudstream3.utils.getQualityFromName +import java.util.* class AllAnimeProvider : MainAPI() { @@ -27,7 +25,7 @@ class AllAnimeProvider : MainAPI() { get() = false override val hasMainPage: Boolean get() = false - + private val hlsHelper = M3u8Helper() private fun getStatus(t: String): ShowStatus { @@ -41,17 +39,17 @@ class AllAnimeProvider : MainAPI() { override val supportedTypes: Set get() = setOf(TvType.Anime, TvType.AnimeMovie) - private data class Data ( + private data class Data( @JsonProperty("shows") val shows: Shows ) - private data class Shows ( + private data class Shows( @JsonProperty("pageInfo") val pageInfo: PageInfo, @JsonProperty("edges") val edges: List, @JsonProperty("__typename") val _typename: String ) - private data class Edges ( + private data class Edges( @JsonProperty("_id") val Id: String?, @JsonProperty("name") val name: String, @JsonProperty("englishName") val englishName: String?, @@ -68,34 +66,35 @@ class AllAnimeProvider : MainAPI() { @JsonProperty("status") val status: String?, ) - private data class AvailableEpisodes ( + private data class AvailableEpisodes( @JsonProperty("sub") val sub: Int, @JsonProperty("dub") val dub: Int, @JsonProperty("raw") val raw: Int ) - private data class AiredStart ( + private data class AiredStart( @JsonProperty("year") val year: Int, @JsonProperty("month") val month: Int, @JsonProperty("date") val date: Int ) - private data class Season ( + private data class Season( @JsonProperty("quarter") val quarter: String, @JsonProperty("year") val year: Int ) - private data class PageInfo ( + private data class PageInfo( @JsonProperty("total") val total: Int, @JsonProperty("__typename") val _typename: String ) - private data class AllAnimeQuery ( + private data class AllAnimeQuery( @JsonProperty("data") val data: Data ) override fun search(query: String): ArrayList { - val link = """$mainUrl/graphql?variables=%7B%22search%22%3A%7B%22allowAdult%22%3Afalse%2C%22query%22%3A%22$query%22%7D%2C%22limit%22%3A26%2C%22page%22%3A1%2C%22translationType%22%3A%22sub%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%229343797cc3d9e3f444e2d3b7db9a84d759b816a4d84512ea72d079f85bb96e98%22%7D%7D""" + val link = + """$mainUrl/graphql?variables=%7B%22search%22%3A%7B%22allowAdult%22%3Afalse%2C%22query%22%3A%22$query%22%7D%2C%22limit%22%3A26%2C%22page%22%3A1%2C%22translationType%22%3A%22sub%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%229343797cc3d9e3f444e2d3b7db9a84d759b816a4d84512ea72d079f85bb96e98%22%7D%7D""" var res = get(link).text if (res.contains("PERSISTED_QUERY_NOT_FOUND")) { res = get(link).text @@ -116,15 +115,15 @@ class AllAnimeProvider : MainAPI() { TvType.Anime, it.thumbnail, it.airedStart?.year, - EnumSet.of(DubStatus.Subbed), //, DubStatus.Dubbed), + EnumSet.of(DubStatus.Subbed, DubStatus.Dubbed), it.englishName, - null, //it.availableEpisodes?.dub, + it.availableEpisodes?.dub, it.availableEpisodes?.sub ) }) } - private data class AvailableEpisodesDetail ( + private data class AvailableEpisodesDetail( @JsonProperty("sub") val sub: List, @JsonProperty("dub") val dub: List, @JsonProperty("raw") val raw: List @@ -137,7 +136,6 @@ class AllAnimeProvider : MainAPI() { rhino.optimizationLevel = -1 val scope: Scriptable = rhino.initStandardObjects() - val html = get(url).text val soup = Jsoup.parse(html) @@ -161,43 +159,28 @@ class AllAnimeProvider : MainAPI() { val episodes = showData.availableEpisodes.let { if (it == null) return@let Pair(null, null) - Pair(if (it.sub != 0) ArrayList((1 .. it.sub).map { epNum -> + Pair(if (it.sub != 0) ArrayList((1..it.sub).map { epNum -> AnimeEpisode( - "$mainUrl/anime/${showData.Id}/episodes/sub/$epNum", - null, - null, - null, - null, - null, - epNum + "$mainUrl/anime/${showData.Id}/episodes/sub/$epNum", episode = epNum ) - }) else null, if (it.dub != 0) ArrayList((1 .. it.dub).map { epNum -> + }) else null, if (it.dub != 0) ArrayList((1..it.dub).map { epNum -> AnimeEpisode( - "$mainUrl/anime/${showData.Id}/episodes/dub/$epNum", - null, - null, - null, - null, - null, - epNum + "$mainUrl/anime/${showData.Id}/episodes/dub/$epNum", episode = epNum ) }) else null) } - return AnimeLoadResponse( - null, - null, - title, - url, - this.name, - TvType.Anime, - poster, - showData.airedStart?.year, - null, // no dub, because there is no way to switch from dub to sub //episodes.second, - episodes.first, - getStatus(showData.status.toString()), - description?.replace(Regex("""\<(.*?)\>"""), "") - ) + return newAnimeLoadResponse(title, url, TvType.Anime) { + posterUrl = poster + year = showData.airedStart?.year + + addEpisodes(DubStatus.Subbed, episodes.first) + addEpisodes(DubStatus.Dubbed, episodes.second) + + showStatus = getStatus(showData.status.toString()) + + plot = description?.replace(Regex("""<(.*?)>"""), "") + } } private val embedBlackList = listOf( @@ -216,7 +199,7 @@ class AllAnimeProvider : MainAPI() { return true } } else { - if (url.contains(it as String)) { + if (url.contains(it)) { return true } } @@ -232,21 +215,21 @@ class AllAnimeProvider : MainAPI() { return out } - private data class Links ( + private data class Links( @JsonProperty("link") val link: String, @JsonProperty("hls") val hls: Boolean?, @JsonProperty("resolutionStr") val resolutionStr: String, @JsonProperty("src") val src: String? ) - private data class AllAnimeVideoApiResponse ( + private data class AllAnimeVideoApiResponse( @JsonProperty("links") val links: List ) private data class ApiEndPoint( @JsonProperty("episodeIframeHead") val episodeIframeHead: String ) - + private fun getM3u8Qualities(m3u8Link: String, referer: String, qualityName: String): ArrayList { return ArrayList(hlsHelper.m3u8Generation(M3u8Helper.M3u8Stream(m3u8Link, null), true).map { stream -> val qualityString = if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p" @@ -273,7 +256,8 @@ class AllAnimeProvider : MainAPI() { val html = get(data).text - val sources = Regex("""sourceUrl[:=]"(.+?)"""").findAll(html).toList().map { URLDecoder.decode(it.destructured.component1().sanitize(), "UTF-8") } + val sources = Regex("""sourceUrl[:=]"(.+?)"""").findAll(html).toList() + .map { URLDecoder.decode(it.destructured.component1().sanitize(), "UTF-8") } sources.forEach { var link = it if (URI(link).isAbsolute || link.startsWith("//")) { @@ -305,16 +289,26 @@ class AllAnimeProvider : MainAPI() { val links = mapper.readValue(response.text).links links.forEach { server -> if (server.hls != null && server.hls) { - getM3u8Qualities(server.link, "$apiEndPoint/player?uri=" + (if (URI(server.link).host.isNotEmpty()) server.link else apiEndPoint + URI(server.link).path), server.resolutionStr).forEach(callback) - } else { - callback(ExtractorLink( - "AllAnime - " + URI(server.link).host, - server.resolutionStr, + getM3u8Qualities( server.link, - "$apiEndPoint/player?uri=" + (if (URI(server.link).host.isNotEmpty()) server.link else apiEndPoint + URI(server.link).path), - getQualityFromName("1080"), - false - )) + "$apiEndPoint/player?uri=" + (if (URI(server.link).host.isNotEmpty()) server.link else apiEndPoint + URI( + server.link + ).path), + server.resolutionStr + ).forEach(callback) + } else { + callback( + ExtractorLink( + "AllAnime - " + URI(server.link).host, + server.resolutionStr, + server.link, + "$apiEndPoint/player?uri=" + (if (URI(server.link).host.isNotEmpty()) server.link else apiEndPoint + URI( + server.link + ).path), + getQualityFromName("1080"), + false + ) + ) } } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AnimeFlickProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AnimeFlickProvider.kt index e18dc610..eabecc4e 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AnimeFlickProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AnimeFlickProvider.kt @@ -76,21 +76,15 @@ class AnimeFlickProvider : MainAPI() { AnimeEpisode(link, name) }.reversed() - return AnimeLoadResponse( - title, - null, - title, - url, - this.name, - getType(title), - poster, - year, - null, - episodes, - null, - description, - genres - ) + return newAnimeLoadResponse(title, url, getType(title)) { + posterUrl = poster + this.year = year + + addEpisodes(DubStatus.Subbed, episodes) + + plot = description + tags = genres + } } override fun loadLinks( diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AnimePaheProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AnimePaheProvider.kt index b056bbbd..13187b8b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AnimePaheProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AnimePaheProvider.kt @@ -293,30 +293,26 @@ class AnimePaheProvider : MainAPI() { } } - AnimeLoadResponse( - animeTitle, - japTitle, - animeTitle, - url, - this.name, - getType(tvType.toString()), - poster, - year, - null, - episodes, - status, - synopsis, - if (!doc.select(".anime-genre > ul a").isEmpty()) { + newAnimeLoadResponse(animeTitle, url, getType(tvType.toString())) { + engName = animeTitle + japName = japTitle + + this.posterUrl = poster + this.year = year + + addEpisodes(DubStatus.Subbed, episodes) + this.showStatus = status + plot = synopsis + tags = if (!doc.select(".anime-genre > ul a").isEmpty()) { ArrayList(doc.select(".anime-genre > ul a").map { it.text().toString() }) } else { null - }, - ArrayList(), - malId, - anilistId, - null, - trailer - ) + } + + this.malId = malId + this.anilistId = anilistId + this.trailerUrl = trailer + } } } @@ -325,7 +321,6 @@ class AnimePaheProvider : MainAPI() { return s?.toIntOrNull() != null } - private fun cookieStrToMap(cookie: String): Map { val cookies = mutableMapOf() for (string in cookie.split("; ")) { @@ -347,7 +342,6 @@ class AnimePaheProvider : MainAPI() { val slice2 = characterMap.slice(0 until s2) var acc: Long = 0 - for ((n, i) in content.reversed().withIndex()) { acc += (when (isNumber("$i")) { true -> "$i".toLong() diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/DubbedAnimeProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/DubbedAnimeProvider.kt index 80f22b9a..d3a4e277 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/DubbedAnimeProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/DubbedAnimeProvider.kt @@ -109,7 +109,7 @@ class DubbedAnimeProvider : MainAPI() { HomePageList("Trending", parseDocumentTrending(trendingUrl)), HomePageList("Recently Added", parseDocument(recentlyAddedUrl)), HomePageList("Recent Releases", parseDocument(lastEpisodeUrl, true)), - // HomePageList("All", parseDocument(allUrl)) + // HomePageList("All", parseDocument(allUrl)) ) return HomePageResponse(listItems) @@ -268,20 +268,12 @@ class DubbedAnimeProvider : MainAPI() { } val img = fixUrl(document.select("div.fkimgs > img").attr("src")) - return AnimeLoadResponse( - null, - null, - title, - url, - this.name, - TvType.Anime, - img, - year, - ArrayList(episodes), - null, - null, - descript, - ) + return newAnimeLoadResponse(title, url, TvType.Anime) { + posterUrl = img + this.year = year + addEpisodes(DubStatus.Dubbed, episodes) + plot = descript + } } } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/GogoanimeProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/GogoanimeProvider.kt index 2f14b8dd..3092e949 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/GogoanimeProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/GogoanimeProvider.kt @@ -185,24 +185,18 @@ class GogoanimeProvider : MainAPI() { "Episode " + it.selectFirst(".name").text().replace("EP", "").trim() ) }.reversed() - return AnimeLoadResponse( - title, - nativeName, - title, - link, - this.name, - getType(type.toString()), - poster, - year, - null, - episodes, - getStatus(status.toString()), - description, - ArrayList(genre), - null, - null, - null, - ) + + return newAnimeLoadResponse(title, link, getType(type.toString())) { + japName = nativeName + engName = title + posterUrl = poster + this.year = year + addEpisodes(DubStatus.Subbed, episodes) // TODO CHECK + plot = description + tags = genre + + showStatus = getStatus(status.toString()) + } } private fun extractVideos(uri: String): List { diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/KawaiifuProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/KawaiifuProvider.kt index d8de465a..cde4f208 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/KawaiifuProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/KawaiifuProvider.kt @@ -109,23 +109,13 @@ class KawaiifuProvider : MainAPI() { } val poster = soup.selectFirst("a.thumb > img").attr("src") - - return AnimeLoadResponse( - title, - null, - title, - url, - this.name, - TvType.Anime, - poster, - year, - null, - episodes, - ShowStatus.Ongoing, - description, - ArrayList(tags), - ArrayList() - ) + return newAnimeLoadResponse(title, url, TvType.Anime) { + this.year = year + posterUrl = poster + addEpisodes(DubStatus.Subbed, episodes) + plot = description + this.tags = tags + } } override fun loadLinks( diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/TenshiProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/TenshiProvider.kt index 95d10a37..2bec47c6 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/TenshiProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/TenshiProvider.kt @@ -268,24 +268,19 @@ class TenshiProvider : MainAPI() { val synonyms = document.select("li.synonym.meta-data > div.info-box > span.value").map { it?.text()?.trim().toString() } - return AnimeLoadResponse( - englishTitle, - japaneseTitle, - canonicalTitle, - url, - this.name, - getType(type ?: ""), - poster, - year.toIntOrNull(), - null, - episodes, - status, - synopsis, - ArrayList(genre), - ArrayList(synonyms), - null, - null, - ) + return newAnimeLoadResponse(canonicalTitle,url,getType(type ?: "")) { + engName = englishTitle + japName = japaneseTitle + + posterUrl = poster + this.year = year.toIntOrNull() + + addEpisodes(DubStatus.Subbed,episodes) + showStatus = status + tags = genre + this.synonyms = synonyms + plot = synopsis + } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/WcoProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/WcoProvider.kt index fe127565..6c96c92f 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/WcoProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/WcoProvider.kt @@ -208,22 +208,16 @@ class WcoProvider : MainAPI() { val genre = document.select("div.elements div.row > div:nth-child(1) > div.row-line:nth-child(5) > a") .map { it?.text()?.trim().toString() } - return AnimeLoadResponse( - canonicalTitle, - japaneseTitle, - canonicalTitle, - url, - this.name, - getType(type ?: ""), - poster, - year, - if (isDubbed) episodes else null, - if (!isDubbed) episodes else null, - status, - synopsis, - ArrayList(genre), - ArrayList(), - ) + return newAnimeLoadResponse(canonicalTitle,url,getType(type ?: "")) { + japName = japaneseTitle + engName = canonicalTitle + posterUrl = poster + this.year = year + addEpisodes(if(isDubbed) DubStatus.Dubbed else DubStatus.Subbed,episodes) + showStatus = status + plot = synopsis + tags = genre + } } override fun loadLinks( diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ZoroProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ZoroProvider.kt index f13d79e3..21ac1511 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ZoroProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ZoroProvider.kt @@ -230,21 +230,17 @@ class ZoroProvider : MainAPI() { it.selectFirst(".ssli-order")?.text()?.toIntOrNull() ) } - return AnimeLoadResponse( - title, - japaneseTitle, - title, - url, - this.name, - TvType.Anime, - poster, - year, - null, - episodes, - status, - description, - tags, - ) + + return newAnimeLoadResponse(title, url, TvType.Anime) { + japName = japaneseTitle + engName = title + posterUrl = poster + this.year = year + addEpisodes(DubStatus.Subbed, episodes) + showStatus = status + plot = description + this.tags = tags + } } private fun getM3u8FromRapidCloud(url: String): String { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt index b14b0712..382ceb01 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt @@ -235,7 +235,7 @@ class ResultFragment : Fragment() { private var currentId: Int? = null private var currentIsMovie: Boolean? = null private var episodeRanges: List? = null - + private var dubRange: Set? = null var url: String? = null private fun fromIndexToSeasonText(selection: Int?): String { @@ -681,7 +681,6 @@ class ResultFragment : Fragment() { } outputFile.writeText(text) - val vlcIntent = Intent(VLC_INTENT_ACTION_RESULT) vlcIntent.setPackage(VLC_PACKAGE) @@ -858,6 +857,25 @@ class ResultFragment : Fragment() { } } + observe(viewModel.dubStatus) { status -> + result_dub_select?.text = status.toString() + } + + observe(viewModel.dubSubSelections) { range -> + dubRange = range + result_dub_select?.visibility = if (range.size <= 1) GONE else VISIBLE + } + + result_dub_select.setOnClickListener { + val ranges = dubRange + if (ranges != null) { + it.popupMenuNoIconsAndNoStringRes(ranges.map { status -> Pair(status.ordinal, status.toString()) } + .toList()) { + viewModel.changeDubStatus(requireContext(), DubStatus.values()[itemId]) + } + } + } + observe(viewModel.selectedRange) { range -> result_episode_select?.text = range } @@ -962,8 +980,10 @@ class ResultFragment : Fragment() { if (metadataInfoArray.size > 0) { result_metadata.visibility = VISIBLE val text = SpannableStringBuilder() - val grayColor = ctx.colorFromAttribute(R.attr.grayTextColor) //ContextCompat.getColor(requireContext(), R.color.grayTextColor) - val textColor = ctx.colorFromAttribute(R.attr.textColor) //ContextCompat.getColor(requireContext(), R.color.textColor) + val grayColor = + ctx.colorFromAttribute(R.attr.grayTextColor) //ContextCompat.getColor(requireContext(), R.color.grayTextColor) + val textColor = + ctx.colorFromAttribute(R.attr.textColor) //ContextCompat.getColor(requireContext(), R.color.textColor) for (meta in metadataInfoArray) { text.color(grayColor) { append(getString(meta.first) + ": ") } .color(textColor) { append("${meta.second}\n") } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt index ad7f7d85..25e9bf37 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt @@ -55,13 +55,20 @@ class ResultViewModel : ViewModel() { val publicEpisodes: LiveData>> get() = _publicEpisodes val publicEpisodesCount: LiveData get() = _publicEpisodesCount - private val dubStatus: MutableLiveData = MutableLiveData() + val dubStatus: MutableLiveData get() = _dubStatus + private val _dubStatus: MutableLiveData = MutableLiveData() private val page: MutableLiveData = MutableLiveData() val id: MutableLiveData = MutableLiveData() val selectedSeason: MutableLiveData = MutableLiveData(-2) val seasonSelections: MutableLiveData> = MutableLiveData() + val dubSubSelections: MutableLiveData> get() = _dubSubSelections + private val _dubSubSelections: MutableLiveData> = MutableLiveData() + + val dubSubEpisodes: MutableLiveData>?> get() = _dubSubEpisodes + private val _dubSubEpisodes: MutableLiveData>?> = MutableLiveData() + private val _watchStatus: MutableLiveData = MutableLiveData() val watchStatus: LiveData get() = _watchStatus @@ -110,7 +117,7 @@ class ResultViewModel : ViewModel() { val seasons = seasonTypes.toList().map { it.first }.sortedBy { it } seasonSelections.postValue(seasons) if (seasons.isEmpty()) { // WHAT THE FUCK DID YOU DO????? HOW DID YOU DO THIS - _publicEpisodes.postValue(Resource.Success( ArrayList())) + _publicEpisodes.postValue(Resource.Success(ArrayList())) return } @@ -160,7 +167,7 @@ class ResultViewModel : ViewModel() { selectedRange.postValue(allRange) } - _publicEpisodes.postValue(Resource.Success( currentList)) + _publicEpisodes.postValue(Resource.Success(currentList)) } fun changeSeason(context: Context, selection: Int?) { @@ -171,6 +178,13 @@ class ResultViewModel : ViewModel() { filterEpisodes(context, _episodes.value, null, range) } + fun changeDubStatus(context: Context, status: DubStatus?) { + dubSubEpisodes.value?.get(status)?.let { episodes -> + dubStatus.postValue(status) + updateEpisodes(context, null, episodes, null) + } + } + private fun updateEpisodes(context: Context, localId: Int?, list: List, selection: Int?) { _episodes.postValue(list) val set = HashMap() @@ -237,7 +251,7 @@ class ResultViewModel : ViewModel() { return name } - fun load(context: Context, url: String, apiName: String, showFillers : Boolean) = viewModelScope.launch { + fun load(context: Context, url: String, apiName: String, showFillers: Boolean) = viewModelScope.launch { _resultResponse.postValue(Resource.Loading(url)) _publicEpisodes.postValue(Resource.Loading()) @@ -273,16 +287,22 @@ class ResultViewModel : ViewModel() { when (d) { is AnimeLoadResponse -> { - val isDub = d.dubEpisodes != null && d.dubEpisodes.isNotEmpty() - dubStatus.postValue(if (isDub) DubStatus.Dubbed else DubStatus.Subbed) + //TODO context.getKey<>() isdub - val dataList = (if (isDub) d.dubEpisodes else d.subEpisodes) + val isDub = + d.episodes.containsKey(DubStatus.Dubbed) && !d.episodes[DubStatus.Dubbed].isNullOrEmpty() + val dubStatus = if (isDub) DubStatus.Dubbed else DubStatus.Subbed + _dubStatus.postValue(dubStatus) - val fillerEpisodes = if(showFillers) safeApiCall { getFillerEpisodes(d.name) } else null + _dubSubSelections.postValue(d.episodes.keys) + val fillerEpisodes = if (showFillers) safeApiCall { getFillerEpisodes(d.name) } else null - if (dataList != null) { // TODO dub and sub at the same time + var idIndex = mainId + val res = d.episodes.map { ep -> val episodes = ArrayList() - for ((index, i) in dataList.withIndex()) { + for ((index, i) in ep.value.withIndex()) { + idIndex++ + val episode = i.episode ?: (index + 1) episodes.add( context.buildResultEpisode( @@ -292,17 +312,22 @@ class ResultViewModel : ViewModel() { null, // TODO FIX SEASON i.url, apiName, - (mainId + index + 1), + idIndex, index, i.rating, - i.descript, + i.description, if (fillerEpisodes is Resource.Success) fillerEpisodes.value?.let { it.contains(episode) && it[episode] == true - } - ?: false else false, + } ?: false else false, ) ) } + + Pair(ep.key, episodes) + }.toMap() + + _dubSubEpisodes.postValue(res) + res[dubStatus]?.let { episodes -> updateEpisodes(context, mainId, episodes, -1) } } @@ -366,11 +391,10 @@ class ResultViewModel : ViewModel() { ), -1 ) } - } } else -> { - + // nothing } } } diff --git a/app/src/main/res/layout/fragment_result.xml b/app/src/main/res/layout/fragment_result.xml index b96a817d..0c70464c 100644 --- a/app/src/main/res/layout/fragment_result.xml +++ b/app/src/main/res/layout/fragment_result.xml @@ -431,8 +431,23 @@ android:layout_gravity="center_vertical" android:layout_marginStart="0dp" style="@style/MultiSelectButton" - > - + /> + +